Download binary image into var, convert to bitmap & show in GUI

Post your working scripts, libraries and tools for AHK v1.1 and older
DJAnonimo
Posts: 3
Joined: 11 Feb 2018, 17:36

Download binary image into var, convert to bitmap & show in GUI

11 Feb 2018, 18:43

Hi all,

You need to download a picture (JPG, PNG etc...) into memory and show it in your GUI without writing a file?

After few hours of research and answers on question like: How can it be done? Why this way? Why me?
Here is a simple example.

I don't know why global or "byref" need to be used for input Imagebin into a function. This is only when downloaded with DownloadBin(). If downloaded with UrlDownloadToFile it can be as a function parameter.
Improvements are always welcome :)

Have Fun!

Code: Select all

; Tested with AHK Unicode 1.1.27.00 on Win7
#NoEnv
SendMode Input
SetWorkingDir %A_ScriptDir% 

url := "http://www.userlogos.org/files/logos/jumpordie/autohotkey_02.png"		; IMAGE URL

size := DownloadBin(url, ImageBin)			; DOWNLOAD JPG INTO VAR
BinImgToBITMAP(size, HBITMAP, Imagebin)			; CONVERT BINARY TO BITMAP

H := Bitmap_GetHeight(HBITMAP)			; GET IMAGE HEIGHT
W := Bitmap_GetWidth(HBITMAP)			; GET IMAGE WIDTH
Gui, Margin, 0, 0
Gui, Add, Text, x0 y0 w%W% h%H% hwndHPic1 ; IMAGE POSITION
Bitmap_SetImage(HPic1, HBITMAP)			; SET IMAGE TO A GIVEN hwnd
Gui, Show, , Image						; SHOW GUI

return

; ----------------------------------------------------------------------------------------------------------------------
; Convert Binary Image to Bitmap.
; ----------------------------------------------------------------------------------------------------------------------
BinImgToBITMAP(size, byref hBitmap, byref Imagebin) {
	if hBitmap
		DllCall("DeleteObject", "ptr", hBitmap)
	hData := DllCall("Kernel32.dll\GlobalAlloc", "UInt", 2, "UPtr", size, "UPtr")
	pData := DllCall("Kernel32.dll\GlobalLock", "Ptr", hData, "UPtr")
	DllCall("Kernel32.dll\RtlMoveMemory", "Ptr", pData, "Ptr", &ImageBin, "UPtr", size)
	DllCall("Kernel32.dll\GlobalUnlock", "Ptr", hData)
	DllCall("Ole32.dll\CreateStreamOnHGlobal", "Ptr", hData, "Int", True, "PtrP", pStream)
	hGdip := DllCall("Kernel32.dll\LoadLibrary", "Str", "Gdiplus.dll", "UPtr")
	VarSetCapacity(SI, 16, 0), NumPut(1, SI, 0, "UChar")
	DllCall("Gdiplus.dll\GdiplusStartup", "PtrP", pToken, "Ptr", &SI, "Ptr", 0)
	DllCall("Gdiplus.dll\GdipCreateBitmapFromStream",  "Ptr", pStream, "PtrP", pBitmap)
	DllCall("Gdiplus.dll\GdipCreateHBITMAPFromBitmap", "Ptr", pBitmap, "PtrP", hBitmap, "UInt", 0)
	DllCall("Gdiplus.dll\GdipDisposeImage", "Ptr", pBitmap)
	DllCall("Gdiplus.dll\GdiplusShutdown", "Ptr", pToken)
	DllCall("Kernel32.dll\FreeLibrary", "Ptr", hGdip)
	DllCall(NumGet(NumGet(pStream + 0, 0, "UPtr") + (A_PtrSize * 2), 0, "UPtr"), "Ptr", pStream)
}

; ----------------------------------------------------------------------------------------------------------------------
; Returns the width of a bitmap.
; ----------------------------------------------------------------------------------------------------------------------
Bitmap_GetWidth(hBitmap) {
   Static Size := (4 * 5) + A_PtrSize + (A_PtrSize - 4)
   VarSetCapacity(BITMAP, Size, 0)
   DllCall("Gdi32.dll\GetObject", "Ptr", hBitmap, "Int", Size, "Ptr", &BITMAP, "Int")
   Return NumGet(BITMAP, 4, "Int")
}
; ----------------------------------------------------------------------------------------------------------------------
; Returns the height of a bitmap.
; ----------------------------------------------------------------------------------------------------------------------
Bitmap_GetHeight(hBitmap) {
   Static Size := (4 * 5) + A_PtrSize + (A_PtrSize - 4)
   VarSetCapacity(BITMAP, Size, 0)
   DllCall("Gdi32.dll\GetObject", "Ptr", hBitmap, "Int", Size, "Ptr", &BITMAP, "Int")
   Return NumGet(BITMAP, 8, "Int")
}
; ----------------------------------------------------------------------------------------------------------------------
; Associates a new bitmap with a static control.
; Parameters:     hCtrl    -  Handle to the GUI control (Pic or Text).
;                 hBitmap  -  Handle to the bitmap to associate with the GUI control.
; Return value:   Handle to the image previously associated with the GUI control, if any; otherwise, NULL.
; ----------------------------------------------------------------------------------------------------------------------
Bitmap_SetImage(hCtrl, hBitmap) {
   ; STM_SETIMAGE = 0x172, IMAGE_BITMAP = 0x00, SS_BITMAP = 0x0E
   WinSet, Style, +0x0E, ahk_id %hCtrl%
   SendMessage, 0x172, 0x00, %hBitmap%, , ahk_id %hCtrl%
   DllCall("DeleteObject", "ptr", ErrorLevel)		;  Delete Objects for prevent memory leak
   DllCall("DeleteObject", "Uint", hBitmap)	
   Return ErrorLevel
}

; DOWNLOAD BIN DATA TO A VARIABLE
DownloadBin(url, byref buf)
{
    static a := "AutoHotkey/" A_AhkVersion
    if (!DllCall("LoadLibrary", "str", "wininet") || !(h := DllCall("wininet\InternetOpen", "str", a, "uint", 1, "ptr", 0, "ptr", 0, "uint", 0, "ptr")))
        return 0
    c := s := 0
    if (f := DllCall("wininet\InternetOpenUrl", "ptr", h, "str", url, "ptr", 0, "uint", 0, "uint", 0x80003000, "ptr", 0, "ptr"))
    {
        while (DllCall("wininet\InternetQueryDataAvailable", "ptr", f, "uint*", s, "uint", 0, "ptr", 0) && s > 0)
        {
            VarSetCapacity(b, c + s, 0)
            if (c > 0)
                DllCall("RtlMoveMemory", "ptr", &b, "ptr", &buf, "ptr", c)
            DllCall("wininet\InternetReadFile", "ptr", f, "ptr", &b + c, "uint", s, "uint*", r)
            c += r
            VarSetCapacity(buf, c, 0)
            if (c > 0)
                DllCall("RtlMoveMemory", "ptr", &buf, "ptr", &b, "ptr", c)
        }
        DllCall("wininet\InternetCloseHandle", "ptr", f)
    }
    DllCall("wininet\InternetCloseHandle", "ptr", h)
    return c
}
Last edited by DJAnonimo on 06 Mar 2018, 14:06, edited 4 times in total.
User avatar
tidbit
Posts: 1272
Joined: 29 Sep 2013, 17:15
Location: USA

Re: Download binary image into var, convert to bitmap & show in GUI

11 Feb 2018, 20:10

welcome back to the forums/ahk, DJAnonimo!
looks.. complicated and great.
rawr. fear me.
*poke*
Is it December 21, 2012 yet?

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 249 guests