• Welcome to Powerbasic Museum 2020-B.
 

News:

Forum in repository mode. No new members allowed.

Main Menu

GDI+: Locking Pixel Data for Writing

Started by José Roca, June 22, 2008, 12:52:39 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

José Roca

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