C#, new Bitmap with IntPtr, ArgumentException
I have a very strange issue.
Here is a simplified code of mine to explain :
class Bitmap1
{
public Bitmap nImage;
public IntPtr data;
public Bitmap1()
{
int w = 2450;
int h = 2450;
this.data = Marshal.AllocHGlobal(w*h);
nImage = new Bitmap(w, h, w, PixelFormat.Format8bppIndexed, data);
}
}
When w
and h
are equal to 2448, everything works well if I invocate the constructor.
But when h and w are equal to 2450, I have an ArgumentException
wh开发者_开发技巧ich seems launch by the "new Bitmap(...);"
I can't understand, and the documentation doesn't say there is a limited size for Marshal.AllocHGlobal
.
What's wrong? Are there other ways to do what I want ?
Thank you very much.
stride Type: System.Int32 Integer that specifies the byte offset between the beginning of one scan line and the next. This is usually (but not necessarily) the number of bytes in the pixel format (for example, 2 for 16 bits per pixel) multiplied by the width of the bitmap. The value passed to this parameter must be a multiple of four..
http://msdn.microsoft.com/en-us/library/zy1a2d14.aspx
So you need something like the following:
int w = 2450;
int h = 2450;
int s = 2452;//Next multiple of 4 after w
this.data = Marshal.AllocHGlobal(s*h);
nImage = new Bitmap(w, h, s, PixelFormat.Format8bppIndexed, data);
This means there are 2 bytes between every line that are just padding and not part of the bitmap itself. When doing pointer arithmetic you obviously need to do s*y+x
and not w*y+x
to account for the padding.
Bitmap bmp = new Bitmap("SomeImage");
// Lock the bitmap's bits.
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb);
// Get the address of the first line.
IntPtr ptr = bmpData.Scan0;
// Declare an array to hold the bytes of the bitmap.
int bytes = bmpData.Stride * bmp.Height;
byte[] rgbValues = new byte[bytes];
// Copy the RGB values into the array.
Marshal.Copy(ptr, rgbValues, 0, bytes);
精彩评论