元帅的输出错误。复制到位图

问题描述 投票:0回答:1

我正在使用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;

从此代码中,我得到计数​​为pixels18数组。值看起来像这样:

255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0

应该如此。 IrfanView像这样显示此图像:

enter image description here

但是我的程序在将位图保存到文件后执行了类似的操作:

enter image description here

为什么我的代码输出的颜色错误?

c# image marshalling
1个回答
0
投票

至少有两件事是错误的,

  • [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;
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.