Skip to content

Instantly share code, notes, and snippets.

@AHK-just-me
Last active September 16, 2024 19:30
Show Gist options
  • Save AHK-just-me/5559658 to your computer and use it in GitHub Desktop.
Save AHK-just-me/5559658 to your computer and use it in GitHub Desktop.
Create include files from images which can be used without external files.
; ======================================================================================================================
; Function: Creates AHK #Include files for images providing a function which will internally create a bitmap/icon.
; AHK version: 1.1.10.01 (U32)
; Script version: 1.0.00.02/2013-06-02/just me - added support for icons (HICON)
; 1.0.00.01/2013-05-18/just me - fixed bug producing invalid function names
; 1.0.00.00/2013-04-30/just me
; Credits: Bitmap creation is based on "How to convert Image data (JPEG/PNG/GIF) to hBITMAP?" by SKAN ->
; http://www.autohotkey.com/board/topic/21213-how-to-convert-image-data-jpegpnggif-to-hbitmap/?p=139257
; ======================================================================================================================
; This software is provided 'as-is', without any express or implied warranty.
; In no event will the authors be held liable for any damages arising from the use of this software.
; ======================================================================================================================
#NoEnv
SetBatchLines, -1
; ======================================================================================================================
; Some strings used to generate the #Include file
; ======================================================================================================================
Header1 := "
(Join`r`n
; ##################################################################################
; # This #Include file was generated by Image2Include.ahk, you must not change it! #
; ##################################################################################
)"
; ----------------------------------------------------------------------------------------------------------------------
Header2 := "
(Join`r`n
If (NewHandle)
hBitmap := 0
If (hBitmap)
Return hBitmap
)"
; ----------------------------------------------------------------------------------------------------------------------
Footer1 := "
(Join`r`n
If !DllCall(""Crypt32.dll\CryptStringToBinary"", ""Ptr"", &B64, ""UInt"", 0, ""UInt"", 0x01, ""Ptr"", 0, ""UIntP"", DecLen, ""Ptr"", 0, ""Ptr"", 0)
Return False
VarSetCapacity(Dec, DecLen, 0)
If !DllCall(""Crypt32.dll\CryptStringToBinary"", ""Ptr"", &B64, ""UInt"", 0, ""UInt"", 0x01, ""Ptr"", &Dec, ""UIntP"", DecLen, ""Ptr"", 0, ""Ptr"", 0)
Return False
; Bitmap creation adopted from ""How to convert Image data (JPEG/PNG/GIF) to hBITMAP?"" by SKAN
; -> http://www.autohotkey.com/board/topic/21213-how-to-convert-image-data-jpegpnggif-to-hbitmap/?p=139257
hData := DllCall(""Kernel32.dll\GlobalAlloc"", ""UInt"", 2, ""UPtr"", DecLen, ""UPtr"")
pData := DllCall(""Kernel32.dll\GlobalLock"", ""Ptr"", hData, ""UPtr"")
DllCall(""Kernel32.dll\RtlMoveMemory"", ""Ptr"", pData, ""Ptr"", &Dec, ""UPtr"", DecLen)
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)
)"
; ----------------------------------------------------------------------------------------------------------------------
Footer2 := "
(Join`r`n
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)
Return hBitmap
}
)"
; ======================================================================================================================
; Read INI file
; ======================================================================================================================
IniFile := A_ScriptFullPath . ":INI"
ImgDir := OutDir := A_ScriptDir
IniRead, Value, %IniFile%, Image2Include, ImgDir, 0
If (Value) && InStr(FileExist(Value), "D")
ImgDir := Value
IniRead, Value, %IniFile%, Image2Include, OutDir, 0
If (Value) && InStr(FileExist(Value), "D")
OutDir := Value
ImgFile := ""
; ======================================================================================================================
; Select an image file
; ======================================================================================================================
Gui, Margin, 20, 20
Gui, Add, Text, xm cNavy, Select Image File:
Gui, Add, Edit, xm y+5 w400 vImgFile +ReadOnly
Gui, Add, Button, x+10 yp hp vBtnFile gSelectFile, ...
Gui, Add, Text, xm y+5 cNavy, Select Output Directory:
Gui, Add, Edit, xm y+5 w400 vOutDir +ReadOnly, %OutDir%
Gui, Add, Button, x+10 yp hp vBtnFolder gSelectFolder, ...
GuiControlGet, P1, Pos, BtnFolder
Gui, Add, Text, xm y+5 cNavy, Script File:
Gui, Add, Edit, xm y+5 w400 vOutFile +ReadOnly
Gui, Add, CheckBox, xm vCreateOnLoad, Create at load-time
Gui, Add, CheckBox, xm vReturnHICON, Return HICON handle
Gui, Add, Button, xm vP2 gConvert, Convert Image
GuiControlGet, P2, Pos
Gui, Add, Button, % "x" . (P1X + P1W - P2W) . " yp wp gShow", Show Script
Gui, Add, StatusBar
Gui, Show, , Convert Image to #Include File
GuiControl, Focus, BtnFile
; Prepare the GUI which will show the generated script on demand
Gui, Script: +Owner1
Gui, Script: Margin, 0, 0
Gui, Script: Font, , Courier New
Gui, Script: Add, Edit, x0 y0 w0 h0
Gui, Script: Add, Edit, % "x0 y0 w" . Round(A_ScreenWidth * 0.8) . " h" . Round(A_ScreenHeight * 0.8)
. " vScriptEdit +hwndHEdit +HScroll"
Gui, Script: Add, StatusBar
Return
; ----------------------------------------------------------------------------------------------------------------------
GuiClose:
ExitApp
; ----------------------------------------------------------------------------------------------------------------------
SelectFile:
Gui, +OwnDialogs
FileSelectFile, ImgFile, 1, %ImgDir%, Select a Picture
, Img (*.bmp; *.emf; *.exif; *.gif; *.ico; *.jpg; *.png; *.tif; *.wmf)
If (ErrorLevel)
Return
GuiControl, , ImgFile, %ImgFile%
SplitPath, ImgFile, , ImgDir, ImgExt, ImgName
ImgName := RegExReplace(ImgName, "[\W]")
ImgName .= "_" . ImgExt
GuiControl, , OutFile, %OutDir%\Create_%ImgName%.ahk
IniWrite, %ImgDir%, %IniFile%, Image2Include, ImgDir
Return
; ----------------------------------------------------------------------------------------------------------------------
SelectFolder:
Gui, +OwnDialogs
FileSelectFolder, OutDir, *%OutDir%, 1, Select a folder to store the scripts:
If (ErrorLevel)
Return
GuiControlGet, ImgFile
GuiControl, , OutDir, %OutDir%
If (ImgFile <> "") {
GuiControl, , OutFile, %OutDir%\Create_%ImgName%.ahk
}
IniWrite, %OutDir%, %IniFile%, Image2Include, OutDir
Return
; ----------------------------------------------------------------------------------------------------------------------
Convert:
SB_SetText("")
Gui, Submit, NoHide
If !FileExist(ImgFile) {
GuiControl, Focus, BtnFile
Return
}
If !InStr(FileExist(OutDir), "d") {
GuiControl, Focus, BtnFolder
Return
}
; -------------------------------------------------------------------------------------------------------------------
; Read the image file
; -------------------------------------------------------------------------------------------------------------------
File := FileOpen(ImgFile, "r")
BinLen := File.Length
File.RawRead(Bin, BinLen)
File.Close()
; -------------------------------------------------------------------------------------------------------------------
; Encode the image file
; -------------------------------------------------------------------------------------------------------------------
DllCall("Crypt32.dll\CryptBinaryToString", "Ptr", &Bin, "UInt", BinLen, "UInt", 0x01, "Ptr", 0, "UIntP", B64Len)
VarSetCapacity(B64, B64Len << !!A_IsUnicode, 0)
DllCall("Crypt32.dll\CryptBinaryToString", "Ptr", &Bin, "UInt", BinLen, "UInt", 0x01, "Ptr", &B64, "UIntP", B64Len)
Bin := ""
VarSetCapacity(Bin, 0)
VarSetCapacity(B64, -1)
B64 := RegExReplace(B64, "\r\n")
B64Len := StrLen(B64)
; -------------------------------------------------------------------------------------------------------------------
; Write the AHK script
; -------------------------------------------------------------------------------------------------------------------
PartLength := 16000
CharsRead := 1
File := FileOpen(OutFile, "w", "UTF-8")
File.Write(Header1 . "`r`nCreate_" . ImgName . "(NewHandle := False) {`r`n")
If (CreateOnLoad)
File.Write("Static hBitmap := Create_" . ImgName . "()`r`n")
Else
File.Write("Static hBitmap := 0`r`n")
File.Write(Header2 . "`r`n")
File.Write("VarSetCapacity(B64, " . StrLen(B64) . " << !!A_IsUnicode)`r`n")
Part := "B64 := """
While (CharsRead < B64Len) {
File.Write(Part . SubStr(B64, CharsRead, PartLength) . """`r`n")
CharsRead += PartLength
If (CharsRead < B64Len)
Part := "B64 .= """
}
File.Write(Footer1 . "`r`n")
If (ReturnHICON)
File.Write("DllCall(""Gdiplus.dll\GdipCreateHICONFromBitmap"", ""Ptr"", pBitmap, ""PtrP"", hBitmap, ""UInt"", 0)`r`n")
Else
File.Write("DllCall(""Gdiplus.dll\GdipCreateHBITMAPFromBitmap"", ""Ptr"", pBitmap, ""PtrP"", hBitmap, ""UInt"", 0)`r`n")
File.Write(Footer2)
File.Close()
SB_SetText(" File " . OutFile . " successfully created!")
Return
; ======================================================================================================================
; Show the generated script
; ======================================================================================================================
Show:
; -------------------------------------------------------------------------------------------------------------------
; Reread the AHK script and show it
; -------------------------------------------------------------------------------------------------------------------
FileRead, B64, %OutFile%
If (ErrorLevel)
Return
FileGetSize, Size, %OutFile%
Gui, Script: Default
GuiControl, , ScriptEdit, %B64%
ControlGet, Lines, LineCount, , , ahk_id %HEDIT%
SB_SetText(" Size: " . Size . " bytes - Lines: " . Lines)
Gui, Show, , %OutFile%
Return
; ----------------------------------------------------------------------------------------------------------------------
ScriptGuiClose:
GuiControl, , ShowEdit
Gui, Hide
Return
#NoEnv
#Include CreateBitmap_ImgProps_png.ahk ; change the name to what you need
SetBatchLines, -1
T := A_TickCount
HBITMAP := CreateBitmap_ImgProps_png() ; change the name to what you need
H := Bitmap_GetHeight(HBITMAP)
W := Bitmap_GetWidth(HBITMAP)
; ----------------------------------------------------------------------------------------------------------------------
Gui, Margin, 0, 0
Gui, Add, Text, x0 y0 w%W% h%H% hwndHPic1
Bitmap_SetImage(HPic1, HBITMAP)
T := A_TickCount - T
Gui, Show, , Included Image - %T% ms
Return
; ----------------------------------------------------------------------------------------------------------------------
GuiClose:
GuiEscape:
ExitApp
; ----------------------------------------------------------------------------------------------------------------------
; 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%
Return ErrorLevel
}
@Ixiko
Copy link

Ixiko commented Apr 29, 2018

Works great! I'm thinking about how to integrate more than one picture to a file. You have an solution?

@rlesch
Copy link

rlesch commented Jun 7, 2020

Does this work with transparent Images like PNG?

ImageSearch doesnt seem to find the image as handle when it has transparency.
so my conclusion is that the transparancy is gone somewhere in the transform process (and seemingly replaced by black as background)

any ideas?

@iPhilip
Copy link

iPhilip commented Jul 31, 2023

A version for AutoHotkey v2 can be found here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment