FIX: Unhandled Exception Occurs When You Create a Bitmap with a Negative Stride (317309)
The information in this article applies to:
- Microsoft GDI+ 1.0
- Microsoft .NET Framework 1.0
- Microsoft Windows XP Professional
- the operating system: Microsoft Windows XP 64-Bit Edition
This article was previously published under Q317309 This article references the following .NET Framework Class
Library namespace:
SYMPTOMS When you call the following GDI+ Bitmap constructor
public Bitmap(int width,int height,int stride,PixelFormat format,IntPtr scan0);
a negative stride parameter specifies that the data pointed to by the scan0 parameter is data to a bottom-up bitmap. When you
create a new GDI+ Bitmap object with bottom-up data, an unhandled exception error may
occur, or the bitmap bits may be drawn incorrectly. CAUSE This behavior occurs if the scan0 parameter points to the start of the buffer that contains the
bitmap bits, rather than to the start of the first scan line of the bitmap
data. RESOLUTION To resolve this issue, move the address pointed to by scan0 from the start of the bitmap buffer to the beginning of the last
row of pixels in the buffer, which is the topmost scan line seen when the image
is drawn. STATUS This
bug was corrected in Microsoft .NET Framework 1.1.
MORE INFORMATION The documentation of this Bitmap constructor defines scan0 as the address of a stream of pixel data. The scan0 parameter should point to the start of the first scan line of the
bitmap data. It is only with top-down bitmaps that the start of the first scan
line matches the start of the bitmap buffer. After you have created the bitmap
with this Bitmap constructor, the data pointed to by the buffer that you allocated
must remain valid throughout the lifetime of the Bitmap object. The following code defines data for two
bitmaps. The first buffer defined is a top-down bitmap buffer, and the second
is a bottom-up buffer. When drawn, these bitmaps look alike because they are
defined with a positive and negative stride, respectively. The first bitmap is
created with top-down bitmap data. Therefore, the pointer pointed to by scan0 is defined as follows:
void* p = ptrTopDown
The second bitmap is created with bottom-up bitmap data, and therefore
the pointer pointed to by scan0 points to the beginning of the last row of pixels in the buffer,
as follows:
void* p = &ptrBottomUp[desiredRow * scanlineWidth]
This C# code draws the two images side by side to demonstrate how to
create two identical bitmaps, one with top-down data and the other with
bottom-up data. To compile this code, you must specify the /unsafe compiler option, as follows:
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
// Using pointers, so we must use the "unsafe" keyword.
unsafe
{
// This data defines the top-down bitmap.
byte[] ptrTopDown =
{255,255,255,255,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
255,255,255,255,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 };
// This data defines the same bitmap, only with bottom-up data.
byte[] ptrBottomUp =
{255,255,255,255,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
255,255,255,255,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 };
int xStart = 0;
int yStart = 0;
int width = 4;
int height = 4;
int bytesPerPixel = 4;
int scanlineWidth = bytesPerPixel * width;
// We must obtain a pointer to the first scanline of the top-down data.
// This happens to be the start of the buffer.
fixed (void* p = ptrTopDown)
{
IntPtr ptr = new IntPtr(p);
PixelFormat format = PixelFormat.Format32bppRgb;
Bitmap bitmapImage = new Bitmap(width,height,scanlineWidth,format,ptr);
Rectangle destRect1 = new Rectangle(0, 0, width, height);
GraphicsUnit units = GraphicsUnit.Pixel;
e.Graphics.DrawImage(bitmapImage, destRect1, xStart, yStart, width, height, units);
}
//Because this is bottom-up bitmap data, we must obtain a pointer to
//the beginning of the last row of pixels in the buffer, which is the topmost scanline
//seen when the image is drawn.
int desiredRow = 3;
// Zero-based desired row. We want the fourth
// row from the top, because that is the start of the
// last row of pixels in the buffer.
fixed (void* p = &ptrBottomUp[desiredRow * scanlineWidth])
{
IntPtr ptr = new IntPtr(p);
PixelFormat format = PixelFormat.Format32bppRgb;
Bitmap bitmapImage = new Bitmap(width,height,-scanlineWidth,format,ptr);
Rectangle destRect1 = new Rectangle(10, 0, width, height);
GraphicsUnit units = GraphicsUnit.Pixel;
e.Graphics.DrawImage(bitmapImage, destRect1, xStart, yStart, width, height, units);
}
}
}
Modification Type: | Minor | Last Reviewed: | 5/3/2006 |
---|
Keywords: | kbDSWGDI2003Swept kbfix kbgdipimaging kbprb KB317309 kbAudDeveloper |
---|
|