Page 1 of 1

Display a bitmap in a Picture Gui control with a bitmap retrieved from a SQLite database

Posted: 23 Dec 2023, 17:44
by JnLlnd
After I retrieve a bitmap BLOB from an SQLite database, how can I display it in a Picture Gui control without having to write it to a file like in this working example?

Code: Select all

#SingleInstance Force
#requires AutoHotkey v1.1

#Include %A_ScriptDir%\Class_SQLiteDB.ahk ; SQLite wrapper from just_me (https://autohotkey.com/boards/viewtopic.php?t=1064)
; not used #Include %A_ScriptDir%\Gdip_All.ahk ; https://github.com/marius-sucan/AHK-GDIp-Library-Compilation/blob/master/ahk-v1-1/Gdip_All.ahk
SetWorkingDir, %A_ScriptDir%

; ======================================================================================================================
; Get the Google logo or store a picture named Original.gif in the script's folder and comment this out
FileDelete, Original.gif
URLDownloadToFile, http://www.google.de/intl/de_ALL/images/logos/images_logo_lg.gif, Original.gif

Gui, 1:Add, Picture, +Border, Original.gif
Gui, 1:Show, AutoSize x50 y50, Original

; Start
FileDelete, Blob.gif
DBFileName := A_ScriptDir . "\TEST_B.DB"
If FileExist(DBFileName) {
   SB_SetText("Deleting " . DBFileName)
   FileDelete, %DBFileName%
}

; Use Class SQLiteDB : Create new instance
DB := new SQLiteDB

; Use Class SQLiteDB : Open/create database and table, insert a BLOB from a GIF file
If !DB.OpenDB(DBFileName) {
   MsgBox, 16, SQLite Error, % "Msg:`t" . DB.ErrorMsg . "`nCode:`t" . DB.ErrorCode
   ExitApp
}

; Write GIF BLOB
HFILE := FileOpen("Original.gif", "r")
Size := HFILE.RawRead(BLOB, HFILE.Length)
HFILE.Close()
If !DB.Exec("CREATE TABLE Test (TextType, BlobType);")
   MsgBox, 16, SQLite Error, % "Msg:`t" . DB.ErrorMsg . "`nCode:`t" . DB.ErrorCode
DB.Exec("BEGIN TRANSACTION;")
; ? stands for an automatically numbered parameter (here: 1) to use in BlobArray
SQL := "INSERT INTO Test VALUES('Text', ?);"
; Create the BLOB array
BlobArray := []
BlobArray.Insert({Addr: &BLOB, Size: Size}) ; will be inserted as element 1
If !DB.StoreBLOB(SQL, BlobArray)
   MsgBox, 16, SQLite Error, % "Msg:`t" . DB.ErrorMsg . "`nCode:`t" . DB.ErrorCode
DB.Exec("COMMIT TRANSACTION;")

; Get the BLOB form the database

If !DB.Query("SELECT * FROM Test;", RecordSet)
   MsgBox, 16, SQLite Error: Query, % "Msg:`t" . RecordSet.ErrorMsg . "`nCode:`t" . RecordSet.ErrorCode
RecordSet.Next(Row) ; get first (and only) row in the Test table

; write the blob to a file (THIS IS WHAT I'D PREFER TO AVOID)
; second field in the row is the blob
Size := Row[2].Size 
Addr := Row[2].GetAddress("Blob")
VarSetCapacity(MyBLOBVar, Size)
DllCall("Kernel32.dll\RtlMoveMemory", "Ptr", &MyBLOBVar, "Ptr", Addr, "Ptr", Size)
HFILE := FileOpen("MyBlob.gif", "w")
HFILE.RawWrite(&MyBLOBVar, Size) ; changed
RecordSet.Free()
HFILE.Close()

Gui, 2:Add, Picture, +Border, MyBlob.gif
; COULD I REPLACE THIS USING HBITMAP:* ?
; Gui,Add, Picture, +Border, % "HBITMAP:*" . ???
Gui, 2:Show, AutoSize x100 y100, Blob

return

2GuiClose:
ExitApp
What I need is to get the correct for value HBITMAP:*

Gui,Add, Picture, +Border, % "HBITMAP:*" . ???

Thanks!

Re: Display a bitmap in a Picture Gui control with a bitmap retrieved from a SQLite database

Posted: 24 Dec 2023, 05:35
by just me
Hi @JnLlnd,

you can try the following passing the pointer to the and the size of the BLOB-Data to Gdip_CreateHBitmapFomData().

Code: Select all

Gdip_CreateHBitmapFomData(DataPtr, DataSize) {
   Local Bitmap := 0, HBitMap := 0
   If (Bitmap := Gdip_CreateBitmapFromData(DataPtr, DataSize)) {
      HBitMap := Gdip_CreateHBITMAPFromBitmap(Bitmap)
      Gdip_DisposeImage(Bitmap)
   }
   Return HBitmap
}
Gdip_CreateBitmapFromData(DataPtr, DataSize) {
   Local Bitmap := 0, Stream := 0, HR := 0
   If (Stream := DllCall("Shlwapi.dll\SHCreateMemStream", "Ptr", DataPtr, "UInt", DataSize, "UPtr")) {
      HR := DllCall("Gdiplus.dll\GdipCreateBitmapFromStream", "Ptr", Stream, "PtrP", Bitmap, "UInt")
      Stream.Release()
   }
   Return (HR ? 0 : Bitmap)
}
*not tested*

Merry Christmas and a happy new year!

Re: Display a bitmap in a Picture Gui control with a bitmap retrieved from a SQLite database

Posted: 24 Dec 2023, 08:49
by JnLlnd
just me wrote:
24 Dec 2023, 05:35
Hi @JnLlnd,

you can try the following passing the pointer to the and the size of the BLOB-Data to Gdip_CreateHBitmapFomData().
Merry Christmas and a happy new year!
Hi just_me

Merry Christmas to you :-)

I tested the code and it did not work yet. The Gdip_CreateHBitmapFomData() function returns 0. More precisely, this is the call to GdipCreateBitmapFromStream that returns 0 in Bitmap.

Yes, that worked. Thanks @just me for the solution and to @william_ahk for the error fixed.

Code: Select all

#SingleInstance Force
#requires AutoHotkey v1.1

#Include %A_ScriptDir%\Class_SQLiteDB.ahk ; SQLite wrapper from just_me (https://autohotkey.com/boards/viewtopic.php?t=1064)
#Include %A_ScriptDir%\Gdip_All.ahk ; https://github.com/marius-sucan/AHK-GDIp-Library-Compilation/blob/master/ahk-v1-1/Gdip_All.ahk
SetWorkingDir, %A_ScriptDir%

; ======================================================================================================================
; Get the Google logo or store a picture named Original.gif in the script's folder and comment this out
FileDelete, Original.gif
URLDownloadToFile, http://www.google.de/intl/de_ALL/images/logos/images_logo_lg.gif, Original.gif

Gui, 1:Add, Picture, +Border, Original.gif
Gui, 1:Show, AutoSize x50 y50, Original

; Start
FileDelete, Blob.gif
DBFileName := A_ScriptDir . "\TEST_B.DB"
If FileExist(DBFileName) {
   SB_SetText("Deleting " . DBFileName)
   FileDelete, %DBFileName%
}

; Use Class SQLiteDB : Create new instance
DB := new SQLiteDB

; Use Class SQLiteDB : Open/create database and table, insert a BLOB from a GIF file
If !DB.OpenDB(DBFileName) {
   MsgBox, 16, SQLite Error, % "Msg:`t" . DB.ErrorMsg . "`nCode:`t" . DB.ErrorCode
   ExitApp
}

; Write GIF BLOB
HFILE := FileOpen("Original.gif", "r")
Size := HFILE.RawRead(BLOB, HFILE.Length)
HFILE.Close()
If !DB.Exec("CREATE TABLE Test (TextType, BlobType);")
   MsgBox, 16, SQLite Error, % "Msg:`t" . DB.ErrorMsg . "`nCode:`t" . DB.ErrorCode
DB.Exec("BEGIN TRANSACTION;")
; ? stands for an automatically numbered parameter (here: 1) to use in BlobArray
SQL := "INSERT INTO Test VALUES('Text', ?);"
; Create the BLOB array
BlobArray := []
BlobArray.Insert({Addr: &BLOB, Size: Size}) ; will be inserted as element 1
If !DB.StoreBLOB(SQL, BlobArray)
   MsgBox, 16, SQLite Error, % "Msg:`t" . DB.ErrorMsg . "`nCode:`t" . DB.ErrorCode
DB.Exec("COMMIT TRANSACTION;")

; Get the BLOB from the database

If !DB.Query("SELECT * FROM Test;", RecordSet)
   MsgBox, 16, SQLite Error: Query, % "Msg:`t" . RecordSet.ErrorMsg . "`nCode:`t" . RecordSet.ErrorCode
RecordSet.Next(Row) ; get first (and only) row in the Test table

; write the blob to hBitmap *** EDIT: NOW WORKING ***
; second field in the row is the blob
Size := Row[2].Size 
Addr := Row[2].GetAddress("Blob")
pToken := Gdip_Startup()
hBitmap := Gdip_CreateHBitmapFomData(Addr, Size)
Gui, 2:Add, Picture, +Border, % "HBITMAP:*" . hBitmap
Gui, 2:Show, AutoSize x100 y100, Blob

RecordSet.Free()
Gdip_Shutdown(pToken )
return

2GuiClose:
ExitApp

Gdip_CreateHBitmapFomData(DataPtr, DataSize) {
   Local Bitmap := 0, HBitMap := 0
   If (Bitmap := Gdip_CreateBitmapFromData(DataPtr, DataSize)) {
      HBitMap := Gdip_CreateHBITMAPFromBitmap(Bitmap)
      Gdip_DisposeImage(Bitmap)
   }
   Return HBitmap
}

Gdip_CreateBitmapFromData(DataPtr, DataSize) {
   Local Bitmap := 0, Stream := 0, HR := 0
   If (Stream := DllCall("Shlwapi.dll\SHCreateMemStream", "Ptr", DataPtr, "UInt", DataSize, "UPtr")) {
      HR := DllCall("Gdiplus.dll\GdipCreateBitmapFromStream", "Ptr", Stream, "PtrP", Bitmap, "UInt")
      Stream.Release()
   }
   Return (HR ? 0 : Bitmap)
}

Re: Display a bitmap in a Picture Gui control with a bitmap retrieved from a SQLite database

Posted: 24 Dec 2023, 23:38
by william_ahk
Perhaps you forgot to pToken := Gdip_Startup()?

Re: Display a bitmap in a Picture Gui control with a bitmap retrieved from a SQLite database

Posted: 25 Dec 2023, 00:27
by JnLlnd
@william_ahk You got it! I'll post the code fixed when I have a little more time. Thanks.

PS: viewtopic.php?p=552284#p552284 fixed.