• Welcome to Jose's Read Only Forum 2023.
 

GDI+: Locking Pixel Data for Reading

Started by José Roca, June 22, 2008, 12:49:50 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

José Roca

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
' ========================================================================================