// load pixels into an image
this.image = new BufferedImage(this.width,
this.height,
BufferedImage.TYPE_INT_RGB);
// get actual image data for easier pixel loading
byte[] iData = new byte[this.size - 54];
for(int i = 0; i < this.size - 54; i++) {
iData[i] = this.data[i+54];
}
// start from bottom row
for(int y = this.height-1; y >= 0; y--) {
for(int x = 0; x < this.width; x++) {
int index = (this.width*y + x) * 3;
int b = iData[index];
int g = iData[index+1];
int r = iData[index+2];
//System.out.format("R: %s\nG: %s\nB: %s\n\n", r, g, b);
// merge rgb values to single int
int rgb = ((r&0x0ff)<<16)|((g&0x0ff)<<8)|(b&0x0ff);
// build image from bottom up
this.image.setRGB(x, this.height-1-y, rgb);
}
}
我正在从Bitmap读取RGB值。我的iData字节数组是正确的,因为我已经对十六进制编辑器进行了检查。但是,当我运行此循环时,我的输出图像会变形(见图片)。我试图解决这个问题需要花费数小时才能解决这个问题,为什么会发生这种情况呢?
输入图像是加拿大国旗。
输出图片:
答案 0 :(得分:0)
我没有考虑宽度上的零字节填充,公式为
WidthWithPadding = ceiling((w * colorDepth)/ 32)* 32.
答案 1 :(得分:0)
图像通常具有宽度,深度(每像素位数)和步幅。通常,步幅不仅仅是宽度*深度,而是填充一定量(通常用于将每行对齐到16位边界以获得内存访问)。
您的代码似乎没有考虑步幅或任何填充,这解释了您在浏览图像时的偏移。我很惊讶颜色没有被切换(建议填充与像素的大小相同),但那些未定义的值会导致黑色条纹穿过图像。
不应将(this.width*y + x) * 3
乘以获取索引,而应使用(this.stride*y + x) * 3
并使用适当的stride值。 BufferedImage class似乎无法以任何明显的方式提供,因此您需要计算或获取其他内容。
答案 2 :(得分:0)
正在发生的一般问题是你的代码将宽度(行之间的距离,以字节为单位)与宽度(一行中的字节数)混为一谈;在对齐的数据格式中,这些不一定是相同的。这样做的一般结果是得到你所看到的那种倾斜,因为第二行从第一行的最后一个字节开始,第三行从倒数第二个字节开始。第二行,依此类推。
您需要做的第一件事是计算数据的步幅,并将其用作行的倍增因子。这是一个简化的循环,它比在每个像素的基础上更有效:
int stride = (this.width + 3) & ~3; // rounds up to the nearest multiple of 4
for (int y = 0; y < this.height; y++) {
int idx = y*stride;
for (int x = 0; x < this.width; x++) {
int b = iData[idx++];
int g = iData[idx++];
int a = iData[idx++];
// etc.
}
}
请注意,上面的舍入技巧((w + a - 1) & ~(a - 1)
)仅适用于二次幂值;舍入技巧的更一般形式是:
int stride = (width + stride - 1)/stride*stride;
虽然首先找到不是2的幂的对齐是非常罕见的。