.net彩色图像字节对齐

发布时间 2023-03-22 21:13:47作者: C-O-L
public Bitmap CreateBitmap24(byte[] originalImageData, int originalWidth, int originalHeight)
{
    // 计算偏移
    int dataOffset = 0;
    if (0 == (originalWidth * 3) % 4)
    {
        dataOffset = 0;
    }
    else
    {
        dataOffset = 4 - (originalWidth * 3) % 4;
    }

    // 最终生成的位图数据大小
    int bitMapWidth = originalWidth * 3 + dataOffset;
    int bitmapDataSize = bitMapWidth * originalHeight;

    byte[] destImageData = new byte[bitmapDataSize];
    byte[] imageData = new byte[bitmapDataSize];

    if (dataOffset == 0)
    {
        destImageData = originalImageData;
        // 像素颜色转换
        for (int i = 0; i < originalHeight; i++)
        {
            for (int j = 0; j < originalWidth * 3; j += 3)
            {
                imageData[i * bitMapWidth + j + 2] = destImageData[i * bitMapWidth + j];
                imageData[i * bitMapWidth + j + 1] = destImageData[i * bitMapWidth + j + 1];
                imageData[i * bitMapWidth + j] = destImageData[i * bitMapWidth + j + 2];
            }
        }
    }
    else
    {
        for (int i = 0; i < originalHeight; i++)
        {
            for (int j = 0; j < originalWidth * 3; j += 3)
            {
                // 在补齐的时候顺带转换颜色
                destImageData[i * bitMapWidth + j + 2] = originalImageData[i * originalWidth * 3 + j];
                destImageData[i * bitMapWidth + j + 1] = originalImageData[i * originalWidth * 3 + j + 1];
                destImageData[i * bitMapWidth + j] = originalImageData[i * originalWidth * 3 + j + 2];

                imageData = destImageData;
            }
        }
    }

    GCHandle pin = GCHandle.Alloc(data, GCHandleType.Pinned);
    var bmp = new Bitmap(originalWidth, originalHeight,
                            (originalWidth * 3 + 3) / 4 * 4,
                            PixelFormat.Format24bppRgb,
                            Marshal.UnsafeAddrOfPinnedArrayElement(imageData, 0));
    bmp = (Bitmap)bmp.Clone();  // workaround the requirement that the memory address stay valid
                                // the clone step can also crop and/or change PixelFormat, if desired
    pin.Free();
    
    return bmp;
}