Help with a bitmap decoder

I am working on a bitmap decoder, but my pixel data processing algorithm seems not quite right:

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 < height) { Byte ReadByte; if (!(Col >= 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; } 

I can only process monochrome bitmaps, and on some parts of the bitmap it handles fine. None of them are compressed, and they are upside down and upside down. I really could help with that.

+4
source share
3 answers
  decimal value = ((bpp*width)/32)/4; int RowSize = (int)Math.Ceiling(value); 

This is not true. Your RowSize variable is actually called a "step". You calculate it as follows:

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

You ignore the step.

Lines of images can be supplemented with additional bytes on the left so that their size is divided by a number, for example (1 = no fill, 2, 4, 8 = default for many images, 16, ...).

In addition, the images can be the rectangle area in the large image, which makes β€œspacing” between the lines in the smaller image even larger (since the step is a larger image step). - In this case, the image may also have an offset for the starting point in the buffer.

Best practice:

 // 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++; } } } } } 
+3
source

I find what I do not understand:

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

RowSize, in my opinion, should be (bpp*width) / 8 + (bpp%8==0?0:1)

0
source

Source: https://habr.com/ru/post/1347452/


All Articles