Jump to content
Sign in to follow this  
weaponx

_GDIPlus_BitmapLockBits

Recommended Posts

weaponx

I'm trying to use this function with AutoIt but I'm not sure if it can handle the return type properly.

Here is the original code:

http://msdn.microsoft.com/en-us/library/ms536298(VS.85).aspx

#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;
}

Here is my attempt:

#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <GUIConstantsEx.au3>

Global Const $filename = "spectrum.bmp"
Global Const $GUI_Width = 100
Global Const $GUI_Height = 100

$hwnd = GUICreate("GUI", $GUI_Width, $GUI_Height)
GUISetState()

_GDIPlus_Startup()
$image = _GDIPlus_ImageLoadFromFile($filename)
$imagegraphics = _GDIPlus_ImageGetGraphicsContext($image)
$graphics = _GDIPlus_GraphicsCreateFromHWND($hwnd)

;Get handle to a Bitmap object
$backgroundbitmap = _GDIPlus_BitmapCreateFromGraphics($GUI_Width, $GUI_Height, $graphics)
$background = _GDIPlus_ImageGetGraphicsContext($backgroundbitmap)

;Lock bits (all pixels) for reading
$BitmapData = _GDIPlus_BitmapLockBits($backgroundbitmap, 0,0,$GUI_Width, $GUI_Height, $GDIP_ILMREAD,$GDIP_PXF24RGB)

$Stride = DllStructGetData($BitmapData,"Stride")
ConsoleWrite("Bitmap Stride: " & $Stride & @CRLF)

$Scan0 = DllStructGetData($BitmapData,"Scan0")
ConsoleWrite("Bitmap Scan0: " & $Scan0 & @CRLF)

$test = DllStructCreate ('uint_ptr pixels[' & $GUI_Width * $GUI_Height * 24 / 8 & ']', $Scan0)

$sHex = DllStructGetData($test, "pixels", 1)
ConsoleWrite(@ERROR & @CRLF)
ConsoleWrite($sHex & @CRLF)


;Unlock bits (all pixels)
_GDIPlus_BitmapUnlockBits($backgroundbitmap, $BitmapData)

;Create image buffer
;$backbufferbitmap = _GDIPlus_BitmapCreateFromGraphics($GUI_Width, $GUI_Height, $graphics)
;$backbuffer = _GDIPlus_ImageGetGraphicsContext($backbufferbitmap)

;Draw the picture into the GUI - it will stretch to fit the GUI
_GDIPlus_GraphicsDrawImageRect($graphics, $image, 0, 0, $GUI_Width, $GUI_Height)

While 1
    $msg = GUIGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
WEnd

_GDIPlus_GraphicsDispose($background)
;_WinAPI_DeleteObject($backbufferbitmap)
_GDIPlus_GraphicsDispose($imagegraphics)
_GDIPlus_ImageDispose($image)
;_GDIPlus_GraphicsDispose($backbuffer)
;_WinAPI_DeleteObject($backbufferbitmap)
_GDIPlus_GraphicsDispose($graphics)
_GDIPlus_Shutdown()

Scan0 returns a pointer 0x017853F8 but I don't think i'm using it correctly.

I see a lot of references to CreateDIBSection but that is regular GDI, I would like to see this work with GDI+.

Share this post


Link to post
Share on other sites
weaponx

Second failed attempt (now with more useless comments!):

#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <GUIConstantsEx.au3>

Global Const $filename = "spectrum.bmp"
Global Const $GUI_Width = 100
Global Const $GUI_Height = 100

$hwnd = GUICreate("GUI", $GUI_Width, $GUI_Height)
GUISetState()

_GDIPlus_Startup()
$image = _GDIPlus_ImageLoadFromFile($filename)
$imagegraphics = _GDIPlus_ImageGetGraphicsContext($image)
$graphics = _GDIPlus_GraphicsCreateFromHWND($hwnd)

;Get handle to a Bitmap object
$backgroundbitmap = _GDIPlus_BitmapCreateFromGraphics($GUI_Width, $GUI_Height, $graphics)
;$background = _GDIPlus_ImageGetGraphicsContext($backgroundbitmap)

;Draw the picture into the GUI - it will stretch to fit the GUI
_GDIPlus_GraphicsDrawImageRect($graphics, $image, 0, 0, $GUI_Width, $GUI_Height)

;Lock bits (all pixels) for reading
$BitmapData = _GDIPlus_BitmapLockBits($backgroundbitmap, 0,0,$GUI_Width, $GUI_Height, $GDIP_ILMREAD,$GDIP_PXF24RGB)

;Stride - Offset, in bytes, between consecutive scan lines of the bitmap. If the stride is positive, the bitmap is top-down. If the stride is negative, the bitmap is bottom-up.
$Stride = DllStructGetData($BitmapData,"Stride")
ConsoleWrite("Bitmap Stride: " & $Stride & @CRLF)

;Image width - Number of pixels in one scan line of the bitmap.
$Width = DllStructGetData($BitmapData,"Width")
ConsoleWrite("Bitmap Width: " & $Width & @CRLF)

;Image height - Number of scan lines in the bitmap.
$Height = DllStructGetData($BitmapData,"Height")
ConsoleWrite("Bitmap Height: " & $Height & @CRLF)

;Pixel format - Integer that specifies the pixel format of the bitmap
$PixelFormat = DllStructGetData($BitmapData,"PixelFormat")
ConsoleWrite("Bitmap PixelFormat: " & $PixelFormat & @CRLF)

;Scan0 - Pointer to the first (index 0) scan line of the bitmap.
$Scan0 = DllStructGetData($BitmapData,"Scan0")
ConsoleWrite("Bitmap Scan0: " & $Scan0 & @CRLF)

$Pixels = DllStructCreate ('uint_ptr pixels[' & $width * $height * $Stride / 4 & ']', $Scan0)
ConsoleWrite("DllStructCreate @ERROR: " & @ERROR & @CRLF)

;DllStructSetData($Pixels,"pixels",$Scan0)
;ConsoleWrite("DllStructSetData @ERROR: " & @ERROR & @CRLF)
   
For $Row = 0 to $Height
    For $Col = 0 to $Width
        
        $element = $row * $Stride / 4 + $col
        ConsoleWrite("Element: " & $element & @CRLF)
        
        $sHex = DllStructGetData($Pixels, "pixels", $element)
        If @ERROR Then
            ConsoleWrite("@ERROR: " & @ERROR & @CRLF)
        Else
            ConsoleWrite(Hex($sHex) & @CRLF)
        EndIf
    Next
Next

;Unlock bits (all pixels)
_GDIPlus_BitmapUnlockBits($backgroundbitmap, $BitmapData)

While 1
    $msg = GUIGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
WEnd

;_GDIPlus_GraphicsDispose($background)
_GDIPlus_GraphicsDispose($imagegraphics)
_GDIPlus_ImageDispose($image)
_GDIPlus_GraphicsDispose($graphics)
_GDIPlus_Shutdown()

Share this post


Link to post
Share on other sites
ProgAndy

i rewrote it again from http://www.forum.it-berater.org/index.php?...page;topic=31.0 and it workes:

#include <GDIPlus.au3>

Local $hStatus; as LONG
Local $token; as DWORD
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
_GDIPlus_Startup()

;~    ' // Create a bitmap object
$strFileName = "D:\Test.bmp"

$pBitmap = _GDIPlus_ImageLoadFromFile($strFileName)


;~    ' // Lock a 5 x 3 rectangular portion of the bitmap for reading
;~    SetRect rc, 20, 32, 5, 3
$BitmapData = _GDIPlus_BitmapLockBits($pBitmap, 20, 23, 5, 3, $GDIP_ILMREAD, $GDIP_PXF32ARGB)

;Stride - Offset, in bytes, between consecutive scan lines of the bitmap. If the stride is positive, the bitmap is top-down. If the stride is negative, the bitmap is bottom-up.
$Stride = DllStructGetData($BitmapData, "Stride")
ConsoleWrite("Bitmap Stride: " & $Stride & @CRLF)

;Image width - Number of pixels in one scan line of the bitmap.
$Width = DllStructGetData($BitmapData, "Width")
ConsoleWrite("Bitmap Width: " & $Width & @CRLF)

;Image height - Number of scan lines in the bitmap.
$Height = DllStructGetData($BitmapData, "Height")
ConsoleWrite("Bitmap Height: " & $Height & @CRLF)

;Pixel format - Integer that specifies the pixel format of the bitmap
$PixelFormat = DllStructGetData($BitmapData, "PixelFormat")
ConsoleWrite("Bitmap PixelFormat: " & $PixelFormat & @CRLF)

;Scan0 - Pointer to the first (index 0) scan line of the bitmap.
$Scan0 = DllStructGetData($BitmapData, "Scan0")
ConsoleWrite("Bitmap Scan0: " & $Scan0 & @CRLF)
$pPixels = $Scan0
;~    ' // Display the hexadecimal value of each pixel in the 5x3 rectangle.
$pPixels = $Scan0
If $pPixels = 0x000000 Then Exit

For $row = 0 To $Height - 1
    For $col = 0 To $Width - 1
        $pixel = DllStructCreate("dword", $pPixels + $row * $Stride / 4 + $col)
        ConsoleWrite(Hex(DllStructGetData($pixel, 1)) & @CRLF)

    Next
    ConsoleWrite("-------" & @CRLF)
Next

Func OnAutoItExit()
;~    ' Unlock the bits
    _GDIPlus_BitmapUnlockBits($pBitmap, $BitmapData)

;~    ' // Cleanup
    If $pBitmap Then _GDIPlus_ImageDispose($pBitmap)

;~    ' // Shutdown GDI+
    _GDIPlus_Shutdown()
EndFunc   ;==>OnAutoItExit

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites
weaponx

Very nice, and very close! Unfortunately the hex codes appear to be offset. Here is my output:

;Should return 5 horizontal pixels(all the same)

$BitmapData = _GDIPlus_BitmapLockBits($pBitmap, 0, 0, 5, 1, $GDIP_ILMREAD, $GDIP_PXF24RGB)

54009E54
 9E54009E
 009E5400
 54009E54
9E54009E

Should be:

009E54
009E54
009E54
 009E54
 009E54

-or-

ff009E54
 ff009E54
ff009E54
 ff009E54
 ff009E54

Test image

NOTE:

Also the help file says the parameters for are absolute rather than relative, so to get a 5x3 area you would have to add 5 to the left and 3 to the top:

$iLeft X coordinate of the upper-left corner of the rectangle to lock

$iTop Y coordinate of the upper-left corner of the rectangle to lock

$iRight X coordinate of the lower-right corner of the rectangle to lock

$iBottom Y coordinate of the lower-right corner of the rectangle to lock

Edited by weaponx

Share this post


Link to post
Share on other sites
ProgAndy

U use $GDIP_PXF24RGB

but the code is for $GDIP_PXF24ARGB

where 4 bytes are used, whereas the other uses just 3 bytes, i think.

//Edit: No even with ARGB, it doesn't fit muttley

Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites
weaponx

U use $GDIP_PXF24RGB

but the code is for $GDIP_PXF24ARGB

where 4 bytes are used, whereas the other uses just 3 bytes, i think.

These are our options:

$GDIP_PXF01INDEXED - 1 bpp, indexed
 $GDIP_PXF04INDEXED - 4 bpp,  indexed
 $GDIP_PXF08INDEXED - 8 bpp, indexed
 $GDIP_PXF16GRAYSCALE - 16 bpp,  grayscale
 $GDIP_PXF16RGB555 - 16 bpp; 5 bits for each  RGB
 $GDIP_PXF16RGB565 - 16 bpp; 5 bits red, 6 bits green, and 5 bits  blue
 $GDIP_PXF16ARGB1555 - 16 bpp; 1 bit for alpha and 5 bits for each RGB  component
 $GDIP_PXF24RGB - 24 bpp; 8 bits for each RGB
 $GDIP_PXF32RGB - 32  bpp; 8 bits for each RGB. No alpha.
 $GDIP_PXF32ARGB - 32 bpp; 8 bits for each  RGB and alpha
 $GDIP_PXF32PARGB - 32 bpp; 8 bits for each RGB and alpha,  pre-mulitiplied

My test image is 24 bit.

$GDIP_PXF24RGB:

54009E54
9E54009E
009E5400
54009E54
9E54009E

$GDIP_PXF32RGB

FF009E54
54FF009E
9E54FF00
009E54FF
FF009E54
Edited by weaponx

Share this post


Link to post
Share on other sites
weaponx

I got it working like this:

$BitmapData = _GDIPlus_BitmapLockBits($pBitmap, 0, 0, 5, 1, $GDIP_ILMREAD, $GDIP_PXF32RGB)

$pixel = DllStructCreate("dword", $Scan0 + $row * $Stride / 4 + ($col*4))

I was just experimenting and it came out correct:

FF009E54
 FF009E54
 FF009E54
 FF009E54
 FF009E54

EDIT: I was wrong, I tried using a 1x5 area and it gives me:

FF009E54
-------
FF009E54
-------
FF009E54
-------
FF009E54
-------
FF07A053
-------

Should be:

FF009E54
-------
FF07a053
-------
FF10a352
-------
FF1ba750
-------
FF27ac4e
-------
Edited by weaponx

Share this post


Link to post
Share on other sites
weaponx

Got it! Thanks a lot ProgAndy.

#include <GDIPlus.au3>

;Local $hStatus; as LONG
;Local $token; as DWORD
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
_GDIPlus_Startup()

;~    ' // Create a bitmap object
$strFileName = "spectrum.bmp"

$pBitmap = _GDIPlus_ImageLoadFromFile($strFileName)

;~    ' // Lock a 5 x 3 rectangular portion of the bitmap for reading
;~    SetRect rc, 20, 32, 5, 3
$BitmapData = _GDIPlus_BitmapLockBits($pBitmap, 0, 0, 3, 5, $GDIP_ILMREAD, $GDIP_PXF32RGB)

;Stride - Offset, in bytes, between consecutive scan lines of the bitmap. If the stride is positive, the bitmap is top-down. If the stride is negative, the bitmap is bottom-up.
$Stride = DllStructGetData($BitmapData, "Stride")
ConsoleWrite("Bitmap Stride: " & $Stride & @CRLF)

;Image width - Number of pixels in one scan line of the bitmap.
$Width = DllStructGetData($BitmapData, "Width")
ConsoleWrite("Bitmap Width: " & $Width & @CRLF)

;Image height - Number of scan lines in the bitmap.
$Height = DllStructGetData($BitmapData, "Height")
ConsoleWrite("Bitmap Height: " & $Height & @CRLF)

;Pixel format - Integer that specifies the pixel format of the bitmap
$PixelFormat = DllStructGetData($BitmapData, "PixelFormat")
ConsoleWrite("Bitmap PixelFormat: " & $PixelFormat & @CRLF)

;Scan0 - Pointer to the first (index 0) scan line of the bitmap.
$Scan0 = DllStructGetData($BitmapData, "Scan0")
ConsoleWrite("Bitmap Scan0: " & $Scan0 & @CRLF)
;$pPixels = $Scan0
;If $pPixels = 0x000000 Then Exit

For $row = 0 To $Height - 1
    For $col = 0 To $Width - 1
        $pixel = DllStructCreate("dword", $Scan0 + $row * $Stride + $col*4)
        ConsoleWrite(Hex(DllStructGetData($pixel, 1)) & @CRLF)
    Next
    ConsoleWrite("-------" & @CRLF)
Next

Func OnAutoItExit()
;~    ' Unlock the bits
    _GDIPlus_BitmapUnlockBits($pBitmap, $BitmapData)

;~    ' // Cleanup
    If $pBitmap Then _GDIPlus_ImageDispose($pBitmap)

;~    ' // Shutdown GDI+
    _GDIPlus_Shutdown()
EndFunc   ;==>OnAutoItExit

Share this post


Link to post
Share on other sites
ProgAndy

Yes. Tried it with one of my pictures and works too muttley No it wotks great !

And now, when I see the solution, it it is clear to me, why it didn't work...

one pixel is 4bytes wide, but the ointer was set forward only one byte :) Now you changed it to 4 bytes and it works .

Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites
weaponx

This is so much faster than using GetPixel for a large area.

100x100 bitmap @ 24 bit:

GetPixel

= 2356 ms

_GDIPlus_BitmapLockBits

= 114.84 ms

Edited by weaponx

Share this post


Link to post
Share on other sites
Malkey

This is so much faster than using GetPixel for a large area.

100x100 bitmap @ 24 bit:

GetPixel

= 2356 ms

_GDIPlus_BitmapLockBits

= 114.84 ms

Having succeeded in speeding up Get Pixels for a large area, it would be really good to do the same for SetPixel for a large area.

As this seems to be a logical extension of this thread, I have posted here. I don't think it need a separate new post.

This is what I am trying for write pixel

With the existing script as posted

1. lockbits

2. When getting existing pixels reduce Alpha channel to 00, and save to array

3. unlock bits

4. lockbits in write mode [$BitmapData = _GDIPlus_BitmapLockBits($pBitmap, 0, 0, 2,3, $GDIP_ILMWRITE, $GDIP_PXF32RGB) ]

5 Write array to bitmap

6 unlock bits

7 Get magnify glass to check if top left pixels of newly created bmp are transparent.

The pixel data appears ok.

The modified pixels are not being written to the bitmap.

Any help / direction would be appreciated.

#include <GDIPlus.au3>

Local $strFileName; as STRING
Local $pBitmap; as DWORD
Local $pPixels; as DWORD PTR
Local $res

;~    ' // Initialize GDI+
;~    StartupInput.GdiplusVersion = 1
_GDIPlus_Startup()

;~    ' // Create a bitmap object
$strFileName = "C:\Documents and Settings\mc.MAL\Desktop\spectrum.bmp"

$pBitmap = _GDIPlus_ImageLoadFromFile($strFileName)

;~    ' // Lock a 5 x 3 rectangular portion of the bitmap for reading
;~    SetRect rc, 20, 32, 5, 3
$BitmapData = _GDIPlus_BitmapLockBits($pBitmap, 0, 0, 2, 3, $GDIP_ILMREAD, $GDIP_PXF32RGB)

;Stride - Offset, in bytes, between consecutive scan lines of the bitmap. If the stride is positive, the bitmap is top-down. If the stride is negative, the bitmap is bottom-up.
$Stride = DllStructGetData($BitmapData, "Stride")
ConsoleWrite("Bitmap Stride: " & $Stride & @CRLF)

;Image width - Number of pixels in one scan line of the bitmap.
$Width = DllStructGetData($BitmapData, "Width")
ConsoleWrite("Bitmap Width: " & $Width & @CRLF)

;Image height - Number of scan lines in the bitmap.
$Height = DllStructGetData($BitmapData, "Height")
ConsoleWrite("Bitmap Height: " & $Height & @CRLF)

;Pixel format - Integer that specifies the pixel format of the bitmap
$PixelFormat = DllStructGetData($BitmapData, "PixelFormat")
ConsoleWrite("Bitmap PixelFormat: " & $PixelFormat & @CRLF)

;Scan0 - Pointer to the first (index 0) scan line of the bitmap.
$Scan0 = DllStructGetData($BitmapData, "Scan0")
ConsoleWrite("Bitmap Scan0: " & $Scan0 & @CRLF)

dim $aData[$Width][$Height]
For $row = 0 To $Height - 1
    For $col = 0 To $Width - 1
        $pixel = DllStructCreate("dword", $Scan0 + $row * $Stride + $col*4)
        $aData[$col][$row] = "0x" & hex(BitAND((DllStructGetData($pixel, 1)),0x00FFFFFF))
        ConsoleWrite(Hex(DllStructGetData($pixel, 1)) & @CRLF)
        $res &= $aData[$col][$row] & " "
    Next
    ConsoleWrite("-------" & @CRLF)
    $res &= @CRLF
Next
ConsoleWrite($res  & @CRLF)


$res = "-------" & @CRLF

_GDIPlus_BitmapUnlockBits($pBitmap, $BitmapData)

$BitmapData = _GDIPlus_BitmapLockBits($pBitmap, 0, 0, 2, 3, $GDIP_ILMWRITE, $GDIP_PXF32RGB)

For $row = 0 To $Height - 1
    For $col = 0 To $Width - 1
        $pixel = DllStructCreate("dword", $Scan0 + $row * $Stride + $col*4)
        DllStructSetData ($pixel, 1,$aData[$col][$row])
        ConsoleWrite(Hex(DllStructGetData($pixel, 1)) & @CRLF)
        $res &= $aData[$col][$row] & " "
    Next
    ConsoleWrite("-------" & @CRLF)
    $res &= @CRLF
Next
ConsoleWrite($res  & @CRLF)
 _GDIPlus_BitmapUnlockBits($pBitmap, $BitmapData)
_GDIPlus_ImageSaveToFile ($pBitmap, @DesktopDir & "\TestWrite.bmp")

Func OnAutoItExit()
;~    ' Unlock the bits
   ; _GDIPlus_BitmapUnlockBits($pBitmap, $BitmapData)

;~    ' // Cleanup
    If $pBitmap Then _GDIPlus_ImageDispose($pBitmap)

;~    ' // Shutdown GDI+
    _GDIPlus_Shutdown()
EndFunc   ;==>OnAutoItExit


#cs
  Bitmap b= new Bitmap("d:\\image.bmp");
           BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
                ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            int stride = bmData.Stride;
            System.IntPtr Scan0 = bmData.Scan0;
            unsafe
            {
                byte* p = (byte*)(void*)Scan0;
                int nOffset = stride - b.Width * 3;
                int nWidth = b.Width * 3;
                for (int y = 0; y < b.Height; ++y)
                {
                    for (int x = 0; x < nWidth; ++x)
                    {
                        p[0] = (byte)(255 - p[0]);
                        ++p;
                    }
                    p += nOffset;
                }
            }

            b.UnlockBits(bmData);
            
#ce

Share this post


Link to post
Share on other sites
weaponx

This will load a 100x100 image into a 200x100 GUI, then it will draw the original image on the left and a modified image on the right.

Basically it draws a green square in the middle of the image and shows before/after.

#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>

Global Const $GUI_Width = 200
Global Const $GUI_Height = 100
$strFileName = "spectrum.bmp"

$hwnd = GUICreate("GUI", $GUI_Width, $GUI_Height)
GUISetState()

_GDIPlus_Startup()

;Get handle to an Image object
$pBitmap = _GDIPlus_ImageLoadFromFile($strFileName)
;Get handle to a Graphics object
$graphics = _GDIPlus_GraphicsCreateFromHWND($hwnd)

;Draw the picture into the GUI - it will stretch to fit the GUI
_GDIPlus_GraphicsDrawImageRect($graphics, $pBitmap, 0, 0, 100, $GUI_Height)

;Get $tagGDIPBITMAPDATA structure
$BitmapData = _GDIPlus_BitmapLockBits($pBitmap, 20, 20, 60, 60, $GDIP_ILMWRITE, $GDIP_PXF32RGB)
If @ERROR Then MsgBox(0,"","Error locking region for writing")

;Stride - Offset, in bytes, between consecutive scan lines of the bitmap. If the stride is positive, the bitmap is top-down. If the stride is negative, the bitmap is bottom-up.
$Stride = DllStructGetData($BitmapData, "Stride")
ConsoleWrite("Bitmap Stride: " & $Stride & @CRLF)

;Image width - Number of pixels in one scan line of the bitmap.
$Width = DllStructGetData($BitmapData, "Width")
ConsoleWrite("Bitmap Width: " & $Width & @CRLF)

;Image height - Number of scan lines in the bitmap.
$Height = DllStructGetData($BitmapData, "Height")
ConsoleWrite("Bitmap Height: " & $Height & @CRLF)

;Pixel format - Integer that specifies the pixel format of the bitmap
$PixelFormat = DllStructGetData($BitmapData, "PixelFormat")
ConsoleWrite("Bitmap PixelFormat: " & $PixelFormat & @CRLF)

;Scan0 - Pointer to the first (index 0) scan line of the bitmap.
$Scan0 = DllStructGetData($BitmapData, "Scan0")
ConsoleWrite("Bitmap Scan0: " & $Scan0 & @CRLF)

For $row = 0 To $Height - 1
    For $col = 0 To $Width - 1
        $pixel = DllStructCreate("dword", $Scan0 + $row * $Stride + $col*4)
        DllStructSetData($pixel,1,0x0000FF00)
        ;ConsoleWrite(Hex(DllStructGetData($pixel, 1)) & @CRLF)
    Next
    ;ConsoleWrite("-------" & @CRLF)
Next

;Unlock region previously locked for writing
_GDIPlus_BitmapUnlockBits($pBitmap, $BitmapData)
_GDIPlus_GraphicsDrawImageRect($graphics, $pBitmap, 100, 0, 100, 100)

While 1
    $msg = GUIGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
WEnd

Func OnAutoItExit()
    If $pBitmap Then _GDIPlus_ImageDispose($pBitmap)
    _GDIPlus_Shutdown()
EndFunc   ;==>OnAutoItExitoÝ÷ Ù8b±Ú²Ø^±©¶§ìzmë*¹ªÞË+kj{)j·§µ«­¢+Ø¥¹±Õ±Ðí%A±Õ̹ÔÌÐì(¥¹±Õ±ÐíU%
½¹ÍѹÑÍà¹ÔÌÐì()±½°
½¹ÍÐÀÌØíU%}]¥Ñ ôÈÀÀ)±½°
½¹ÍÐÀÌØíU%}!¥¡ÐôÄÀÀ(ÀÌØíÍÑÉ¥±9µôÅÕ½ÐíÍÁÑÉÕ´¹µÀÅÕ½Ðì((ÀÌØí¡Ý¹ôU%
ÉÑ ÅÕ½ÐíU$ÅÕ½Ðì°ÀÌØíU%}]¥Ñ °ÀÌØíU%}!¥¡Ð¤)U%MÑMÑÑ ¤()}%A±ÕÍ}MÑÉÑÕÀ ¤((íС¹±Ñ¼¸%µ½©Ð(ÀÌØíÁ  ¥ÑµÀô}%A±ÕÍ}1½É½µ¥± ÀÌØíÍÑÉ¥±9µ¤(íС¹±Ñ¼ÉÁ¡¥Ì½©Ð(ÀÌØíÉÁ¡¥Ìô}%A±ÕÍ}ÉÁ¡¥Í
ÉÑɽµ!]9 ÀÌØí¡Ý¹¤((íÉÜÑ¡Á¥ÑÕÉ¥¹Ñ¼Ñ¡U$´¥ÐÝ¥±°ÍÑÉÑ Ñ¼¥ÐÑ¡U$)}%A±ÕÍ}ÉÁ¡¥ÍÉÝ%µIÐ ÀÌØíÉÁ¡¥Ì°ÀÌØíÁ   ¥ÑµÀ°À°À°ÄÀÀ°ÀÌØíU%}!¥¡Ð¤((íÐÀÌØíÑ%A    %Q5AQÍÑÉÕÑÕÉ(ÀÌØí    ¥ÑµÁÑô}%A±ÕÍ}  ¥ÑµÁ1½­   ¥ÑÌ ÀÌØíÁ   ¥ÑµÀ°ÈÀ°ÈÀ°ØÀ°ØÀ°ÀÌØí%A}%15]I%Q°ÀÌØí%A}AaÌÉI¤)%II=HQ¡¸5Í    ½à À°ÅÕ½ÐìÅÕ½Ðì°ÅÕ½ÐíÉɽȱ½­¥¹É¥½¸½ÈÝɥѥ¹ÅÕ½Ðì¤((íMÑÉ¥´=Íа¥¸åÑÌ°Ñݸ½¹ÍÕÑ¥Ù͸±¥¹Ì½Ñ¡¥ÑµÀ¸%Ñ¡ÍÑÉ¥¥ÌÁ½Í¥Ñ¥Ù°Ñ¡¥ÑµÀ¥ÌѽÀµ½Ý¸¸%Ñ¡ÍÑÉ¥¥Ì¹Ñ¥Ù°Ñ¡¥ÑµÀ¥Ì½Ñѽ´µÕÀ¸(ÀÌØíMÑÉ¥ô±±MÑÉÕÑÑÑ ÀÌØí   ¥ÑµÁÑ°ÅÕ½ÐíMÑÉ¥ÅÕ½Ðì¤)
½¹Í½±]É¥Ñ ÅÕ½Ðí    ¥ÑµÀMÑÉ¥èÅÕ½ÐìµÀìÀÌØíMÑÉ¥µÀì
I1¤((í%µÝ¥Ñ ´9յȽÁ¥á±Ì¥¸½¹Í¸±¥¹½Ñ¡¥ÑµÀ¸(ÀÌØí]¥Ñ ô±±MÑÉÕÑÑÑ ÀÌØí    ¥ÑµÁÑ°ÅÕ½Ðí]¥Ñ ÅÕ½Ðì¤)
½¹Í½±]É¥Ñ ÅÕ½Ðí    ¥ÑµÀ]¥Ñ èÅÕ½ÐìµÀìÀÌØí]¥Ñ µÀì
I1¤((í%µ¡¥¡Ð´9յȽ͸±¥¹Ì¥¸Ñ¡¥ÑµÀ¸(ÀÌØí!¥¡Ðô±±MÑÉÕÑÑÑ ÀÌØí    ¥ÑµÁÑ°ÅÕ½Ðí!¥¡ÐÅÕ½Ðì¤)
½¹Í½±]É¥Ñ ÅÕ½Ðí    ¥ÑµÀ!¥¡ÐèÅÕ½ÐìµÀìÀÌØí!¥¡ÐµÀì
I1¤((íA¥á°½ÉµÐ´%¹ÑÈÑ¡ÐÍÁ¥¥ÌÑ¡Á¥á°½ÉµÐ½Ñ¡¥ÑµÀ(ÀÌØíA¥á±½ÉµÐô±±MÑÉÕÑÑÑ ÀÌØí  ¥ÑµÁÑ°ÅÕ½ÐíA¥á±½ÉµÐÅÕ½Ðì¤)
½¹Í½±]É¥Ñ ÅÕ½Ðí    ¥ÑµÀA¥á±½ÉµÐèÅÕ½ÐìµÀìÀÌØíA¥á±½ÉµÐµÀì
I1¤((íM¸À´A½¥¹ÑÈѼѡ¥ÉÍС¥¹àÀ¤Í¸±¥¹½Ñ¡¥ÑµÀ¸(ÀÌØíM¸Àô±±MÑÉÕÑÑÑ ÀÌØí  ¥ÑµÁÑ°ÅÕ½ÐíM¸ÀÅÕ½Ðì¤)
½¹Í½±]É¥Ñ ÅÕ½Ðí    ¥ÑµÀM¸ÀèÅÕ½ÐìµÀìÀÌØíM¸ÀµÀì
I1¤()½ÈÀÌØíɽÜôÀQ¼ÀÌØí!¥¡Ð´Ä(½ÈÀÌØí½°ôÀQ¼ÀÌØí]¥Ñ ´Ä(ÀÌØíÁ¥á°ô±±MÑÉÕÑ
ÉÑ ÅÕ½ÐíݽÉÅÕ½Ðì°ÀÌØíM¸À¬ÀÌØíɽܨÀÌØíMÑÉ¥¬ÀÌØí½°¨Ð¤(±±MÑÉÕÑMÑÑ ÀÌØíÁ¥á°°Ä°ÁàÔÔÀÁÀÀ¤(í
½¹Í½±]ɥѡ!ࡱ±MÑÉÕÑÑÑ ÀÌØíÁ¥á°°Ä¤¤µÀì
I1¤(9áÐ(í
½¹Í½±]É¥Ñ ÅÕ½Ðì´´´´´´´ÅÕ½ÐìµÀì
I1¤)9áÐ((íU¹±½¬É¥½¸ÁÉÙ¥½Õͱ䱽­½ÈÝɥѥ¹)}%A±ÕÍ}  ¥ÑµÁU¹±½­   ¥ÑÌ ÀÌØíÁ   ¥ÑµÀ°ÀÌØí  ¥ÑµÁѤ)}%A±ÕÍ}ÉÁ¡¥ÍÉÝ%µIÐ ÀÌØíÉÁ¡¥Ì°ÀÌØíÁ  ¥ÑµÀ°ÄÀÀ°À°ÄÀÀ°ÄÀÀ¤()]¡¥±Ä(ÀÌØíµÍôU%Ñ5Í ¤(%ÀÌØíµÍôÀÌØíU%}Y9Q}
1=MQ¡¸á¥Ñ1½½À)]¹()Õ¹=¹Õѽ%Ñá¥Ð ¤(%ÀÌØíÁ    ¥ÑµÀQ¡¸}%A±ÕÍ}%µ¥ÍÁ½Í ÀÌØíÁ ¥ÑµÀ¤(}%A±ÕÍ}M¡Õѽݸ ¤)¹Õ¹ìôôÐí=¹Õѽ%Ñá¥
Edited by weaponx

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×