How to save image in clipboard.
How to save image in clipboard.
Let say you have an image in your clipboard, how do you save it into PNG?
Re: How to save image in clipboard.
See @SKAN’s ScreenCaptureToPNG in this thread (note there are some forum color tags that need to be removed). I don’t know if he has updated it since then.
Re: How to save image in clipboard.
Code: Select all
^+a::
msgbox, yo
If % SaveClipboardImageAs(BMPF:=A_Temp "\screen.bmp")
msgbox, hi
If % ConvertGraphicsFile(BMPF, (OUTF:=A_Temp "\screen.png"))
Runwait, Rundll32.exe %A_Windir%\system32\shimgvw.dll`,ImageView_Fullscreen %OUTF%
Return
SaveClipboardImageAs(tImg="") {
If ! DllCall("IsClipboardFormatAvailable",UInt,2)
msgbox, failed
Return 0
$:=ClipboardAll
NumPut(0x4D42,$,2), D:=NumGet($,36), NumPut(66+D,$,4), NumPut(0,$,8), NumPut(66,$,12)
If ( (Z:=DllCall("_lcreat",Str,tImg,UInt,0)) = -1
|| DllCall("_lwrite",UInt,Z,UInt,&$+2,UInt,66+D) = -1 || DllCall("_lclose",UInt,Z) = -1 )
Return 0
Return 1
}
ConvertGraphicsFile(Src, Trg, Ov=1) {
Static shlwapi,ShConvertGraphics
If ( D="" )
D:=DllCall("LoadLibrary",Str,"shlwapi.dll"),CG:=DllCall("GetProcAddress",UInt,D,Int,488)
VarSetCapacity(uSrc,(sSz:=StrLen(Src)*2+1)), DllCall("MultiByteToWideChar",Int,0,Int,0
,Str,Src,Int,-1,Str,uSrc,Int,sSz ), VarSetCapacity(uTrg,(tSz:=StrLen(Trg)*2+1))
DllCall("MultiByteToWideChar",Int,0,Int,0,Str,Trg,Int,-1,Str,uTrg,Int,tSz)
Return ! DllCall(CG,Str,uSrc,Str,uTrg,UInt,Ov)
}
return
Last edited by LogicNg on 03 Sep 2021, 05:49, edited 1 time in total.
Re: How to save image in clipboard.
its runnable once u delete all broken old forum tags from it
Re: How to save image in clipboard.
It fails at
Code: Select all
If ! DllCall("IsClipboardFormatAvailable",UInt,2)
Re: How to save image in clipboard.
I'm not getting it to produce an image either. Some things may have changed with Windows or something since this worked.
By the way, the way you edited it, it would have no chance of working as the function will always return 0 and not continue even if the image conversion worked. You can't just insert a MsgBox after an "if" statement and not mess things up. You made the "return 0" statement unconditional by doing that. Your "MsgBox hi" statement similarly makes the "if" statement that follows it execute unconditionally.
By the way, the way you edited it, it would have no chance of working as the function will always return 0 and not continue even if the image conversion worked. You can't just insert a MsgBox after an "if" statement and not mess things up. You made the "return 0" statement unconditional by doing that. Your "MsgBox hi" statement similarly makes the "if" statement that follows it execute unconditionally.
-
- Posts: 4358
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: How to save image in clipboard.
Anyway, using outdated code is not the best choice. As an option:
Code: Select all
destPngFilePath := A_ScriptDir . "\ClipboardImage.png"
hBitmap := GetBitmapFromClipboard()
HBitmapToPng(hBitmap, destPngFilePath)
DllCall("DeleteObject", "Ptr", hBitmap)
Return
GetBitmapFromClipboard() {
if !DllCall("IsClipboardFormatAvailable", "UInt", CF_BITMAP := 2)
throw "There is no image in the Clipboard"
if !DllCall("OpenClipboard", "Ptr", 0)
throw "OpenClipboard failed"
hBitmap := DllCall("GetClipboardData", "UInt", CF_BITMAP)
DllCall("CloseClipboard")
if !hBitmap
throw "GetClipboardData failed"
Return hBitmap
}
HBitmapToPng(hBitmap, destPngFilePath) {
static CLSID_WICImagingFactory := "{CACAF262-9370-4615-A13B-9F5539DA4C0A}"
, IID_IWICImagingFactory := "{EC5EC8A9-C395-4314-9C77-54D7A935FF70}"
, GUID_ContainerFormatPng := "{1B7CFAF4-713F-473C-BBCD-6137425FAEAF}"
, WICBitmapUseAlpha := 0x00000000, GENERIC_WRITE := 0x40000000
, WICBitmapEncoderNoCache := 0x00000002
VarSetCapacity(GUID, 16, 0)
DllCall("Ole32\CLSIDFromString", "WStr", GUID_ContainerFormatPng, "Ptr", &GUID)
IWICImagingFactory := ComObjCreate(CLSID_WICImagingFactory, IID_IWICImagingFactory)
Vtable( IWICImagingFactory , CreateBitmapFromHBITMAP := 21 ).Call("Ptr", hBitmap, "Ptr", 0, "UInt", WICBitmapUseAlpha, "PtrP", IWICBitmap)
Vtable( IWICImagingFactory , CreateStream := 14 ).Call("PtrP", IWICStream)
Vtable( IWICStream , InitializeFromFilename := 15 ).Call("WStr", destPngFilePath, "UInt", GENERIC_WRITE)
Vtable( IWICImagingFactory , CreateEncoder := 8 ).Call("Ptr", &GUID, "Ptr", 0, "PtrP", IWICBitmapEncoder)
Vtable( IWICBitmapEncoder , Initialize := 3 ).Call("Ptr", IWICStream, "UInt", WICBitmapEncoderNoCache)
Vtable( IWICBitmapEncoder , CreateNewFrame := 10 ).Call("PtrP", IWICBitmapFrameEncode, "Ptr", 0)
Vtable( IWICBitmapFrameEncode , Initialize := 3 ).Call("Ptr", 0)
Vtable( IWICBitmapFrameEncode , WriteSource := 11 ).Call("Ptr", IWICBitmap, "Ptr", 0)
Vtable( IWICBitmapFrameEncode , Commit := 12 ).Call()
Vtable( IWICBitmapEncoder , Commit := 11 ).Call()
for k, v in [IWICBitmapFrameEncode, IWICBitmapEncoder, IWICStream, IWICBitmap, IWICImagingFactory]
ObjRelease(v)
}
Vtable(ptr, n) {
return Func("DllCall").Bind(NumGet(NumGet(ptr+0), A_PtrSize*n), "Ptr", ptr)
}
Re: How to save image in clipboard.
@boiler Use too much Python
@teadrinker Your code works! Thank you all for your help!
@teadrinker Your code works! Thank you all for your help!
Re: How to save image in clipboard.
For latecomers, if you want to use the current date and time as filename, try this
Code: Select all
destPngFilePath := A_ScriptDir . "\" . A_Now . ".png"
Re: How to save image in clipboard.
One issue though, normally when you copy an image from MSPaint you can paste it anywhere. When I use @teadrinker's code to save an image copied from MSPaint, it saves a completely white image with exactly the same size as the one I copied, is there a way to fix it?
Re: How to save image in clipboard.
You are damn amazing, with some minor changes I get it working!
Code: Select all
#NoEnv ; Screen capture demo for SavePicture()
#SingleInstance, Force
; Hotkey, PrintScreen, Fullscreen
; Hotkey, !PrintScreen, ActiveWindow
Return ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - // end of auto-execute section
^+a::
Critical, On
hBM := 0
HotKey, %A_ThisHotKey%, Off
; OldClipboard := ClipboardAll
; Clipboard := ""
; SendInput, % (A_ThisLabel="ActiveWindow" ? "!" : "") . "{PrintScreen}"
; ClipWait, 1, 1
hBM := CB_hBMP_Get()
; If (OldClipboard)
; {
; Clipboard := OldClipboard
; }
Critical, Off
If ( hBM )
{
sFile := A_ScriptDir "\\" A_Now ".png"
GDIP("Startup")
SavePicture(hBM, sFile)
GDIP("Shutdown")
DllCall( "DeleteObject", "Ptr",hBM )
If FileExist(sFile)
{
SoundBeep
Run %sFile%
}
}
HotKey, %A_ThisHotKey%, On
Return
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CB_hBMP_Get() { ; By SKAN on D297 @ bit.ly/2L81pmP
Local OK := [0,0,0,0]
OK.1 := DllCall( "OpenClipboard", "Ptr",0 )
OK.2 := OK.1 ? DllCall( "IsClipboardFormatAvailable", "UInt",8 ) : 0 ; CF_BITMAP
OK.3 := OK.2 ? DllCall( "GetClipboardData", "UInt", 2, "Ptr" ) : 0
OK.4 := OK.1 ? DllCall( "CloseClipboard" ) : 0
Return OK.3 ? DllCall( "CopyImage", "Ptr",OK.3, "Int",0, "Int",0, "Int",0, "UInt",0x200C, "Ptr" )
+ ( ErrorLevel := 0 ) : ( ErrorLevel := !OK.2 ? 1 : 2 ) >> 2
}
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SavePicture(hBM, sFile) { ; By SKAN on D293 @ bit.ly/2L81pmP
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
}
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GDIP(C:="Startup") { ; By SKAN on D293 @ bit.ly/2L81pmP
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)
}
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- Posts: 4358
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: How to save image in clipboard.
This variant does not save transparency.
-
- Posts: 4358
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: How to save image in clipboard.
Code: Select all
destPngFilePath := A_ScriptDir . "\ClipboardImage.png"
hBitmap := GetBitmapFromClipboard()
HBitmapToPng(hBitmap, destPngFilePath)
DllCall("DeleteObject", "Ptr", hBitmap)
Return
GetBitmapFromClipboard() {
static CF_BITMAP := 2, CF_DIB := 8, SRCCOPY := 0x00CC0020
if !DllCall("IsClipboardFormatAvailable", "UInt", CF_BITMAP)
throw "There is no image in the Clipboard"
if !DllCall("OpenClipboard", "Ptr", 0)
throw "OpenClipboard failed"
hDIB := DllCall("GetClipboardData", "UInt", CF_DIB, "Ptr")
hBM := DllCall("GetClipboardData", "UInt", CF_BITMAP, "Ptr")
DllCall("CloseClipboard")
if !hDIB
throw "GetClipboardData failed"
pDIB := DllCall("GlobalLock", "Ptr", hDIB, "Ptr")
width := NumGet(pDIB + 4, "UInt")
height := NumGet(pDIB + 8, "UInt")
bpp := NumGet(pDIB + 14, "UShort")
DllCall("GlobalUnlock", "Ptr", pDIB)
hDC := DllCall("CreateCompatibleDC", "Ptr", 0, "Ptr")
oBM := DllCall("SelectObject", "Ptr", hDC, "Ptr", hBM, "Ptr")
hMDC := DllCall("CreateCompatibleDC", "Ptr", 0, "Ptr")
hNewBM := CreateDIBSection(width, -height,, bpp)
oPrevBM := DllCall("SelectObject", "Ptr", hMDC, "Ptr", hNewBM, "Ptr")
DllCall("BitBlt", "Ptr", hMDC, "Int", 0, "Int", 0, "Int", width, "Int", height
, "Ptr", hDC , "Int", 0, "Int", 0, "UInt", SRCCOPY)
DllCall("SelectObject", "Ptr", hDC, "Ptr", oBM, "Ptr")
DllCall("DeleteDC", "Ptr", hDC), DllCall("DeleteObject", "Ptr", hBM)
DllCall("SelectObject", "Ptr", hMDC, "Ptr", oPrevBM, "Ptr")
DllCall("DeleteDC", "Ptr", hMDC)
Return hNewBM
}
CreateDIBSection(w, h, ByRef ppvBits := 0, bpp := 32) {
hDC := DllCall("GetDC", "Ptr", 0, "Ptr")
VarSetCapacity(BITMAPINFO, 40, 0)
NumPut(40 , BITMAPINFO, 0)
NumPut( w , BITMAPINFO, 4)
NumPut( h , BITMAPINFO, 8)
NumPut( 1 , BITMAPINFO, 12)
NumPut(bpp, BITMAPINFO, 14)
hBM := DllCall("CreateDIBSection", "Ptr", hDC, "Ptr", &BITMAPINFO, "UInt", 0
, "PtrP", ppvBits, "Ptr", 0, "UInt", 0, "Ptr")
DllCall("ReleaseDC", "Ptr", 0, "Ptr", hDC)
return hBM
}
HBitmapToPng(hBitmap, destPngFilePath) {
static CLSID_WICImagingFactory := "{CACAF262-9370-4615-A13B-9F5539DA4C0A}"
, IID_IWICImagingFactory := "{EC5EC8A9-C395-4314-9C77-54D7A935FF70}"
, GUID_ContainerFormatPng := "{1B7CFAF4-713F-473C-BBCD-6137425FAEAF}"
, WICBitmapUseAlpha := 0x00000000, GENERIC_WRITE := 0x40000000
, WICBitmapEncoderNoCache := 0x00000002
VarSetCapacity(GUID, 16, 0)
DllCall("Ole32\CLSIDFromString", "WStr", GUID_ContainerFormatPng, "Ptr", &GUID)
IWICImagingFactory := ComObjCreate(CLSID_WICImagingFactory, IID_IWICImagingFactory)
Vtable( IWICImagingFactory , CreateBitmapFromHBITMAP := 21 ).Call("Ptr", hBitmap, "Ptr", 0, "UInt", WICBitmapUseAlpha, "PtrP", IWICBitmap)
Vtable( IWICImagingFactory , CreateStream := 14 ).Call("PtrP", IWICStream)
Vtable( IWICStream , InitializeFromFilename := 15 ).Call("WStr", destPngFilePath, "UInt", GENERIC_WRITE)
Vtable( IWICImagingFactory , CreateEncoder := 8 ).Call("Ptr", &GUID, "Ptr", 0, "PtrP", IWICBitmapEncoder)
Vtable( IWICBitmapEncoder , Initialize := 3 ).Call("Ptr", IWICStream, "UInt", WICBitmapEncoderNoCache)
Vtable( IWICBitmapEncoder , CreateNewFrame := 10 ).Call("PtrP", IWICBitmapFrameEncode, "Ptr", 0)
Vtable( IWICBitmapFrameEncode , Initialize := 3 ).Call("Ptr", 0)
Vtable( IWICBitmapFrameEncode , WriteSource := 11 ).Call("Ptr", IWICBitmap, "Ptr", 0)
Vtable( IWICBitmapFrameEncode , Commit := 12 ).Call()
Vtable( IWICBitmapEncoder , Commit := 11 ).Call()
for k, v in [IWICBitmapFrameEncode, IWICBitmapEncoder, IWICStream, IWICBitmap, IWICImagingFactory]
ObjRelease(v)
}
Vtable(ptr, n) {
return Func("DllCall").Bind(NumGet(NumGet(ptr+0), A_PtrSize*n), "Ptr", ptr)
}
Last edited by teadrinker on 10 Feb 2022, 04:24, edited 1 time in total.
Re: How to save image in clipboard.
You can save hbitmap with transparency without wic.
viewtopic.php?t=63345
viewtopic.php?t=63345
-
- Posts: 4358
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: How to save image in clipboard.
But why?
Re: How to save image in clipboard.
After my testings with wic may be up to 4 times slower.
-
- Posts: 4358
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: How to save image in clipboard.
Have you tested my code as it is? If performance matters, it must be transformed to DllCall(NumGet(NumGet ....
Re: How to save image in clipboard.
I tested as it is.
But I do not see reasons to use wic for such tasks.
Also, what do You mean by saving transparency?
For example Your last code does not save transparency if I copy picture with transparent background from photoshop.
But I do not see reasons to use wic for such tasks.
Also, what do You mean by saving transparency?
For example Your last code does not save transparency if I copy picture with transparent background from photoshop.
-
- Posts: 4358
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: How to save image in clipboard.
Your test was incorrect. Try this one:
Code: Select all
HBitmapToPng(hBitmap, destPngFilePath) {
static CLSID_WICImagingFactory := "{CACAF262-9370-4615-A13B-9F5539DA4C0A}"
, IID_IWICImagingFactory := "{EC5EC8A9-C395-4314-9C77-54D7A935FF70}"
, GUID_ContainerFormatPng := "{1B7CFAF4-713F-473C-BBCD-6137425FAEAF}"
, WICBitmapUseAlpha := 0x00000000, GENERIC_WRITE := 0x40000000
, WICBitmapEncoderNoCache := 0x00000002
VarSetCapacity(GUID, 16, 0)
DllCall("Ole32\CLSIDFromString", "WStr", GUID_ContainerFormatPng, "Ptr", &GUID)
IWICImagingFactory := ComObjCreate(CLSID_WICImagingFactory, IID_IWICImagingFactory)
; IWICImagingFactory::CreateBitmapFromHBITMAP
DllCall(NumGet(NumGet(IWICImagingFactory + 0) + A_PtrSize*21), "Ptr", IWICImagingFactory, "Ptr", hBitmap, "Ptr", 0, "UInt", WICBitmapUseAlpha, "PtrP", IWICBitmap)
; IWICImagingFactory::CreateStream
DllCall(NumGet(NumGet(IWICImagingFactory + 0) + A_PtrSize*14), "Ptr", IWICImagingFactory, "PtrP", IWICStream)
; IWICStream::InitializeFromFilename
DllCall(NumGet(NumGet(IWICStream + 0) + A_PtrSize*15), "Ptr", IWICStream, "WStr", destPngFilePath, "UInt", GENERIC_WRITE)
; IWICImagingFactory::CreateEncoder
DllCall(NumGet(NumGet(IWICImagingFactory + 0) + A_PtrSize*8), "Ptr", IWICImagingFactory, "Ptr", &GUID, "Ptr", 0, "PtrP", IWICBitmapEncoder)
; IWICBitmapEncoder::Initialize
DllCall(NumGet(NumGet(IWICBitmapEncoder + 0) + A_PtrSize*3), "Ptr", IWICBitmapEncoder, "Ptr", IWICStream, "UInt", WICBitmapEncoderNoCache)
; IWICBitmapEncoder::CreateNewFrame
DllCall(NumGet(NumGet(IWICBitmapEncoder + 0) + A_PtrSize*10), "Ptr", IWICBitmapEncoder, "PtrP", IWICBitmapFrameEncode, "Ptr", 0)
; IWICBitmapFrameEncode::Initialize
DllCall(NumGet(NumGet(IWICBitmapFrameEncode + 0) + A_PtrSize*3), "Ptr", IWICBitmapFrameEncode, "Ptr", 0)
; IWICBitmapFrameEncode::WriteSource
DllCall(NumGet(NumGet(IWICBitmapFrameEncode + 0) + A_PtrSize*11), "Ptr", IWICBitmapFrameEncode, "Ptr", IWICBitmap, "Ptr", 0)
; IWICBitmapFrameEncode::Commit
DllCall(NumGet(NumGet(IWICBitmapFrameEncode + 0) + A_PtrSize*12), "Ptr", IWICBitmapFrameEncode)
; IWICBitmapEncoder::Commit
DllCall(NumGet(NumGet(IWICBitmapEncoder + 0) + A_PtrSize*11), "Ptr", IWICBitmapEncoder)
for k, v in [IWICBitmapFrameEncode, IWICBitmapEncoder, IWICStream, IWICBitmap, IWICImagingFactory]
ObjRelease(v)
}
The code works, that's enough. In addition, as I said, WIC works faster, and the size of the resulting file is much smaller. Moreover, this simple and demonstrative example (I mean the previose variant) gives you a possibility to start learninig WIC sintax to use it for more complex tasks.
This is a really odd question! Try right clicking on the image at the top of this page (AHK AutoHotkey Automation. Hotkeys. Scripting.) and choose «copy image». Then launch my script.
Can you provide the code to do it? I failed to paste an image copied from PS to Word saving transparency.
Who is online
Users browsing this forum: Bing [Bot], Chunjee, DRS, slishnevsky, Tio_oddish and 78 guests