Locking Pixel Data for Writing
The following example creates a
Bitmap object based on a BMP file. The call to the
GdipBitmapLockBits function locks a 50x30 rectangular portion of the bitmap for writing. The locked portion starts at (20, 10); that is, row 10, column 20. One of the arguments passed to
GdipBitmapLockBits is the address of a
BitmapData structure. When
GdipBitmapLockBits returns, the
Scan0 data member of the
BitmapData structure points to a block of memory that represents the pixels in the 50x30 portion of the bitmap. The
Stride data member of the
BitmapData structure holds the byte offset between one scan line and the next scan line in that block of memory.
Scan0 does not point to the actual pixel data of the
Bitmap object; rather, it points to a temporary buffer that represents a portion of the pixel data in the Bitmap. The code writes the value &HFF00FF00 (green) to 1500 locations in the temporary buffer. Later, the call to
GdipBitmapUnlockBits copies those values to the
Bitmap object itself.
Note that pixels is a pointer to a DWORD, so the code must calculate the number of DWORD values that fit in a scan line. Because each DWORD is four bytes, that number is the stride divided by 4.
C++
VOID Example_LockBits2(HDC hdc)
{
Graphics graphics(hdc);
UINT* pixels;
// Create a Bitmap object from a BMP file.
Bitmap bitmap(L"LockBitsTest2.bmp");
// Display the bitmap before locking and altering it.
graphics.DrawImage(&bitmap, 10, 10);
// Lock a 50xs30 rectangular portion of the bitmap for writing.
BitmapData bitmapData;
Rect rect(20, 10, 50, 30);
bitmap.LockBits(
&rect,
ImageLockModeWrite,
PixelFormat32bppARGB,
&bitmapData);
// Write to the temporary buffer provided by LockBits.
pixels = (UINT*)bitmapData.Scan0;
for(UINT row = 0; row < 30; ++row)
{
for(UINT col = 0; col < 50; ++col)
{
pixels[row * bitmapData.Stride / 4 + col] = 0xff00ff00;
}
}
// Commit the changes, and unlock the 50x30 portion of the bitmap.
bitmap.UnlockBits(&bitmapData);
// Display the altered bitmap.
graphics.DrawImage(&bitmap, 150, 10);
}
PowerBASIC
SUB GDIP_LockBits2 (BYVAL hdc AS DWORD)
LOCAL hStatus AS LONG
LOCAL pGraphics AS DWORD
LOCAL pBitmap AS DWORD
LOCAL strFileName AS STRING
LOCAL bmpData AS BITMAPDATA
LOCAL rc AS RECT
LOCAL row AS LONG
LOCAL col AS LONG
LOCAL pPixels AS DWORD PTR
hStatus = GdipCreateFromHDC(hdc, pGraphics)
' // Create a Bitmap object from a BMP file.
strFileName = UCODE$("LockBitsTest2.bmp")
hStatus = GdipCreateBitmapFromFile(STRPTR(strFileName), pBitmap)
' // Display the bitmap before locking and altering it
hStatus = GdipDrawImageI(pGraphics, pBitmap, 10, 10)
' // Lock a 50x30 rectangular portion of the bitmap for writing
SetRect rc, 20, 10, 50, 30
hStatus = GdipBitmapLockBits(pBitmap, rc, %ImageLockModeWrite, %PixelFormat32bppARGB, bmpData)
pPixels = bmpData.Scan0
IF pPixels THEN
FOR row = 0 TO 29
FOR col = 0 TO 49
@pPixels[row * bmpData.Stride / 4 + col] = &HFF00FF00
NEXT
NEXT
END IF
' // Commit the changes and unlock the 50x30 portion of the bitmap
hStatus = GdipBitmapUnlockBits(pBitmap, bmpData)
' // Display the altered image
hStatus = GdipDrawImageI(pGraphics, pBitmap, 150, 10)
' // Cleanup
IF pBitmap THEN GdipDisposeImage(pBitmap)
IF pGraphics THEN GdipDeleteGraphics(pGraphics)
END SUB
(http://www.jose.it-berater.org/captures/GdipBitmapLockBits2.png)