Locking Pixel Data for Reading
The following console application creates a
Bitmap object based on a BMP file. The call to the
GdipBitmapLockBits function locks a 5x3 rectangular portion of the bitmap for reading. The locked portion starts at (20, 30); that is, row 30, 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 holds the values of the pixels in the 5x3 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.
The nested loops display the hexadecimal values of the fifteen retrieved pixels. 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.
The code below, along with a particular file,
LockBitsTest1.bmp, produces the following output:
The stride is 460
FFFF0000
FFFF0000
FFFF0000
FFFF0000
--------
FF0000FF
FF0000FF
FF0000FF
FF0000FF
--------
FF0000FF
FF0000FF
FF0000FF
FF0000FF
C++
#include <windows.h>
#include <gdiplus.h>
#include <stdio.h>
using namespace Gdiplus;
INT main()
{
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
Bitmap* bitmap = new Bitmap(L"LockBitsTest1.bmp");
BitmapData* bitmapData = new BitmapData;
Rect rect(20, 30, 5, 3);
// Lock a 5x3 rectangular portion of the bitmap for reading.
bitmap->LockBits(
&rect,
ImageLockModeRead,
PixelFormat32bppARGB,
bitmapData);
printf("The stride is %d.\n\n", bitmapData->Stride);
// Display the hexadecimal value of each pixel in the 5x3 rectangle.
UINT* pixels = (UINT*)bitmapData->Scan0;
for(UINT row = 0; row < 3; ++row)
{
for(UINT col = 0; col < 5; ++col)
{
printf("%x\n", pixels[row * bitmapData->Stride / 4 + col]);
}
printf("- - - - - - - - - - \n");
}
bitmap->UnlockBits(bitmapData);
delete bitmapData;
delete bitmap;
GdiplusShutdown(gdiplusToken);
return 0;
}
PowerBASIC
#COMPILE EXE
#DIM ALL
#INCLUDE "GDIPLUS.INC"
' ========================================================================================
' Main
' ========================================================================================
FUNCTION PBMAIN
LOCAL hStatus AS LONG
LOCAL token AS DWORD
LOCAL StartupInput AS GdiplusStartupInput
LOCAL strFileName AS STRING
LOCAL pBitmap AS DWORD
LOCAL bmpData AS BITMAPDATA
LOCAL rc AS RECT
LOCAL row AS LONG
LOCAL col AS LONG
LOCAL pPixels AS DWORD PTR
' // Initialize GDI+
StartupInput.GdiplusVersion = 1
hStatus = GdiplusStartup(token, StartupInput, BYVAL %NULL)
IF hStatus <> %StatusOk THEN
PRINT "Unable to initialize GDI+"
EXIT FUNCTION
END IF
' // Create a bitmap object
strFileName = UCODE$("LockBitsTest1.bmp")
hStatus = GdipCreateBitmapFromFile(STRPTR(strFileName), pBitmap)
IF hStatus <> %StatusOk THEN
PRINT "GdipCreateBitmapFromFile failed - Status = " & STR$(hStatus)
GOTO Terminate
END IF
' // Lock a 5 x 3 rectangular portion of the bitmap for reading
SetRect rc, 20, 32, 5, 3
hStatus = GdipBitmapLockBits(pBitmap, rc, %ImageLockModeRead, %PixelFormat32bppARGB, bmpData)
IF hStatus <> %StatusOk THEN
PRINT "GdipBitmapLockBits failed - Status = " & STR$(hStatus)
GOTO Terminate
END IF
PRINT "The stride is " & STR$(bmpData.stride)
PRINT
' // Display the hexadecimal value of each pixel in the 5x3 rectangle.
pPixels = bmpData.Scan0
IF pPixels = %NULL THEN GOTO Terminate
FOR row = 0 TO 2
FOR col = 0 TO 4
PRINT HEX$(@pPixels[row * bmpData.stride / 4 + col])
NEXT
PRINT "--------"
NEXT
Terminate:
' Unlock the bits
hStatus = GdipBitmapUnlockBits(pBitmap, bmpData)
' // Cleanup
IF pBitmap THEN hStatus = GdipDisposeImage(pBitmap)
' // Shutdown GDI+
GdiplusShutdown token
WAITKEY$
END FUNCTION
' ========================================================================================