Page 1 of 1

SavePicture() : Save hBitmap as BMP, JPG, GIF, PNG, TIF

Posted: 04 Sep 2019, 13:54
by SKAN
SavePicture( hBM, sFile )

Note: This function offers limited functionality: JPEG quality is fixed at 75% and transparency will not be preserved for PNG.
Saved file will be a BMP if you pass any file extension other than: BMP, JPG, JPEG, GIF, PNG, TIF, TIFF

Code: Select all

SavePicture(hBM, sFile) {                                            ; By SKAN on D293 @ bit.ly/2krOIc9
Local V,  pBM := VarSetCapacity(V,16,0)>>8,  Ext := LTrim(SubStr(sFile,-3),"."),  E := [0,0,0,0]
Local Enc := 0x557CF400 | Round({"bmp":0, "jpg":1,"jpeg":1,"gif":2,"tif":5,"tiff":5,"png":6}[Ext])
  E[1] := DllCall("gdi32\GetObjectType", "Ptr",hBM ) <> 7
  E[2] := E[1] ? 0 : DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Ptr",hBM, "UInt",0, "PtrP",pBM)
  NumPut(0x2EF31EF8,NumPut(0x0000739A,NumPut(0x11D31A04,NumPut(Enc+0,V,"UInt"),"UInt"),"UInt"),"UInt")
  E[3] := pBM ? DllCall("gdiplus\GdipSaveImageToFile", "Ptr",pBM, "WStr",sFile, "Ptr",&V, "UInt",0) : 1
  E[4] := pBM ? DllCall("gdiplus\GdipDisposeImage", "Ptr",pBM) : 1
Return E[1] ? 0 : E[2] ? -1 : E[3] ? -2 : E[4] ? -3 : 1  
}
  • ErrorLevel


SavePicture() requires GDI+ initialized prior to calling it.
GDI+ can be Start.Shut with GDIP("Startup") and GDIP("Shutdown")
Thanks to @tmplinshi for a bug report. Now fixed.

Code: Select all

GDIP(C:="Startup") {                                      ; By SKAN on D293 @ bit.ly/2krOIc9
  Static SI:=Chr(!(VarSetCapacity(Si,24,0)>>16)), pToken:=0, hMod:=0, Res:=0, AOK:=0
  If (AOK := (C="Startup" and pToken=0) Or (C<>"Startup" and pToken<>0))  {
      If (C="Startup") {
               hMod := DllCall("LoadLibrary", "Str","gdiplus.dll", "Ptr")
               Res  := DllCall("gdiplus\GdiplusStartup", "PtrP",pToken, "Ptr",&SI, "UInt",0)
      } Else { 
               Res  := DllCall("gdiplus\GdiplusShutdown", "Ptr",pToken)
               DllCall("FreeLibrary", "Ptr",hMod),   hMod:=0,   pToken:=0
   }}  
Return (AOK ? !Res : Res:=0)    
}

Usage example

The cryptic nested NumPut explained

The following script will automatically Save picture (JPEG) when PrintScreen / Alt+PrintScreen is used for screen capture.

Code: Screen capture demo

Re: SavePicture() : Save hBitmap as BMP, JPG, GIF, PNG, TIF

Posted: 07 Sep 2019, 00:29
by tmplinshi
Hi, just a bug report for 64-bit AutoHotkey:

The return type of LoadLibrary function should be Ptr, otherwise the calling to FreeLibrary function would be fail.

Code: Select all

MsgBox % DllCall("FreeLibrary", "Ptr",hMod) ? "success" : "fail"

Re: SavePicture() : Save hBitmap as BMP, JPG, GIF, PNG, TIF

Posted: 07 Sep 2019, 03:11
by SKAN
Thank you @tmplinshi :)
Fixed.

Re: SavePicture() : Save hBitmap as BMP, JPG, GIF, PNG, TIF

Posted: 03 Jan 2020, 09:41
by danrevella
Hi,
please excuse for boring, I have look at your tool (and also another in fact this post is replicate over), but I am in search of a script who let me capture and save a full windows who is larger then my desktop: f.e my desktop is 1920*1080 but the window I need to capture is 9400*9200, so if i use PrintScreen or Alt-Printscreen, I obtain an image who only show 1920*1080 instead of 9400*9200.
Does exist a possibility to get the full capture window?
Many thanks

Re: SavePicture() : Save hBitmap as BMP, JPG, GIF, PNG, TIF

Posted: 03 Jan 2020, 10:50
by SKAN
danrevella wrote:
03 Jan 2020, 09:41
f.e my desktop is 1920*1080 but the window I need to capture is 9400*9200
I don't understand how this is possible?
If I try to resize a given window to be larger than desktop, the window is resized only to the size of desktop.
For example, with single monitor setup sized 1366x768, I am not able to resize notepad window to 6000x4000 ?!

Code: Select all

#NoEnv
#Warn
#SingleInstance, Force

Run Notepad
Winwait ahk_class Notepad
WinMove,,, 0, 0, 6000, 4000

Re: SavePicture() : Save hBitmap as BMP, JPG, GIF, PNG, TIF

Posted: 03 Jan 2020, 11:26
by danrevella
It is possible: try this an give any resolution you want to a (resizable) window


; [^ = Ctrl] [+ = Shift] [! = Alt] [# = Win]
;WIN+t hotkey

#t::
WinGet, window, ID, A
InputBox, width, Resize window, Enter width:, , 170, 130
if (width != "")
{
InputBox, height, Resize Window, Enter height:, , 170, 130
}
WinGetTitle, Title, A
MsgBox, The active window is "%Title%".

WinGet, id, , %Title%
Result := DllCall("SetWindowPos", "uint", id, "uint", HWND_TOP, "Int", 0, "Int", 0, "Int", width, "Int", height, "UInt", 0x400)

return


Re: SavePicture() : Save hBitmap as BMP, JPG, GIF, PNG, TIF

Posted: 03 Jan 2020, 14:12
by SKAN
danrevella wrote:
03 Jan 2020, 11:26
It is possible: try this an give any resolution you want to a (resizable) window
Thanks. Nice test code. Nitpick: You haven't defined the constant HWND_TOP which should be 0.

Your snippet doesn't work for all apps though. Maybe those apps have message handlers to override the resize.
Works when tested with Notepad and AutoHotkey help. AutoHotkey spy reveals the window size correctly.

I tried resizing AutoHotkey help to 2000x2000 (My screen is 1366x768) and took a snaphot with hBM := hWnd_to_hBmp( WinExist("A") )
and saved it with SavePicture().
The function is unable to blit the title bar correctly, in Windows 7. Yet to try in Windows 10.
Please refer the attachment

Re: SavePicture() : Save hBitmap as BMP, JPG, GIF, PNG, TIF

Posted: 03 Jan 2020, 14:13
by guest3456
danrevella wrote:
03 Jan 2020, 11:26
It is possible: try this an give any resolution you want to a (resizable) window


; [^ = Ctrl] [+ = Shift] [! = Alt] [# = Win]
;WIN+t hotkey

#t::
WinGet, window, ID, A
InputBox, width, Resize window, Enter width:, , 170, 130
if (width != "")
{
InputBox, height, Resize Window, Enter height:, , 170, 130
}
WinGetTitle, Title, A
MsgBox, The active window is "%Title%".

WinGet, id, , %Title%
Result := DllCall("SetWindowPos", "uint", id, "uint", HWND_TOP, "Int", 0, "Int", 0, "Int", width, "Int", height, "UInt", 0x400)

return

does not work for me. i tried resizing notepad to 9000 width, and it only resized to approx 4800 width, which spanned my two monitors.

you could try PrintWindow() to get the screenshot

Re: SavePicture() : Save hBitmap as BMP, JPG, GIF, PNG, TIF

Posted: 03 Jan 2020, 15:22
by danrevella
SKAN wrote:
03 Jan 2020, 14:12
danrevella wrote:
03 Jan 2020, 11:26
It is possible: try this an give any resolution you want to a (resizable) window
Thanks. Nice test code. Nitpick: You haven't defined the constant HWND_TOP which should be 0.

Your snippet doesn't work for all apps though. Maybe those apps have message handlers to override the resize.
Works when tested with Notepad and AutoHotkey help. AutoHotkey spy reveals the window size correctly.

I tried resizing AutoHotkey help to 2000x2000 (My screen is 1366x768) and took a snaphot with hBM := hWnd_to_hBmp( WinExist("A") )
and saved it with SavePicture().
The function is unable to blit the title bar correctly, in Windows 7. Yet to try in Windows 10.
Please refer the attachment
As I told you, I'm a total beginner in AHK, so please may you post your example with a full working code (also with the necessary dependences?
Many thanks

Re: SavePicture() : Save hBitmap as BMP, JPG, GIF, PNG, TIF

Posted: 03 Jan 2020, 15:24
by danrevella
guest3456 wrote:
03 Jan 2020, 14:13

does not work for me. i tried resizing notepad to 9000 width, and it only resized to approx 4800 width, which spanned my two monitors.

you could try PrintWindow() to get the screenshot
As I told I'm a newbie, may you gentle tell me about PrintWindow(), is it a native function, or is it a library, may you be so kind to give me the necessary code?
Thanks

Re: SavePicture() : Save hBitmap as BMP, JPG, GIF, PNG, TIF

Posted: 04 Jan 2020, 03:04
by SKAN
I have to test this in Windows 10.
I'm leaving city and will be back on Monday.

Re: SavePicture() : Save hBitmap as BMP, JPG, GIF, PNG, TIF

Posted: 04 Jan 2020, 05:48
by danrevella
you told me:
Thanks. Nice test code. Nitpick: You haven't defined the constant HWND_TOP which should be 0.

So may you give me the correction to my code?
See you next week

Re: SavePicture() : Save hBitmap as BMP, JPG, GIF, PNG, TIF

Posted: 22 Feb 2022, 01:52
by jly
Hello, SKAN:
I get the thumbnail of a file as an HBitmap, add it to a Picture control, and the background of the picture is transparent.
If I save it as a .png file with SavePicture functtion, the background of the image file is black.
How can I make the background of the saved picture transparent?

In the following two figures, the first is the image of the saved png file,
and the second is the image displayed in the picture control.

Re: SavePicture() : Save hBitmap as BMP, JPG, GIF, PNG, TIF

Posted: 22 Feb 2022, 04:10
by SKAN
jly wrote:
22 Feb 2022, 01:52
If I save it as a .png file with SavePicture functtion, the background of the image file is black.
Yes. This function is compact and too limited, and I have mentioned it in OP.
If you need to save PNG with transparency, you may have to opt for one of the GDIP variants available in our forum.
Thanks.

Re: SavePicture() : Save hBitmap as BMP, JPG, GIF, PNG, TIF

Posted: 22 Feb 2022, 20:21
by jly
SKAN wrote:
22 Feb 2022, 04:10
jly wrote:
22 Feb 2022, 01:52
If I save it as a .png file with SavePicture functtion, the background of the image file is black.
Yes. This function is compact and too limited, and I have mentioned it in OP.
If you need to save PNG with transparency, you may have to opt for one of the GDIP variants available in our forum.
Thanks.
OK,thank you very much!

Re: SavePicture() : Save hBitmap as BMP, JPG, GIF, PNG, TIF

Posted: 25 Apr 2024, 15:48
by GEOVAN
SKAN wrote:
04 Sep 2019, 13:54
SavePicture( hBM, sFile )

Note: This function offers limited functionality: JPEG quality is fixed at 75% and transparency will not be preserved for PNG.
Saved file will be a BMP if you pass any file extension other than: BMP, JPG, JPEG, GIF, PNG, TIF, TIFF

Code: Select all

SavePicture(hBM, sFile) {                                            ; By SKAN on D293 @ bit.ly/2krOIc9
Local V,  pBM := VarSetCapacity(V,16,0)>>8,  Ext := LTrim(SubStr(sFile,-3),"."),  E := [0,0,0,0]
Local Enc := 0x557CF400 | Round({"bmp":0, "jpg":1,"jpeg":1,"gif":2,"tif":5,"tiff":5,"png":6}[Ext])
  E[1] := DllCall("gdi32\GetObjectType", "Ptr",hBM ) <> 7
  E[2] := E[1] ? 0 : DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Ptr",hBM, "UInt",0, "PtrP",pBM)
  NumPut(0x2EF31EF8,NumPut(0x0000739A,NumPut(0x11D31A04,NumPut(Enc+0,V,"UInt"),"UInt"),"UInt"),"UInt")
  E[3] := pBM ? DllCall("gdiplus\GdipSaveImageToFile", "Ptr",pBM, "WStr",sFile, "Ptr",&V, "UInt",0) : 1
  E[4] := pBM ? DllCall("gdiplus\GdipDisposeImage", "Ptr",pBM) : 1
Return E[1] ? 0 : E[2] ? -1 : E[3] ? -2 : E[4] ? -3 : 1  
}
  • ErrorLevel


SavePicture() requires GDI+ initialized prior to calling it.
GDI+ can be Start.Shut with GDIP("Startup") and GDIP("Shutdown")
Thanks to @tmplinshi for a bug report. Now fixed.

Code: Select all

GDIP(C:="Startup") {                                      ; By SKAN on D293 @ bit.ly/2krOIc9
  Static SI:=Chr(!(VarSetCapacity(Si,24,0)>>16)), pToken:=0, hMod:=0, Res:=0, AOK:=0
  If (AOK := (C="Startup" and pToken=0) Or (C<>"Startup" and pToken<>0))  {
      If (C="Startup") {
               hMod := DllCall("LoadLibrary", "Str","gdiplus.dll", "Ptr")
               Res  := DllCall("gdiplus\GdiplusStartup", "PtrP",pToken, "Ptr",&SI, "UInt",0)
      } Else { 
               Res  := DllCall("gdiplus\GdiplusShutdown", "Ptr",pToken)
               DllCall("FreeLibrary", "Ptr",hMod),   hMod:=0,   pToken:=0
   }}  
Return (AOK ? !Res : Res:=0)    
}

Usage example

The cryptic nested NumPut explained

The following script will automatically Save picture (JPEG) when PrintScreen / Alt+PrintScreen is used for screen capture.

Code: Screen capture demo

Please, how can we modify this wonderful code to get 100% jpg quality instead of 75% ?