我正在使用PPM
图像查看器。
我的PPM
文件看起来像这样,并在注释中解释了它的工作原理。
P3
3 2 #widht and heigth
255 #depth, 24bpp in this case
255 0 0 0 255 0 0 0 255 #here, each pixel have 3 values RGB. We have 6 pixels
255 255 0 255 255 255 0 0 0
我正在这样读取此文件:通过此代码作为byte array
:
var imageWidth = imageStream[1]; // 3
var imageHeight = imageStream[2]; // 2
int j = 0;
var pixels = new byte[imageWidth * imageHeight * 3]; // multiply by 3 channels, R, G, B
for (int i = 4; i < imageStream.Length; i++) //pixel values starts from index 4
{
pixels[j] = (byte)imageStream[i]; // imageStream is array of ints
j++;
}
var bitmap = new Bitmap(imageWidth, imageHeight, PixelFormat.Format24bppRgb);
var bitmapData = bitmap.LockBits(
new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb);
Marshal.Copy(pixels, 0, bitmapData.Scan0, pixels.Length);
bitmap.UnlockBits(bitmapData);
return bitmap;
从此代码中,我得到计数为pixels
的18
数组。值看起来像这样:
255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0
应该如此。 IrfanView
像这样显示此图像:
但是我的程序在将位图保存到文件后执行了类似的操作:
为什么我的代码输出的颜色错误?
至少有两件事是错误的,
Format24bppRgb
表示字顺序中的RGB,字节顺序为B G R。Format24bppRgb
位图,在每行像素的末尾可能会有一些填充。考虑到bitmapData.Stride
可以解决此问题。Marshal.Copy
无法解决字节交换问题,但是可以手动完成,例如(未测试):
unsafe
{
int j = 0;
for (int y = 0; y < imageHeight; y++)
{
byte* ptr = (byte*)bitmapData.Scan0 + bitmapData.Stride * y;
for (int x = 0; x < imageWidth; x++)
{
// R
ptr[2] = pixels[j];
// G
ptr[1] = pixels[j + 1];
// B
ptr[0] = pixels[j + 2];
ptr += 3;
j += 3;
}
}
}