I was looking for the fastest way to convert a 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 in a very low quality result (bad pallet)
and 2 gives me a Bitmap with negative stride, when I try to lockbits and copy the data to a byte array I get an exception: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
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 make 2 gives a positive stride? Or how can I copy data using lockbits of a negative stride??
Best Answer
The problem here is that
Scan0
points to the beginning of the first scan line, not the beginning of the first byte of data. In a bottom-up bitmap, the first scan line isStride
bytes from the end of the bitmap data.When you call
Marshal.Copy
to copy the data fromScan0
, it tries to copy(Height*Stride)
bytes, starting from position((Height-1)*Stride)
. Clearly, that's going to run off into the weeds.If you just want to copy the bitmap data, you have to calculate the starting address with
Scan0 - (Height-1)*Stride
. That will start you at the beginning of the bitmap data. You can pass that computed address toMarshal.Copy
.If you want to copy the scan lines in order (i.e. top, next, next, ... bottom), then you have to copy a line at a time: copy
Stride
bytes fromScan0
, then addStride
(which is negative), copy that line, etc. Rick Brewster had the right answer there: https://stackoverflow.com/a/10360753/56778