Jump to content

Recommended Posts

Posted

I'm trying to use a function from the leptonica dll. It seems like it should be straightforward, but I'm having no luck with it.

From the documentation:

typedef unsigned char l_uint8

PIX* pixReadMemBmp(const l_uint8 *cdata, size_t size)

Then, in AutoIT, I have:

$leptonicaHandle = DllOpen("path\to\liblept168.dll");

$image = _ScreenCapture_Capture("", $x1, $y1, $x2, $y2);

$tmp = _GDIPlus_BitmapCreateFromHBITMAP($image);
$width = _GDIPlus_ImageGetWidth($tmp);
$height = _GDIPlus_ImageGetHeight($tmp);

$pix = DllCall($leptonicaHandle, "ptr:cdecl", "pixReadMemBmp", "str", $image, "ULONG_PTR", (($width * $height * 24) + 54));
; @error == 0
; $pix[0] == 0x000000

There are no errors when this executes. The call to pixReadMemBmp just returns a bad memory address every time. I read that HBITMAP can be type-cast into uchar * without issue, but I think this may be where my code is off. I have "str" above, but I've tried "str*", "ptr" and "handle" as well.

Also, the last parameter to DllCall is supposed to be the size of the bitmap in bytes (width * height * 24bits/pixel) + 54bytesforheader. I'm not 100% sure this is correct, but I couldn't find any AutoIT functions to get image size from an HBITMAP.

I'd appreciate any thoughts on this. Thanks...

Posted

Actually the documentation says this also.

Read/write to memory [only on linux]

PIX *pixReadMemBmp()

l_int32 pixWriteMemBmp()

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

  • 13 years later...
Posted

In case someone found this topic on the search engines, here is how to create a pix object from a bitmap object
 

#include <WinAPIGdi.au3>
#include <WinAPIGdiDC.au3>
#include <WinAPIHObj.au3>
#include <Memory.au3>

#include <ScreenCapture.au3>

Local $hLeptonicaDll = DllOpen(@ScriptDir & "\liblept168.dll")
If $hLeptonicaDll = -1 Then Exit
Local $hBitmap = _ScreenCapture_Capture()
Local $pPix = _CreatePixFromHBITMAP($hBitmap)
ConsoleWrite("Pix object: " & $pPix & @CR)
_WinAPI_DeleteObject($hBitmap)
DllCall($hLeptonicaDll, "none:cdecl", "pixDestroy", "ptr*", $pPix)
DllClose($hLeptonicaDll)

Func _CreatePixFromHBITMAP($hHBITMAP)

    ; Get bitmap information
    Local $tBITMAP = DllStructCreate($tagBITMAP)
    _WinAPI_GetObject($hHBITMAP, DllStructGetSize($tBITMAP), DllStructGetPtr($tBITMAP))
    If @error Then Return SetError(1, 0, 0)

    Local $iWidth = DllStructGetData($tBITMAP, "bmWidth")
    Local $iHeight = Abs(DllStructGetData($tBITMAP, "bmHeight"))

    ; Get a device context
    Local $hDC = _WinAPI_GetDC(0)
    If $hDC = 0 Then Return SetError(2, 0, 0)

    ; Get pix object
    Local $pPix = DllCall($hLeptonicaDll, "ptr:cdecl", "pixCreate", "int", $iWidth, "int", $iHeight, "int", 32)
    If @error Or $pPix[0] = 0 Then
        _WinAPI_ReleaseDC(0, $hDC)
        Return SetError(3, 0, 0)
    EndIf
    $pPix = $pPix[0]
    ; Get the pointer to Leptonica's allocated memory
    Local $pPixData = DllCall($hLeptonicaDll, "ptr:cdecl", "pixGetData", "ptr", $pPix)
    If @error Or $pPixData[0] = 0 Then
        _WinAPI_ReleaseDC(0, $hDC)
        DllCall($hLeptonicaDll, "none:cdecl", "pixDestroy", "ptr*", $pPix)
        Return SetError(4, 0, 0)
    EndIf
    $pPixData = $pPixData[0]

    ; Create a 32 bit HBITMAP copy if needed
    Local $bDeleteHBITMAP = False
    If DllStructGetData($tBITMAP, "bmBitsPixel") <> 32 Then
        $hHBITMAP = _Create32HBITMAP($hHBITMAP, $iWidth, $iHeight)
        If @error Then
            _WinAPI_ReleaseDC(0, $hDC)
            DllCall($hLeptonicaDll, "none:cdecl", "pixDestroy", "ptr*", $pPix)
            Return SetError(5, 0, 0)
        EndIf
        $bDeleteHBITMAP = True
    EndIf

    ; Create BITMAPINFOHEADER
    Local $tBIHDR = DllStructCreate("dword biSize;long biWidth;long biHeight;WORD biPlanes;WORD biBitCount;dword biCompression;dword biSizeImage;long biXPelsPerMeter;long biYPelsPerMeter;dword biClrUsed;dword biClrImportant;")
    DllStructSetData($tBIHDR, "biSize", DllStructGetSize($tBIHDR))
    DllStructSetData($tBIHDR, "biWidth", $iWidth)
    DllStructSetData($tBIHDR, "biHeight", -$iHeight) ; Negative for top-down DIB
    DllStructSetData($tBIHDR, "biPlanes", 1)
    DllStructSetData($tBIHDR, "biBitCount", 32)
    DllStructSetData($tBIHDR, "biCompression", 0) ; BI_RGB

    ; Calculate buffer size
    Local $iRowSize = Int(($iWidth * 32 + 31) / 32) * 4
    Local $iImageSize = $iRowSize * $iHeight
    ; Allocate temporary buffer for GetDIBits
    Local $pTempBuffer = _MemVirtualAlloc(0, $iImageSize, 0x1000, 0x04)
    If $pTempBuffer = 0 Then
        _WinAPI_ReleaseDC(0, $hDC)
        DllCall($hLeptonicaDll, "none:cdecl", "pixDestroy", "ptr*", $pPix)
        If $bDeleteHBITMAP Then _WinAPI_DeleteObject($hHBITMAP)
        Return SetError(5, 0, 0)
    EndIf
    ; Get the pixel data
    _WinAPI_GetDIBits($hDC, $hHBITMAP, 0, $iHeight, $pTempBuffer, DllStructGetPtr($tBIHDR), $DIB_RGB_COLORS)
    ; Copy data into Leptonica's buffer
    DllCall("kernel32.dll", "none", "RtlMoveMemory", "ptr", $pPixData, "ptr", $pTempBuffer, "ulong_ptr", $iImageSize)

    _WinAPI_ReleaseDC(0, $hDC)
    _MemVirtualFree($pTempBuffer, 0, 0x8000) ; Free our temporary buffer
    If $bDeleteHBITMAP Then _WinAPI_DeleteObject($hHBITMAP)

    Return $pPix
EndFunc   ;==>_CreatePixFromHBITMAP

Func _Create32HBITMAP($hBitmap, $iWidth, $iHeight)
    ; Create 32-bit bitmap
    Local $hDC = _WinAPI_GetDC(0)
    Local $hBitmap32 = _WinAPI_CreateCompatibleBitmapEx($hDC, $iWidth, $iHeight, 0xFF000000) ; Black with alpha=255
    _WinAPI_ReleaseDC(0, $hDC)
    If $hBitmap32 = 0 Then Return SetError(1, 0, 0)
    ; Use AlphaBlend for format conversion
    Local $hDC1 = _WinAPI_CreateCompatibleDC(0)
    Local $hDC2 = _WinAPI_CreateCompatibleDC(0)
    Local $hOld1 = _WinAPI_SelectObject($hDC1, $hBitmap)
    Local $hOld2 = _WinAPI_SelectObject($hDC2, $hBitmap32)
    ; AlphaBlend automatically handles format conversion and sets alpha
    _WinAPI_AlphaBlend($hDC2, 0, 0, $iWidth, $iHeight, $hDC1, 0, 0, $iWidth, $iHeight, 255)
    _WinAPI_SelectObject($hDC1, $hOld1)
    _WinAPI_SelectObject($hDC2, $hOld2)
    ; Clean up
    _WinAPI_DeleteDC($hDC1)
    _WinAPI_DeleteDC($hDC2)
    Return $hBitmap32
EndFunc   ;==>_Create32HBITMAP

 

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
×
×
  • Create New...