帮助Bitmap解码器

我一直在研究位图解码器,但我处理像素数据的算法似乎不太合适:

public IntPtr ReadPixels(Stream fs, int offset, int width, int height, int bpp) { IntPtr bBits; int pixelCount = bpp * width * height; int Row = 0; decimal value = ((bpp*width)/32)/4; int RowSize = (int)Math.Ceiling(value); int ArraySize = RowSize * Math.Abs(height); int Col = 0; Byte[] BMPData = new Byte[ArraySize]; BinaryReader r = new BinaryReader(fs); r.BaseStream.Seek(offset, SeekOrigin.Begin); while (Row = RowSize)) { ReadByte = r.ReadByte(); BMPData[(Row * RowSize) + Col] = ReadByte; Col += 1; } if (Col >= RowSize) { Col = 0; Row += 1; } } bBits = System.Runtime.InteropServices.Marshal.AllocHGlobal(BMPData.Length); System.Runtime.InteropServices.Marshal.Copy(BMPData, 0, bBits, BMPData.Length); return bBits; } 

我只能处理单色位图,而在某些位图上,部分位图处理得很好。 没有被压缩,它们被颠倒并翻转。 我真的可以在这个方面提供一些帮助。

  decimal value = ((bpp*width)/32)/4; int RowSize = (int)Math.Ceiling(value); 

这是不正确的。 您的RowSize变量实际上称为“stride”。 你像这样计算它:

  int bytes = (width * bitsPerPixel + 7) / 8; int stride = 4 * ((bytes + 3) / 4); 

你无视这一步。

图像行可以用额外的字节填充到左侧,使其大小除以一个数字,例如(1 =无填充,2,4,8 =许多图像的默认值,16,…)。

此外,图像可以是较大图像内的矩形区域,使得较小图像中的线之间的“填充”甚至更大(因为步幅是较大图像的步幅)。 – 在这种情况下,图像也可以在缓冲区中具有其起始点的偏移量。

更好的做法是:

 // Overload this method 3 time for different bit per SUB-pixel values (8, 16, or 32) // = (byte, int, float) // SUB-pixel != pixel (= 1 3 or 4 sub-pixels (grey or RGB or BGR or BGRA or RGBA or ARGB or ABGR) unsafe { byte[] buffer = image.Buffer; int stride = image.buffer.Length / image.PixelHeight; // or int stride = image.LineSize; (or something like that) fixed (float* regionStart = (float*)(void*)buffer) // or byte* or int* depending on datatype { for (int y = 0; y < height; y++) // height in pixels { // float* and float or byte* and byte or int* and int float* currentPos = regionStart + offset / SizeOf(float) + stride / SizeOf(float) * y; for (int x = 0; x < width; x++) // width in pixels { for (int chan = 0; chan < channel; chan++) // 1, 3 or 4 channels { // DO NOT USE DECIMAL - you want accurate image values // with best performance - primative types // not a .NET complex type used for nice looking values for users eg 12.34 // instead use actual sub pixel type (float/int/byte) or double instead! var currentValue = value; currentPos++; } } } } } 

我发现了一些我不理解的东西:

 decimal value = ((bpp*width)/32)/4; int RowSize = (int)Math.Ceiling(value); 

在我看来,RowSize应该是(bpp*width) / 8 + (bpp%8==0?0:1)