How can I copy pixel data from a negative bitmap?

I was looking for the fastest way to convert Bitmap to 8bpp. I found 2 ways:

1.

public static System.Drawing.Image ConvertTo8bpp(Bitmap oldbmp) { using (var ms = new MemoryStream()) { oldbmp.Save(ms, ImageFormat.Gif); ms.Position = 0; return System.Drawing.Image.FromStream(ms); } } 

2. http://www.wischik.com/lu/programmer/1bpp.html

But: 1. Results with very low quality (poor pallet)

and 2 gives me a bitmap with a negative step when I try to block and copy data to an array of bytes. I get an exception: Attempted to read or write protected memory. This often indicates that another memory is corrupted.

  BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, bmp.PixelFormat); this.stride = bmpData.Stride; this.bytesPerPixel = GetBytesPerPixel(bmp.PixelFormat); int length = bmpData.Stride * bmp.Height; if (this.stride < 0) this.data = new byte[-length]; else this.data = new byte[length]; Marshal.Copy(bmpData.Scan0, data, 0, length); //Unlock the bitmap bmp.UnlockBits(bmpData); 

How can I do 2 gives a positive step? Or how can I copy data using negative step locks?

+4
source share
5 answers

Copy 1 line at a time, calculating the start pointer for the line as ((byte*)scan0 + (y * stride)) . The code will be identical for a positive or negative step.

+4
source

The problem here is that Scan0 indicates the beginning of the first scan line, and not the beginning of the first data byte. In a bottom-up bitmap, the first scan line is Stride bytes from the end of the bitmap data.

When you call Marshal.Copy to copy data from Scan0 , it tries to copy (Height*Stride) bytes, starting at ((Height-1)*Stride) . Clearly, this is about to run off into the weeds.

If you want to copy bitmap data, you need to calculate the start address using Scan0 - (Height-1)*Stride . This will launch you at the beginning of the bitmap data. You can pass this calculated address to Marshal.Copy .

If you want to copy the scan lines in order (that is, from above, further, further, ... below), you need to copy the line at a time: copy Stride bytes from Scan0 , then add Stride (which is negative), copy this line, etc. d. Rick Brewster had the correct answer: fooobar.com/questions/1364252 / ...

+7
source

I don’t know why there is something strange in the bitmap created by the FromHbitmap method, but I know that you can fix it with Bitmap bmpClone = (Bitmap)bmp.Clone(); and make LockBits on bmpClone.

Also, I found that if you use bmp.Clone() , you cannot Dispose () from bmp until you are done with the clone.

It also works and allows you to get rid of the negative image of an image sooner rather than later:

  Bitmap bmp = null; using (Bitmap bmpT = CopyToBpp(bmpO, 1)) { bmp = new Bitmap(bmpT); } 
+4
source

From the C # documentation in BitmapData: The step is the width of one line of pixels (scan line), rounded to a four-byte border. If the step is positive, the bitmap is from top to bottom. If the step is negative, the bitmap is from bottom to top.

+2
source

I assume that the exception you get is related to

 this.data = new byte[-length]; 

And then I try to copy the data into a byte array of negative size (I don’t see how it even compiles in reality ...).

-2
source

All Articles