Sign in to follow this  
Followers 0
zagibu

Working with ScreenCapture & HBITMAP

12 posts in this topic

I'm trying to write an ImageSearch routine similar to the one in AutoHotkey, and I'm stuck with a (probably) very amateuri-ish problem.

_ScreenCapture_Capture("") is returning a HBITMAP handle. What do I do with that? I just want the raw bitmap data (the same I would get by using a binary FileOpen/FileRead on a bitmap file). I don't want to let ScreenCapture create the file, then read it from there, because that would lead to a lot of disk access.

Thanks in advance.

Share this post


Link to post
Share on other sites



What do you want to do with it?

Set to Image Control? Look at _SetBitmapToCtrl from resources.au3

Or use other functions from GDIPlus :)


*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

I just need the raw byte data...I need it to do comparisons byte-wise.

Share this post


Link to post
Share on other sites

There is a Function called _GDIPlus_BitmapCreateFromHBITMAP, which is supposed to take a HBITMAP and return a "bitmap object". But I don't see anything that can be used to access the bitmap data.

It's probably so obvious that noone can be bothered to post it...

Share this post


Link to post
Share on other sites

Even though MS defines GetBitmapBits/SetBitmapBits to be obsolete, you can still use them:

#include <WinAPI.au3>
#Include <ScreenCapture.au3>

$hBmp = _ScreenCapture_Capture("", 0, 0, 16, 16)
$aSize = DllCall('gdi32.dll', 'int', 'GetBitmapBits', 'ptr', $hBmp, 'int', 0, 'ptr', 0)
If $aSize[0] Then
    $tBits = DllStructCreate('byte[' & $aSize[0] & ']')
    DllCall('gdi32.dll', 'int', 'GetBitmapBits', 'ptr', $hBmp, 'int', $aSize[0], 'ptr', DllStructGetPtr($tBits))
    $sHex = Hex(DllStructGetData($tBits, 1))
    MsgBox(0, '', $sHex)
EndIf
_WinAPI_DeleteObject($hBmp)

Exit

"be smart, drink your wine"

Share this post


Link to post
Share on other sites

Cool, thanks a lot. Just on a side note: what would be a non-obsolete way of doing it?

Share this post


Link to post
Share on other sites

That would be GetDIBits, but for that you also need the handle to DC in which the bitmap is selected, so you'd have to do what _ScreenCapture_Capture() does and call GetDIBits after BitBlt.


"be smart, drink your wine"

Share this post


Link to post
Share on other sites

Hmmm, what about this:

$hbmp = _ScreenCapture_Capture("")
$himg = _GDIPlus_BitmapCreateFromHBITMAP($hbmp)
$gfx = _GDIPlus_ImageGetGraphicsContext($himg)
$dc = _GDIPlus_GraphicsGetDC($gfx)

And then use GetDIBits?

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

Your solution works fine, BTW, thanks a lot, Siao. A problem is, that I get a 32bit BMP, though, no matter what I set with _ScreenCapture_SetBMPFormat().

Anyone see a quick operation to dump the additional byte? Or a way to get a 24bit BMP that needs no post-processing?

Edited by zagibu

Share this post


Link to post
Share on other sites

#include <WinAPI.au3>

Const $DIB_RGB_COLORS = 0
$iWidth = 16;@DesktopWidth
$iHeight = 16;@DesktopHeight
$iBitCount = 24
$tBMI = DllStructCreate($tagBITMAPINFO)
        DllStructSetData($tBMI, "Size", DllStructGetSize($tBMI) - 4)
        DllStructSetData($tBMI, "Width", $iWidth)
        DllStructSetData($tBMI, "Height", -$iHeight)
        DllStructSetData($tBMI, "Planes", 1)
        DllStructSetData($tBMI, "BitCount", $iBitCount)
$hDC = _WinAPI_GetDC(0)
$hCDC = _WinAPI_CreateCompatibleDC($hDC)
$aDIB = DllCall('gdi32.dll','ptr','CreateDIBSection', 'ptr',0, 'ptr',DllStructGetPtr($tBMI), 'uint',$DIB_RGB_COLORS, 'ptr*',0, 'ptr',0, 'uint',0)
_WinAPI_DeleteObject(_WinAPI_SelectObject($hCDC, $aDIB[0]))
_WinAPI_BitBlt($hCDC, 0, 0, $iWidth, $iHeight, $hDC, 0, 0, $SRCCOPY)
$tBits = DllStructCreate('byte[' & $iWidth*$iHeight*$iBitCount/8 & ']', $aDIB[4])
        $sHex = Hex(DllStructGetData($tBits, 1))
        MsgBox(0, '', $sHex)

_WinAPI_DeleteObject($aDIB[0])
_WinAPI_DeleteDC($hCDC)
_WinAPI_ReleaseDC(0, $hDC)


"be smart, drink your wine"

Share this post


Link to post
Share on other sites

$aDIB = DllCall('gdi32.dll','ptr','CreateDIBSection', 'ptr',0, 'ptr',DllStructGetPtr($tBMI), 'uint',$DIB_RGB_COLORS, 'ptr*',0, 'ptr',0, 'uint',0)
I had been trying to use GetDIBits, without success.

Thank-you very much, Siao. This entire script is very helpful.

Share this post


Link to post
Share on other sites

I had been trying to use GetDIBits, without success.

Thank-you very much, Siao. This entire script is very helpful.

what if i want to read a .bmp file with the same format? this seems to read a region in a desktop so i want to compare the 2.

Thanks.

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  
Followers 0