Skip to content

Instantly share code, notes, and snippets.

@AHK-just-me
Last active July 31, 2023 19:12
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
}
@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