p5.js问题:复制的图像为何被压缩且重复?
像素复制后Buffer显示异常问题
我正在为学校作业做像素数据处理,需要把一张图像的像素数据复制到buffer里,但buffer显示出大幅压缩且包含两张相同图像的异常(左侧是原图像,右侧是buffer,灰色区域是背景):

控制台确认过,buffer和原图像的分辨率都是512x512,但显示还是异常。我用的复制代码如下:
imgs[0].loadPixels(); avgImg.loadPixels(); for(var y = 0; y < imgs[0].height; ++y) { for(var x = 0; x < imgs[0].width; ++x) { var index = (y * imgs[0].width + x) * 4; avgImg.pixels[index] = imgs[0].pixels[index]; avgImg.pixels[index + 1] = imgs[0].pixels[index + 1] avgImg.pixels[index + 2] = imgs[0].pixels[index + 2] avgImg.pixels[index + 3] = imgs[0].pixels[index + 3] } } avgImg.updatePixels(); image(avgImg, avgImg.width, 0);
请问哪里操作出错了?
问题原因及解决方法
这种异常是像素数组的行对齐(stride)不匹配导致的。在Processing/p5.js这类框架中,像素数组的实际长度可能因底层画布的内存对齐要求,比width*height*4更大——比如部分环境会把每行像素的字节数向上取整到特定倍数,此时直接用原图像的width计算目标图像的像素索引,会导致目标图像每行像素提前结束,后续像素挤入下一行,最终出现压缩、重复的显示问题。
解决办法:
方法一:用内置
copy()方法替代手动循环(最简便可靠)
若只是单纯复制像素,框架内置的copy()会自动处理行对齐问题,无需手动遍历:imgs[0].loadPixels(); avgImg.loadPixels(); // 复制原图像全部像素到avgImg imgs[0].copy(0, 0, imgs[0].width, imgs[0].height, 0, 0, avgImg.width, avgImg.height); avgImg.updatePixels(); image(avgImg, avgImg.width, 0);方法二:手动循环时区分原图像与目标图像的width
若必须手动处理像素,计算目标图像的索引时要使用自身的width,而非原图像的width:imgs[0].loadPixels(); avgImg.loadPixels(); for(var y = 0; y < imgs[0].height; ++y) { for(var x = 0; x < imgs[0].width; ++x) { // 原图像索引用原图像width计算 var srcIndex = (y * imgs[0].width + x) * 4; // 目标图像索引用目标图像width计算 var dstIndex = (y * avgImg.width + x) * 4; avgImg.pixels[dstIndex] = imgs[0].pixels[srcIndex]; avgImg.pixels[dstIndex + 1] = imgs[0].pixels[srcIndex + 1]; avgImg.pixels[dstIndex + 2] = imgs[0].pixels[srcIndex + 2]; avgImg.pixels[dstIndex + 3] = imgs[0].pixels[srcIndex + 3]; } } avgImg.updatePixels(); image(avgImg, avgImg.width, 0);
另外需要确认avgImg的创建方式正确——比如在p5.js中,需通过createGraphics(512, 512)创建,避免因创建方式错误导致实际画布尺寸与声明的width/height不符。
内容的提问来源于stack exchange,提问作者Ryolu
相关产品推荐
相关产品推荐

