viewtopic.php?p=418993#p418993
Code: Select all
pDIB := DllCall("GlobalLock", "Ptr", hDIB)
Code: Select all
pDIB := DllCall("GlobalLock", "Ptr", hDIB, "ptr")
Code: Select all
pDIB := DllCall("GlobalLock", "Ptr", hDIB)
Code: Select all
pDIB := DllCall("GlobalLock", "Ptr", hDIB, "ptr")
teadrinker wrote: ↑04 Sep 2021, 06:30Code: 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) }
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) {
gdip := new GDIplus()
pBitmap := gdip.CreateBitmapFromHBITMAP(hBitmap)
gdip.SaveBitmap(pBitmap, destPngFilePath)
gdip.DisposeImage(pBitmap)
}
class GDIplus {
__New() {
this.hLib := DllCall("LoadLibrary", "Str", "gdiplus", "Ptr")
VarSetCapacity(si, 8 + A_PtrSize*2, 0), si := Chr(1)
DllCall("gdiplus\GdiplusStartup", "PtrP", pToken, "Ptr", &si, "Ptr", 0)
this.token := pToken
}
__Delete() {
DllCall("gdiplus\GdiplusShutdown", "Ptr", this.token)
DllCall("FreeLibrary", "Ptr", this.hLib)
}
CreateBitmapFromHBITMAP(hBitmap, Palette=0) {
DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Ptr", hBitmap, "Ptr", Palette, "PtrP", pBitmap)
return pBitmap
}
SaveBitmap(pBitmap, ByRef info, Quality := 75, tobuff := "")
{
; info — if copying to buffer, then file extension, if copying to file, then file path
if tobuff
Extension := info
else
SplitPath, info,,, Extension
if Extension not in BMP,DIB,RLE,JPG,JPEG,JPE,JFIF,GIF,TIF,TIFF,PNG
return -1
DllCall("gdiplus\GdipGetImageEncodersSize", "UintP", nCount, "UintP", nSize)
VarSetCapacity(ci, nSize)
DllCall("gdiplus\GdipGetImageEncoders", "UInt", nCount, "UInt", nSize, "Ptr", &ci)
if !(nCount && nSize)
return -2
Loop, % nCount {
sString := StrGet(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
if !InStr(sString, "*." Extension)
continue
pCodec := &ci+idx
break
}
if !pCodec
return -3
if RegExMatch(Extension, "i)^J(PG|PEG|PE|FIF)$") && Quality != 75 {
DllCall("gdiplus\GdipGetEncoderParameterListSize", "Ptr", pBitmap, "Ptr", pCodec, "UintP", nSize)
VarSetCapacity(EncoderParameters, nSize, 0)
DllCall("gdiplus\GdipGetEncoderParameterList", "Ptr", pBitmap, "Ptr", pCodec, "UInt", nSize, "Ptr", &EncoderParameters)
Loop, % NumGet(EncoderParameters, "UInt")
{
elem := (24+A_PtrSize)*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
if (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6)
{
p := elem+&EncoderParameters-pad-4
NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20, "UInt")), "UInt")
break
}
}
}
if !tobuff
E := DllCall("gdiplus\GdipSaveImageToFile", "Ptr", pBitmap, "WStr", info, "Ptr", pCodec, "UInt", p ? p : 0)
else {
DllCall( "ole32\CreateStreamOnHGlobal", "UInt", 0, "Int", 1, "PtrP", pStream )
if !E := DllCall( "gdiplus\GdipSaveImageToStream", "Ptr", pBitmap, "Ptr", pStream, "Ptr", pCodec, "UInt", p ? p : 0 ) {
DllCall( "ole32\GetHGlobalFromStream", "Ptr", pStream, "PtrP", hData )
pData := DllCall( "GlobalLock", "Ptr", hData, "Ptr" )
nSize := DllCall( "GlobalSize", "Ptr", hData, "Ptr" )
VarSetCapacity( info, 0), VarSetCapacity( info, nSize, 0 )
DllCall( "RtlMoveMemory", "Ptr", &info, "Ptr", pData, "UInt", nSize )
DllCall( "GlobalUnlock", "Ptr", hData )
DllCall( "GlobalFree", "Ptr", hData )
}
ObjRelease(pStream)
}
return E ? -4 : tobuff ? nSize : 0
}
DisposeImage(pBitmap) {
return DllCall("gdiplus\GdipDisposeImage", "Ptr", pBitmap)
}
}
teadrinker wrote: ↑25 Apr 2024, 16:10Perhaps this will work on Windows XP: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) { gdip := new GDIplus() pBitmap := gdip.CreateBitmapFromHBITMAP(hBitmap) gdip.SaveBitmap(pBitmap, destPngFilePath) gdip.DisposeImage(pBitmap) } class GDIplus { __New() { this.hLib := DllCall("LoadLibrary", "Str", "gdiplus", "Ptr") VarSetCapacity(si, 8 + A_PtrSize*2, 0), si := Chr(1) DllCall("gdiplus\GdiplusStartup", "PtrP", pToken, "Ptr", &si, "Ptr", 0) this.token := pToken } __Delete() { DllCall("gdiplus\GdiplusShutdown", "Ptr", this.token) DllCall("FreeLibrary", "Ptr", this.hLib) } CreateBitmapFromHBITMAP(hBitmap, Palette=0) { DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Ptr", hBitmap, "Ptr", Palette, "PtrP", pBitmap) return pBitmap } SaveBitmap(pBitmap, ByRef info, Quality := 75, tobuff := "") { ; info — if copying to buffer, then file extension, if copying to file, then file path if tobuff Extension := info else SplitPath, info,,, Extension if Extension not in BMP,DIB,RLE,JPG,JPEG,JPE,JFIF,GIF,TIF,TIFF,PNG return -1 DllCall("gdiplus\GdipGetImageEncodersSize", "UintP", nCount, "UintP", nSize) VarSetCapacity(ci, nSize) DllCall("gdiplus\GdipGetImageEncoders", "UInt", nCount, "UInt", nSize, "Ptr", &ci) if !(nCount && nSize) return -2 Loop, % nCount { sString := StrGet(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16") if !InStr(sString, "*." Extension) continue pCodec := &ci+idx break } if !pCodec return -3 if RegExMatch(Extension, "i)^J(PG|PEG|PE|FIF)$") && Quality != 75 { DllCall("gdiplus\GdipGetEncoderParameterListSize", "Ptr", pBitmap, "Ptr", pCodec, "UintP", nSize) VarSetCapacity(EncoderParameters, nSize, 0) DllCall("gdiplus\GdipGetEncoderParameterList", "Ptr", pBitmap, "Ptr", pCodec, "UInt", nSize, "Ptr", &EncoderParameters) Loop, % NumGet(EncoderParameters, "UInt") { elem := (24+A_PtrSize)*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0) if (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6) { p := elem+&EncoderParameters-pad-4 NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20, "UInt")), "UInt") break } } } if !tobuff E := DllCall("gdiplus\GdipSaveImageToFile", "Ptr", pBitmap, "WStr", info, "Ptr", pCodec, "UInt", p ? p : 0) else { DllCall( "ole32\CreateStreamOnHGlobal", "UInt", 0, "Int", 1, "PtrP", pStream ) if !E := DllCall( "gdiplus\GdipSaveImageToStream", "Ptr", pBitmap, "Ptr", pStream, "Ptr", pCodec, "UInt", p ? p : 0 ) { DllCall( "ole32\GetHGlobalFromStream", "Ptr", pStream, "PtrP", hData ) pData := DllCall( "GlobalLock", "Ptr", hData, "Ptr" ) nSize := DllCall( "GlobalSize", "Ptr", hData, "Ptr" ) VarSetCapacity( info, 0), VarSetCapacity( info, nSize, 0 ) DllCall( "RtlMoveMemory", "Ptr", &info, "Ptr", pData, "UInt", nSize ) DllCall( "GlobalUnlock", "Ptr", hData ) DllCall( "GlobalFree", "Ptr", hData ) } ObjRelease(pStream) } return E ? -4 : tobuff ? nSize : 0 } DisposeImage(pBitmap) { return DllCall("gdiplus\GdipDisposeImage", "Ptr", pBitmap) } }
Code: Select all
jpegFilePath := A_Desktop . "\MyImageFile.jpeg" ; specify the file path you prefer
quality := 1 ; specify quality from 0 to 1, where 1 is 100%
hBitmap := GetBitmapFromClipboard()
SaveBitmapToJpeg(hBitmap, jpegFilePath, quality)
DllCall("DeleteObject", "Ptr", hBitmap)
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
}
SaveBitmapToJpeg(hBitmap, destJpegFilePath, quality := 0.75) {
static CLSID_WICImagingFactory := "{CACAF262-9370-4615-A13B-9F5539DA4C0A}"
, IID_IWICImagingFactory := "{EC5EC8A9-C395-4314-9C77-54D7A935FF70}"
, GUID_ContainerFormatJpeg := "{19E4A5AA-5662-4FC5-A0C0-1758028E1057}"
, WICBitmapIgnoreAlpha := 0x2, GENERIC_WRITE := 0x40000000, VT_R4 := 0x00000004
, WICBitmapEncoderNoCache := 0x00000002, szPROPBAG2 := 24 + A_PtrSize*2
VarSetCapacity(GUID, 16, 0)
DllCall("Ole32\CLSIDFromString", "WStr", GUID_ContainerFormatJpeg, "Ptr", &GUID)
IWICImagingFactory := ComObjCreate(CLSID_WICImagingFactory, IID_IWICImagingFactory)
Vtable( IWICImagingFactory , CreateBitmapFromHBITMAP := 21 ).Call("Ptr", hBitmap, "Ptr", 0, "UInt", WICBitmapIgnoreAlpha, "PtrP", IWICBitmap)
Vtable( IWICImagingFactory , CreateStream := 14 ).Call("PtrP", IWICStream)
Vtable( IWICStream , InitializeFromFilename := 15 ).Call("WStr", destJpegFilePath, "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, "PtrP", IPropertyBag2)
Vtable( IPropertyBag2 , CountProperties := 5 ).Call("UIntP", count)
VarSetCapacity(arrPROPBAG2 , szPROPBAG2*count, 0)
Vtable( IPropertyBag2 , GetPropertyInfo := 6 ).Call("UInt", 0, "UInt", count, "Ptr", &arrPROPBAG2, "UIntP", read)
Loop % read
addr := &arrPROPBAG2 + szPROPBAG2*(A_Index - 1)
until StrGet(NumGet(addr + 8 + A_PtrSize)) = "ImageQuality" && found := true
if found {
VarSetCapacity(variant, 24, 0)
NumPut(VT_R4, variant)
NumPut(quality, variant, 8, "Float")
Vtable( IPropertyBag2, Write := 4 ).Call("UInt", 1, "Ptr", addr, "Ptr", &variant)
}
Vtable( IWICBitmapFrameEncode , Initialize := 3 ).Call("Ptr", IPropertyBag2)
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, IPropertyBag2, IWICStream, IWICBitmap, IWICImagingFactory]
ObjRelease(v)
}
Vtable(ptr, n) {
return Func("DllCall").Bind(NumGet(NumGet(ptr+0), A_PtrSize*n), "Ptr", ptr)
}
Code: Select all
SaveBitmapFromClipboard(A_ScriptDir . "\ClipboardImage.jpg", 100)
SaveBitmapFromClipboard(destImageFilePath, jpegQuality := 75) {
hBitmap := GetBitmapFromClipboard()
HBitmapToImageFile(hBitmap, destImageFilePath, 100)
DllCall("DeleteObject", "Ptr", hBitmap)
}
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
}
HBitmapToImageFile(hBitmap, destImageFilePath, jpegQuality := 75) {
gdip := new GDIplus()
pBitmap := gdip.CreateBitmapFromHBITMAP(hBitmap)
gdip.SaveBitmap(pBitmap, destImageFilePath, jpegQuality)
gdip.DisposeImage(pBitmap)
}
class GDIplus {
__New() {
this.hLib := DllCall("LoadLibrary", "Str", "gdiplus", "Ptr")
VarSetCapacity(si, 8 + A_PtrSize*2, 0), si := Chr(1)
DllCall("gdiplus\GdiplusStartup", "PtrP", pToken, "Ptr", &si, "Ptr", 0)
this.token := pToken
}
__Delete() {
DllCall("gdiplus\GdiplusShutdown", "Ptr", this.token)
DllCall("FreeLibrary", "Ptr", this.hLib)
}
CreateBitmapFromHBITMAP(hBitmap, Palette=0) {
DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Ptr", hBitmap, "Ptr", Palette, "PtrP", pBitmap)
return pBitmap
}
SaveBitmap(pBitmap, ByRef info, Quality := 75, tobuff := "")
{
; info — if copying to buffer, then file extension, if copying to file, then file path
if tobuff
Extension := info
else
SplitPath, info,,, Extension
if Extension not in BMP,DIB,RLE,JPG,JPEG,JPE,JFIF,GIF,TIF,TIFF,PNG
return -1
DllCall("gdiplus\GdipGetImageEncodersSize", "UintP", nCount, "UintP", nSize)
VarSetCapacity(ci, nSize)
DllCall("gdiplus\GdipGetImageEncoders", "UInt", nCount, "UInt", nSize, "Ptr", &ci)
if !(nCount && nSize)
return -2
Loop, % nCount {
sString := StrGet(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
if !InStr(sString, "*." Extension)
continue
pCodec := &ci+idx
break
}
if !pCodec
return -3
if RegExMatch(Extension, "i)^J(PG|PEG|PE|FIF)$") && Quality != 75 {
DllCall("gdiplus\GdipGetEncoderParameterListSize", "Ptr", pBitmap, "Ptr", pCodec, "UintP", nSize)
VarSetCapacity(EncoderParameters, nSize, 0)
DllCall("gdiplus\GdipGetEncoderParameterList", "Ptr", pBitmap, "Ptr", pCodec, "UInt", nSize, "Ptr", &EncoderParameters)
Loop, % NumGet(EncoderParameters, "UInt")
{
elem := (24+A_PtrSize)*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
if (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6)
{
p := elem+&EncoderParameters-pad-4
NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20, "UInt")), "UInt")
break
}
}
}
if !tobuff
E := DllCall("gdiplus\GdipSaveImageToFile", "Ptr", pBitmap, "WStr", info, "Ptr", pCodec, "UInt", p ? p : 0)
else {
DllCall( "ole32\CreateStreamOnHGlobal", "UInt", 0, "Int", 1, "PtrP", pStream )
if !E := DllCall( "gdiplus\GdipSaveImageToStream", "Ptr", pBitmap, "Ptr", pStream, "Ptr", pCodec, "UInt", p ? p : 0 ) {
DllCall( "ole32\GetHGlobalFromStream", "Ptr", pStream, "PtrP", hData )
pData := DllCall( "GlobalLock", "Ptr", hData, "Ptr" )
nSize := DllCall( "GlobalSize", "Ptr", hData, "Ptr" )
VarSetCapacity( info, 0), VarSetCapacity( info, nSize, 0 )
DllCall( "RtlMoveMemory", "Ptr", &info, "Ptr", pData, "UInt", nSize )
DllCall( "GlobalUnlock", "Ptr", hData )
DllCall( "GlobalFree", "Ptr", hData )
}
ObjRelease(pStream)
}
return E ? -4 : tobuff ? nSize : 0
}
DisposeImage(pBitmap) {
return DllCall("gdiplus\GdipDisposeImage", "Ptr", pBitmap)
}
}
Code: Select all
hBM := CB_hBMP_Get()
sFile := A_ScriptDir "\\" A_Now ".jpg" ; you can also save as jpg but quality = 75
GDIP("Startup")
SavePicture(hBM, sFile)
GDIP("Shutdown")
DllCall( "DeleteObject", "Ptr",hBM )
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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)
}
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Understood. In fact, saving a JPEG at 75% quality doesn't require any special steps since it's the default setting. But if you need to change the quality, additional actions are required. In my code the following lines are responsible for this:teadrinker wrote: ↑I am sure that there is a "line" in the code that can modify the code to always save JPG as 100% qaulity.
Just for educational purposes, i will appreciate if you can point me what is the part of the code that changes the 75 to 100%.
Code: Select all
if RegExMatch(Extension, "i)^J(PG|PEG|PE|FIF)$") && Quality != 75 {
DllCall("gdiplus\GdipGetEncoderParameterListSize", "Ptr", pBitmap, "Ptr", pCodec, "UintP", nSize)
VarSetCapacity(EncoderParameters, nSize, 0)
DllCall("gdiplus\GdipGetEncoderParameterList", "Ptr", pBitmap, "Ptr", pCodec, "UInt", nSize, "Ptr", &EncoderParameters)
Loop, % NumGet(EncoderParameters, "UInt")
{
elem := (24+A_PtrSize)*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
if (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6)
{
p := elem+&EncoderParameters-pad-4
NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20, "UInt")), "UInt")
break
}
}
}
Code: Select all
F2:: ; press F2 to save screenshot
hBM := ""
hBM := GDI_CaptureScreen( 0, 0, A_ScreenWidth, A_ScreenHeight )
SaveToImageFile(hBM, A_ScriptDir . "\ClipboardImage.jpg", 100)
DllCall("DeleteObject", "Ptr", hBM) ; Clean-up
Return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GDI_CaptureScreen( X, Y, W, H, ByRef Checksum="" ) {
tDC := DllCall( "CreateCompatibleDC", UInt,0 )
hBM := DllCall( "CopyImage", UInt,DllCall( "CreateBitmap", Int,W, Int,H, UInt,1, UInt,24
, UInt,0 ), UInt,0, Int,0, Int,0, UInt,0x2008, UInt )
oBM := DllCall( "SelectObject", UInt,tDC, UInt,hBM ), hDC := DllCall( "GetDC", UInt,0 )
DllCall( "BitBlt"
, UInt,tDC, UInt,0, UInt,0, Int,W, Int,H, UInt,hDC, UInt,X, UInt,Y, UInt,0x00CC0020 )
DllCall( "ReleaseDC", UInt,0, UInt,hDC ), DllCall( "SelectObject", UInt,tDC, UInt,oBM )
If ( Checksum <> "" )
VarSetCapacity( BM,24,0 ), DllCall( "GetObject", UInt,hBM, UInt,24, UInt,&BM )
, DllCall( "shlwapi\HashData", UInt,NumGet(BM,20), UInt,NumGet( BM,12 )*NumGet( BM,8 )
, Int64P,Checksum, UInt,7 )
Return hBM, DllCall( "DeleteDC", UInt,tDC )
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SaveToImageFile(hBM, destImageFilePath, jpegQuality := 75) {
gdip := new GDIplus()
pBM := gdip.CreateBitmapFromHBITMAP(hBM)
gdip.SaveBitmap(pBM, destImageFilePath, jpegQuality)
gdip.DisposeImage(pBM)
}
class GDIplus {
__New() {
this.hLib := DllCall("LoadLibrary", "Str", "gdiplus", "Ptr")
VarSetCapacity(si, 8 + A_PtrSize*2, 0), si := Chr(1)
DllCall("gdiplus\GdiplusStartup", "PtrP", pToken, "Ptr", &si, "Ptr", 0)
this.token := pToken
}
__Delete() {
DllCall("gdiplus\GdiplusShutdown", "Ptr", this.token)
DllCall("FreeLibrary", "Ptr", this.hLib)
}
CreateBitmapFromHBITMAP(hBM, Palette=0) {
DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Ptr", hBM, "Ptr", Palette, "PtrP", pBM)
return pBM
}
SaveBitmap(pBM, ByRef info, Quality := 75, tobuff := "")
{
; info — if copying to buffer, then file extension, if copying to file, then file path
if tobuff
Extension := info
else
SplitPath, info,,, Extension
if Extension not in BMP,DIB,RLE,JPG,JPEG,JPE,JFIF,GIF,TIF,TIFF,PNG
return -1
DllCall("gdiplus\GdipGetImageEncodersSize", "UintP", nCount, "UintP", nSize)
VarSetCapacity(ci, nSize)
DllCall("gdiplus\GdipGetImageEncoders", "UInt", nCount, "UInt", nSize, "Ptr", &ci)
if !(nCount && nSize)
return -2
Loop, % nCount {
sString := StrGet(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
if !InStr(sString, "*." Extension)
continue
pCodec := &ci+idx
break
}
if !pCodec
return -3
if RegExMatch(Extension, "i)^J(PG|PEG|PE|FIF)$") && Quality != 75 {
DllCall("gdiplus\GdipGetEncoderParameterListSize", "Ptr", pBM, "Ptr", pCodec, "UintP", nSize)
VarSetCapacity(EncoderParameters, nSize, 0)
DllCall("gdiplus\GdipGetEncoderParameterList", "Ptr", pBM, "Ptr", pCodec, "UInt", nSize, "Ptr", &EncoderParameters)
Loop, % NumGet(EncoderParameters, "UInt")
{
elem := (24+A_PtrSize)*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
if (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6)
{
p := elem+&EncoderParameters-pad-4
NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20, "UInt")), "UInt")
break
}
}
}
if !tobuff
E := DllCall("gdiplus\GdipSaveImageToFile", "Ptr", pBM, "WStr", info, "Ptr", pCodec, "UInt", p ? p : 0)
else {
DllCall( "ole32\CreateStreamOnHGlobal", "UInt", 0, "Int", 1, "PtrP", pStream )
if !E := DllCall( "gdiplus\GdipSaveImageToStream", "Ptr", pBM, "Ptr", pStream, "Ptr", pCodec, "UInt", p ? p : 0 ) {
DllCall( "ole32\GetHGlobalFromStream", "Ptr", pStream, "PtrP", hData )
pData := DllCall( "GlobalLock", "Ptr", hData, "Ptr" )
nSize := DllCall( "GlobalSize", "Ptr", hData, "Ptr" )
VarSetCapacity( info, 0), VarSetCapacity( info, nSize, 0 )
DllCall( "RtlMoveMemory", "Ptr", &info, "Ptr", pData, "UInt", nSize )
DllCall( "GlobalUnlock", "Ptr", hData )
DllCall( "GlobalFree", "Ptr", hData )
}
ObjRelease(pStream)
}
return E ? -4 : tobuff ? nSize : 0
}
DisposeImage(pBM) {
return DllCall("gdiplus\GdipDisposeImage", "Ptr", pBM)
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Yes, it's ok.
No, the DeleteObject() function is not intended for this data type. Resource freeing has already been done in the gdip.DisposeImage(pBM) line.
Code: Select all
GDI_CaptureScreen(X, Y, W, H) {
static flags := (SRCCOPY := 0x00CC0020) | (CAPTUREBLT := 0x40000000)
hDC := DllCall("GetDC", "Ptr", 0, "Ptr")
hBM := DllCall("CreateCompatibleBitmap", "Ptr", hDC, "Int", W, "Int", H, "Ptr")
hMDC := DllCall("CreateCompatibleDC", "Ptr", hDC, "Ptr")
hObj := DllCall("SelectObject", "Ptr", hMDC, "Ptr", hBM, "Ptr")
DllCall("BitBlt", "Ptr", hMDC, "Int", 0, "Int", 0, "Int", W, "Int", H
, "Ptr", hDC, "Int", X, "Int", Y, "UInt", flags)
DllCall("SelectObject", "Ptr", hMDC, "Ptr", hObj, "Ptr")
DllCall("DeleteDC", "Ptr", hMDC)
DllCall("ReleaseDC", "Ptr", 0, "Ptr", hDC)
Return hBM
}
Code: Select all
F2:: ; press F2 to save screenshot
hBM := ""
hBM := GDI_CaptureScreen( 0, 0, A_ScreenWidth, A_ScreenHeight )
SaveToImageFile(hBM, A_ScriptDir . "\ScreenshotImage.jpg", 100)
DllCall("DeleteObject", "Ptr", hBM) ; Clean-up
Return
F3:: ; press F3 to load screenshot to clipboard
Clipboard := ; Clear the clipboard
GDI_CaptureScreenToClipboard(0, 0, A_ScreenWidth, A_ScreenHeight)
DllCall("DeleteObject", "Ptr", hBM) ; Clean-up
Return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GDI_CaptureScreen(X, Y, W, H) {
static flags := (SRCCOPY := 0x00CC0020) | (CAPTUREBLT := 0x40000000)
hDC := DllCall("GetDC", "Ptr", 0, "Ptr")
hBM := DllCall("CreateCompatibleBitmap", "Ptr", hDC, "Int", W, "Int", H, "Ptr")
hMDC := DllCall("CreateCompatibleDC", "Ptr", hDC, "Ptr")
hObj := DllCall("SelectObject", "Ptr", hMDC, "Ptr", hBM, "Ptr")
DllCall("BitBlt", "Ptr", hMDC, "Int", 0, "Int", 0, "Int", W, "Int", H
, "Ptr", hDC, "Int", X, "Int", Y, "UInt", flags)
DllCall("SelectObject", "Ptr", hMDC, "Ptr", hObj, "Ptr")
DllCall("DeleteDC", "Ptr", hMDC)
DllCall("ReleaseDC", "Ptr", 0, "Ptr", hDC)
Return hBM
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SaveToImageFile(hBM, destImageFilePath, jpegQuality := 75) {
gdip := new GDIplus()
pBM := gdip.CreateBitmapFromHBITMAP(hBM)
gdip.SaveBitmap(pBM, destImageFilePath, jpegQuality)
gdip.DisposeImage(pBM)
}
class GDIplus {
__New() {
this.hLib := DllCall("LoadLibrary", "Str", "gdiplus", "Ptr")
VarSetCapacity(si, 8 + A_PtrSize*2, 0), si := Chr(1)
DllCall("gdiplus\GdiplusStartup", "PtrP", pToken, "Ptr", &si, "Ptr", 0)
this.token := pToken
}
__Delete() {
DllCall("gdiplus\GdiplusShutdown", "Ptr", this.token)
DllCall("FreeLibrary", "Ptr", this.hLib)
}
CreateBitmapFromHBITMAP(hBM, Palette=0) {
DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Ptr", hBM, "Ptr", Palette, "PtrP", pBM)
return pBM
}
SaveBitmap(pBM, ByRef info, Quality := 75, tobuff := "")
{
; info — if copying to buffer, then file extension, if copying to file, then file path
if tobuff
Extension := info
else
SplitPath, info,,, Extension
if Extension not in BMP,DIB,RLE,JPG,JPEG,JPE,JFIF,GIF,TIF,TIFF,PNG
return -1
DllCall("gdiplus\GdipGetImageEncodersSize", "UintP", nCount, "UintP", nSize)
VarSetCapacity(ci, nSize)
DllCall("gdiplus\GdipGetImageEncoders", "UInt", nCount, "UInt", nSize, "Ptr", &ci)
if !(nCount && nSize)
return -2
Loop, % nCount {
sString := StrGet(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
if !InStr(sString, "*." Extension)
continue
pCodec := &ci+idx
break
}
if !pCodec
return -3
if RegExMatch(Extension, "i)^J(PG|PEG|PE|FIF)$") && Quality != 75 {
DllCall("gdiplus\GdipGetEncoderParameterListSize", "Ptr", pBM, "Ptr", pCodec, "UintP", nSize)
VarSetCapacity(EncoderParameters, nSize, 0)
DllCall("gdiplus\GdipGetEncoderParameterList", "Ptr", pBM, "Ptr", pCodec, "UInt", nSize, "Ptr", &EncoderParameters)
Loop, % NumGet(EncoderParameters, "UInt")
{
elem := (24+A_PtrSize)*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
if (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6)
{
p := elem+&EncoderParameters-pad-4
NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20, "UInt")), "UInt")
break
}
}
}
if !tobuff
E := DllCall("gdiplus\GdipSaveImageToFile", "Ptr", pBM, "WStr", info, "Ptr", pCodec, "UInt", p ? p : 0)
else {
DllCall( "ole32\CreateStreamOnHGlobal", "UInt", 0, "Int", 1, "PtrP", pStream )
if !E := DllCall( "gdiplus\GdipSaveImageToStream", "Ptr", pBM, "Ptr", pStream, "Ptr", pCodec, "UInt", p ? p : 0 ) {
DllCall( "ole32\GetHGlobalFromStream", "Ptr", pStream, "PtrP", hData )
pData := DllCall( "GlobalLock", "Ptr", hData, "Ptr" )
nSize := DllCall( "GlobalSize", "Ptr", hData, "Ptr" )
VarSetCapacity( info, 0), VarSetCapacity( info, nSize, 0 )
DllCall( "RtlMoveMemory", "Ptr", &info, "Ptr", pData, "UInt", nSize )
DllCall( "GlobalUnlock", "Ptr", hData )
DllCall( "GlobalFree", "Ptr", hData )
}
ObjRelease(pStream)
}
return E ? -4 : tobuff ? nSize : 0
}
DisposeImage(pBM) {
return DllCall("gdiplus\GdipDisposeImage", "Ptr", pBM)
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GDI_CaptureScreenToClipboard( X, Y, W, H) {
Static SizeOfDIB := A_PtrSize = 8 ? 104 : 84 ; DIBSECTION
Static SizeOfBM := A_PtrSize = 8 ? 32 : 24 ; BITMAP
Static SizeOfBIH := 40 ; BITMAPINFOHEADER
Static OffBits := A_PtrSize = 8 ? 24 : 20 ; BITMAP -> bmBits
Static OffSize := A_PtrSize = 8 ? 52 : 44 ; BITMAPINFOHEADER -> biSizeImage
Local
hDC := DllCall("GetDC", "Ptr", 0, "UPtr")
cDC := DllCall("CreateCompatibleDC", "Ptr", hDC, "UPtr")
hBM := DllCall("CreateCompatibleBitmap", "Ptr", hDC, "Int", W, "Int", H, "UPtr")
hBM := DllCall("CopyImage", "Ptr", hBM, "UInt", 0, "Int", 0, "Int", 0, "UInt", 0x2008, "UPtr")
oBM := DllCall("SelectObject", "Ptr", cDC, "Ptr", hBM, "UPtr")
DllCall("BitBlt", "Ptr", cDC, "Int", 0, "Int", 0, "Int", W, "Int", H
, "Ptr", hDC, "Int", X, "Int", Y, "UInt", 0x40CC0020)
DllCall("SelectObject", "Ptr", cDC, "Ptr", oBM)
DllCall("DeleteDC", "Ptr", tDC)
DllCall("ReleaseDC", "Ptr", 0, "Ptr", hDC)
VarSetCapacity(DIB, SizeOfDIB, 0) ; DIBSECTION
DllCall("GetObject", "Ptr", hBM, "Int", SizeOfDIB, "Ptr", &DIB)
Size := NumGet(DIB, OffSize, "UInt")
Bits := NumGet(DIB, OffBits, "UPtr")
hDIB := DllCall("GlobalAlloc", "UInt", 2, "UInt", SizeOfBIH + Size, "UPtr")
pDIB := DllCall("GlobalLock", "Ptr", hDIB, "UPtr")
DllCall("RtlMoveMemory", "Ptr", pDIB, "Ptr", &DIB + SizeOfBM, "UInt", SizeOfBIH)
DllCall("RtlMoveMemory", "Ptr", pDIB + SizeOfBIH, "Ptr", Bits, "UInt", Size)
DllCall("GlobalUnlock", "Ptr", hDIB)
DllCall("DeleteObject", "Ptr", hBM)
DllCall("OpenClipboard", "Ptr", 0)
DllCall("EmptyClipboard")
DllCall("SetClipboardData", "UInt", 8, "Ptr", hDIB)
DllCall("CloseClipboard")
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
These linesGEOVAN wrote: ↑Code: Select all
F3:: ; press F3 to load screenshot to clipboard Clipboard := ; Clear the clipboard GDI_CaptureScreenToClipboard(0, 0, A_ScreenWidth, A_ScreenHeight) DllCall("DeleteObject", "Ptr", hBM) ; Clean-up Return
Code: Select all
Clipboard := ; Clear the clipboard
DllCall("DeleteObject", "Ptr", hBM) ; Clean-up
Code: Select all
DllCall("DeleteObject", "Ptr", hBM) ; Clean-up
Code: Select all
F2:: ; press F2 to save screenshot
hBM := ""
hBM := GDI_CaptureScreen( 0, 0, A_ScreenWidth, A_ScreenHeight )
SaveToImageFile(hBM, A_ScriptDir . "\ScreenshotImage.jpg", 100)
DllCall("DeleteObject", "Ptr", hBM) ; Clean-up
Return
F3:: ; press F3 to load screenshot to clipboard
GDI_CaptureScreenToClipboard(0, 0, A_ScreenWidth, A_ScreenHeight)
Return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GDI_CaptureScreen(X, Y, W, H) {
static flags := (SRCCOPY := 0x00CC0020) | (CAPTUREBLT := 0x40000000)
hDC := DllCall("GetDC", "Ptr", 0, "Ptr")
hBM := DllCall("CreateCompatibleBitmap", "Ptr", hDC, "Int", W, "Int", H, "Ptr")
hMDC := DllCall("CreateCompatibleDC", "Ptr", hDC, "Ptr")
hObj := DllCall("SelectObject", "Ptr", hMDC, "Ptr", hBM, "Ptr")
DllCall("BitBlt", "Ptr", hMDC, "Int", 0, "Int", 0, "Int", W, "Int", H
, "Ptr", hDC, "Int", X, "Int", Y, "UInt", flags)
DllCall("SelectObject", "Ptr", hMDC, "Ptr", hObj, "Ptr")
DllCall("DeleteDC", "Ptr", hMDC)
DllCall("ReleaseDC", "Ptr", 0, "Ptr", hDC)
Return hBM
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SaveToImageFile(hBitmap, destImageFilePath, jpegQuality := 75) {
gdip := new GDIplus()
pBitmap := gdip.CreateBitmapFromHBITMAP(hBitmap)
gdip.SaveBitmap(pBitmap, destImageFilePath, jpegQuality)
gdip.DisposeImage(pBitmap)
}
class GDIplus {
__New() {
this.hLib := DllCall("LoadLibrary", "Str", "gdiplus", "Ptr")
VarSetCapacity(si, 8 + A_PtrSize*2, 0), si := Chr(1)
DllCall("gdiplus\GdiplusStartup", "PtrP", pToken, "Ptr", &si, "Ptr", 0)
this.token := pToken
}
__Delete() {
DllCall("gdiplus\GdiplusShutdown", "Ptr", this.token)
DllCall("FreeLibrary", "Ptr", this.hLib)
}
CreateBitmapFromHBITMAP(hBitmap, Palette=0) {
DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Ptr", hBitmap, "Ptr", Palette, "PtrP", pBitmap)
return pBitmap
}
SaveBitmap(pBitmap, ByRef info, Quality := 75, tobuff := "")
{
; info — if copying to buffer, then file extension, if copying to file, then file path
if tobuff
Extension := info
else
SplitPath, info,,, Extension
if Extension not in BMP,DIB,RLE,JPG,JPEG,JPE,JFIF,GIF,TIF,TIFF,PNG
return -1
DllCall("gdiplus\GdipGetImageEncodersSize", "UintP", nCount, "UintP", nSize)
VarSetCapacity(ci, nSize)
DllCall("gdiplus\GdipGetImageEncoders", "UInt", nCount, "UInt", nSize, "Ptr", &ci)
if !(nCount && nSize)
return -2
Loop, % nCount {
sString := StrGet(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
if !InStr(sString, "*." Extension)
continue
pCodec := &ci+idx
break
}
if !pCodec
return -3
if RegExMatch(Extension, "i)^J(PG|PEG|PE|FIF)$") && Quality != 75 {
DllCall("gdiplus\GdipGetEncoderParameterListSize", "Ptr", pBitmap, "Ptr", pCodec, "UintP", nSize)
VarSetCapacity(EncoderParameters, nSize, 0)
DllCall("gdiplus\GdipGetEncoderParameterList", "Ptr", pBitmap, "Ptr", pCodec, "UInt", nSize, "Ptr", &EncoderParameters)
Loop, % NumGet(EncoderParameters, "UInt")
{
elem := (24+A_PtrSize)*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
if (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6)
{
p := elem+&EncoderParameters-pad-4
NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20, "UInt")), "UInt")
break
}
}
}
if !tobuff
E := DllCall("gdiplus\GdipSaveImageToFile", "Ptr", pBitmap, "WStr", info, "Ptr", pCodec, "UInt", p ? p : 0)
else {
DllCall( "ole32\CreateStreamOnHGlobal", "UInt", 0, "Int", 1, "PtrP", pStream )
if !E := DllCall( "gdiplus\GdipSaveImageToStream", "Ptr", pBitmap, "Ptr", pStream, "Ptr", pCodec, "UInt", p ? p : 0 ) {
DllCall( "ole32\GetHGlobalFromStream", "Ptr", pStream, "PtrP", hData )
pData := DllCall( "GlobalLock", "Ptr", hData, "Ptr" )
nSize := DllCall( "GlobalSize", "Ptr", hData, "Ptr" )
VarSetCapacity( info, 0), VarSetCapacity( info, nSize, 0 )
DllCall( "RtlMoveMemory", "Ptr", &info, "Ptr", pData, "UInt", nSize )
DllCall( "GlobalUnlock", "Ptr", hData )
DllCall( "GlobalFree", "Ptr", hData )
}
ObjRelease(pStream)
}
return E ? -4 : tobuff ? nSize : 0
}
DisposeImage(pBitmap) {
return DllCall("gdiplus\GdipDisposeImage", "Ptr", pBitmap)
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GDI_CaptureScreenToClipboard( X, Y, W, H) {
Static SizeOfDIB := A_PtrSize = 8 ? 104 : 84 ; DIBSECTION
Static SizeOfBM := A_PtrSize = 8 ? 32 : 24 ; BITMAP
Static SizeOfBIH := 40 ; BITMAPINFOHEADER
Static OffBits := A_PtrSize = 8 ? 24 : 20 ; BITMAP -> bmBits
Static OffSize := A_PtrSize = 8 ? 52 : 44 ; BITMAPINFOHEADER -> biSizeImage
Local
hDC := DllCall("GetDC", "Ptr", 0, "UPtr")
cDC := DllCall("CreateCompatibleDC", "Ptr", hDC, "UPtr")
hBM := DllCall("CreateCompatibleBitmap", "Ptr", hDC, "Int", W, "Int", H, "UPtr")
hBM := DllCall("CopyImage", "Ptr", hBM, "UInt", 0, "Int", 0, "Int", 0, "UInt", 0x2008, "UPtr")
oBM := DllCall("SelectObject", "Ptr", cDC, "Ptr", hBM, "UPtr")
DllCall("BitBlt", "Ptr", cDC, "Int", 0, "Int", 0, "Int", W, "Int", H
, "Ptr", hDC, "Int", X, "Int", Y, "UInt", 0x40CC0020)
DllCall("SelectObject", "Ptr", cDC, "Ptr", oBM)
DllCall("DeleteDC", "Ptr", tDC)
DllCall("ReleaseDC", "Ptr", 0, "Ptr", hDC)
VarSetCapacity(DIB, SizeOfDIB, 0) ; DIBSECTION
DllCall("GetObject", "Ptr", hBM, "Int", SizeOfDIB, "Ptr", &DIB)
Size := NumGet(DIB, OffSize, "UInt")
Bits := NumGet(DIB, OffBits, "UPtr")
hDIB := DllCall("GlobalAlloc", "UInt", 2, "UInt", SizeOfBIH + Size, "UPtr")
pDIB := DllCall("GlobalLock", "Ptr", hDIB, "UPtr")
DllCall("RtlMoveMemory", "Ptr", pDIB, "Ptr", &DIB + SizeOfBM, "UInt", SizeOfBIH)
DllCall("RtlMoveMemory", "Ptr", pDIB + SizeOfBIH, "Ptr", Bits, "UInt", Size)
DllCall("GlobalUnlock", "Ptr", hDIB)
DllCall("DeleteObject", "Ptr", hBM)
DllCall("OpenClipboard", "Ptr", 0)
DllCall("EmptyClipboard")
DllCall("SetClipboardData", "UInt", 8, "Ptr", hDIB)
DllCall("CloseClipboard")
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Code: Select all
F2:: ; press F2 to save screenshot
hBM := ""
hBM := GDI_CaptureScreen( 0, 0, A_ScreenWidth, A_ScreenHeight )
SaveToImageFile(hBM, A_ScriptDir . "\ScreenshotImage.jpg", 100)
DllCall("DeleteObject", "Ptr", hBM) ; Clean-up
Return
F3:: ; press F3 to load screenshot to clipboard
GDI_CaptureScreenToClipboard(0, 0, A_ScreenWidth, A_ScreenHeight)
Return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GDI_CaptureScreen(X, Y, W, H) {
static flags := (SRCCOPY := 0x00CC0020) | (CAPTUREBLT := 0x40000000)
hDC := DllCall("GetDC", "Ptr", 0, "Ptr")
hBM := DllCall("CreateCompatibleBitmap", "Ptr", hDC, "Int", W, "Int", H, "Ptr")
hMDC := DllCall("CreateCompatibleDC", "Ptr", hDC, "Ptr")
hObj := DllCall("SelectObject", "Ptr", hMDC, "Ptr", hBM, "Ptr")
DllCall("BitBlt", "Ptr", hMDC, "Int", 0, "Int", 0, "Int", W, "Int", H
, "Ptr", hDC, "Int", X, "Int", Y, "UInt", flags)
DllCall("SelectObject", "Ptr", hMDC, "Ptr", hObj, "Ptr")
DllCall("DeleteDC", "Ptr", hMDC)
DllCall("ReleaseDC", "Ptr", 0, "Ptr", hDC)
Return hBM
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SaveToImageFile(hBM, destImageFilePath, jpegQuality := 75) {
gdip := new GDIplus()
pBM := gdip.CreateBitmapFromHBITMAP(hBM)
gdip.SaveBitmap(pBM, destImageFilePath, jpegQuality)
gdip.DisposeImage(pBM)
}
class GDIplus {
__New() {
this.hLib := DllCall("LoadLibrary", "Str", "gdiplus", "Ptr")
VarSetCapacity(si, 8 + A_PtrSize*2, 0), si := Chr(1)
DllCall("gdiplus\GdiplusStartup", "PtrP", pToken, "Ptr", &si, "Ptr", 0)
this.token := pToken
}
__Delete() {
DllCall("gdiplus\GdiplusShutdown", "Ptr", this.token)
DllCall("FreeLibrary", "Ptr", this.hLib)
}
CreateBitmapFromHBITMAP(hBM, Palette=0) {
DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Ptr", hBM, "Ptr", Palette, "PtrP", pBM)
return pBM
}
SaveBitmap(pBM, ByRef info, Quality := 75, tobuff := "")
{
; info — if copying to buffer, then file extension, if copying to file, then file path
if tobuff
Extension := info
else
SplitPath, info,,, Extension
if Extension not in BMP,DIB,RLE,JPG,JPEG,JPE,JFIF,GIF,TIF,TIFF,PNG
return -1
DllCall("gdiplus\GdipGetImageEncodersSize", "UintP", nCount, "UintP", nSize)
VarSetCapacity(ci, nSize)
DllCall("gdiplus\GdipGetImageEncoders", "UInt", nCount, "UInt", nSize, "Ptr", &ci)
if !(nCount && nSize)
return -2
Loop, % nCount {
sString := StrGet(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
if !InStr(sString, "*." Extension)
continue
pCodec := &ci+idx
break
}
if !pCodec
return -3
if RegExMatch(Extension, "i)^J(PG|PEG|PE|FIF)$") && Quality != 75 {
DllCall("gdiplus\GdipGetEncoderParameterListSize", "Ptr", pBM, "Ptr", pCodec, "UintP", nSize)
VarSetCapacity(EncoderParameters, nSize, 0)
DllCall("gdiplus\GdipGetEncoderParameterList", "Ptr", pBM, "Ptr", pCodec, "UInt", nSize, "Ptr", &EncoderParameters)
Loop, % NumGet(EncoderParameters, "UInt")
{
elem := (24+A_PtrSize)*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
if (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6)
{
p := elem+&EncoderParameters-pad-4
NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20, "UInt")), "UInt")
break
}
}
}
if !tobuff
E := DllCall("gdiplus\GdipSaveImageToFile", "Ptr", pBM, "WStr", info, "Ptr", pCodec, "UInt", p ? p : 0)
else {
DllCall( "ole32\CreateStreamOnHGlobal", "UInt", 0, "Int", 1, "PtrP", pStream )
if !E := DllCall( "gdiplus\GdipSaveImageToStream", "Ptr", pBM, "Ptr", pStream, "Ptr", pCodec, "UInt", p ? p : 0 ) {
DllCall( "ole32\GetHGlobalFromStream", "Ptr", pStream, "PtrP", hData )
pData := DllCall( "GlobalLock", "Ptr", hData, "Ptr" )
nSize := DllCall( "GlobalSize", "Ptr", hData, "Ptr" )
VarSetCapacity( info, 0), VarSetCapacity( info, nSize, 0 )
DllCall( "RtlMoveMemory", "Ptr", &info, "Ptr", pData, "UInt", nSize )
DllCall( "GlobalUnlock", "Ptr", hData )
DllCall( "GlobalFree", "Ptr", hData )
}
ObjRelease(pStream)
}
return E ? -4 : tobuff ? nSize : 0
}
DisposeImage(pBM) {
return DllCall("gdiplus\GdipDisposeImage", "Ptr", pBM)
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GDI_CaptureScreenToClipboard( X, Y, W, H) {
Static SizeOfDIB := A_PtrSize = 8 ? 104 : 84 ; DIBSECTION
Static SizeOfBM := A_PtrSize = 8 ? 32 : 24 ; BITMAP
Static SizeOfBIH := 40 ; BITMAPINFOHEADER
Static OffBits := A_PtrSize = 8 ? 24 : 20 ; BITMAP -> bmBits
Static OffSize := A_PtrSize = 8 ? 52 : 44 ; BITMAPINFOHEADER -> biSizeImage
Local
hDC := DllCall("GetDC", "Ptr", 0, "UPtr")
cDC := DllCall("CreateCompatibleDC", "Ptr", hDC, "UPtr")
hBM := DllCall("CreateCompatibleBitmap", "Ptr", hDC, "Int", W, "Int", H, "UPtr")
hBM := DllCall("CopyImage", "Ptr", hBM, "UInt", 0, "Int", 0, "Int", 0, "UInt", 0x2008, "UPtr")
oBM := DllCall("SelectObject", "Ptr", cDC, "Ptr", hBM, "UPtr")
DllCall("BitBlt", "Ptr", cDC, "Int", 0, "Int", 0, "Int", W, "Int", H
, "Ptr", hDC, "Int", X, "Int", Y, "UInt", 0x40CC0020)
DllCall("SelectObject", "Ptr", cDC, "Ptr", oBM)
DllCall("DeleteDC", "Ptr", tDC)
DllCall("ReleaseDC", "Ptr", 0, "Ptr", hDC)
VarSetCapacity(DIB, SizeOfDIB, 0) ; DIBSECTION
DllCall("GetObject", "Ptr", hBM, "Int", SizeOfDIB, "Ptr", &DIB)
Size := NumGet(DIB, OffSize, "UInt")
Bits := NumGet(DIB, OffBits, "UPtr")
hDIB := DllCall("GlobalAlloc", "UInt", 2, "UInt", SizeOfBIH + Size, "UPtr")
pDIB := DllCall("GlobalLock", "Ptr", hDIB, "UPtr")
DllCall("RtlMoveMemory", "Ptr", pDIB, "Ptr", &DIB + SizeOfBM, "UInt", SizeOfBIH)
DllCall("RtlMoveMemory", "Ptr", pDIB + SizeOfBIH, "Ptr", Bits, "UInt", Size)
DllCall("GlobalUnlock", "Ptr", hDIB)
DllCall("DeleteObject", "Ptr", hBM)
DllCall("OpenClipboard", "Ptr", 0)
DllCall("EmptyClipboard")
DllCall("SetClipboardData", "UInt", 8, "Ptr", hDIB)
DllCall("CloseClipboard")
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Code: Select all
DllCall("DeleteObject", "Ptr", hBM) ; Clean-up
The DeleteObject() function should be used by hBitmap when hBitmap has been created and is no longer needed. Failure to use DeleteObject() in this case will result in a memory leak.
No, the variable name doesn't matter.
The variable name that was chosen to save hBitmap when it was created must be used.
Code: Select all
F2:: ; press F2 to save screenshot
hBM := ""
hBM := GDI_CaptureScreen( 0, 0, A_ScreenWidth, A_ScreenHeight )
SaveToImageFile(hBM, A_ScriptDir . "\ScreenshotImage.jpg", 100)
DllCall("DeleteObject", "Ptr", hBM) ; Clean-up
Return
F3:: ; press F3 to load screenshot to clipboard
GDI_CaptureScreenToClipboard(0, 0, A_ScreenWidth, A_ScreenHeight)
Return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GDI_CaptureScreen(X, Y, W, H) {
static flags := (SRCCOPY := 0x00CC0020) | (CAPTUREBLT := 0x40000000)
hDC := DllCall("GetDC", "Ptr", 0, "Ptr")
hBM := DllCall("CreateCompatibleBitmap", "Ptr", hDC, "Int", W, "Int", H, "Ptr")
hMDC := DllCall("CreateCompatibleDC", "Ptr", hDC, "Ptr")
hObj := DllCall("SelectObject", "Ptr", hMDC, "Ptr", hBM, "Ptr")
DllCall("BitBlt", "Ptr", hMDC, "Int", 0, "Int", 0, "Int", W, "Int", H
, "Ptr", hDC, "Int", X, "Int", Y, "UInt", flags)
DllCall("SelectObject", "Ptr", hMDC, "Ptr", hObj, "Ptr")
DllCall("DeleteDC", "Ptr", hMDC)
DllCall("ReleaseDC", "Ptr", 0, "Ptr", hDC)
Return hBM
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SaveToImageFile(hBitmap, destImageFilePath, jpegQuality := 75) {
gdip := new GDIplus()
pBitmap := gdip.CreateBitmapFromHBITMAP(hBitmap)
gdip.SaveBitmap(pBitmap, destImageFilePath, jpegQuality)
gdip.DisposeImage(pBitmap)
}
class GDIplus {
__New() {
this.hLib := DllCall("LoadLibrary", "Str", "gdiplus", "Ptr")
VarSetCapacity(si, 8 + A_PtrSize*2, 0), si := Chr(1)
DllCall("gdiplus\GdiplusStartup", "PtrP", pToken, "Ptr", &si, "Ptr", 0)
this.token := pToken
}
__Delete() {
DllCall("gdiplus\GdiplusShutdown", "Ptr", this.token)
DllCall("FreeLibrary", "Ptr", this.hLib)
}
CreateBitmapFromHBITMAP(hBitmap, Palette=0) {
DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Ptr", hBitmap, "Ptr", Palette, "PtrP", pBitmap)
return pBitmap
}
SaveBitmap(pBitmap, ByRef info, Quality := 75, tobuff := "")
{
; info — if copying to buffer, then file extension, if copying to file, then file path
if tobuff
Extension := info
else
SplitPath, info,,, Extension
if Extension not in BMP,DIB,RLE,JPG,JPEG,JPE,JFIF,GIF,TIF,TIFF,PNG
return -1
DllCall("gdiplus\GdipGetImageEncodersSize", "UintP", nCount, "UintP", nSize)
VarSetCapacity(ci, nSize)
DllCall("gdiplus\GdipGetImageEncoders", "UInt", nCount, "UInt", nSize, "Ptr", &ci)
if !(nCount && nSize)
return -2
Loop, % nCount {
sString := StrGet(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
if !InStr(sString, "*." Extension)
continue
pCodec := &ci+idx
break
}
if !pCodec
return -3
if RegExMatch(Extension, "i)^J(PG|PEG|PE|FIF)$") && Quality != 75 {
DllCall("gdiplus\GdipGetEncoderParameterListSize", "Ptr", pBitmap, "Ptr", pCodec, "UintP", nSize)
VarSetCapacity(EncoderParameters, nSize, 0)
DllCall("gdiplus\GdipGetEncoderParameterList", "Ptr", pBitmap, "Ptr", pCodec, "UInt", nSize, "Ptr", &EncoderParameters)
Loop, % NumGet(EncoderParameters, "UInt")
{
elem := (24+A_PtrSize)*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
if (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6)
{
p := elem+&EncoderParameters-pad-4
NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20, "UInt")), "UInt")
break
}
}
}
if !tobuff
E := DllCall("gdiplus\GdipSaveImageToFile", "Ptr", pBitmap, "WStr", info, "Ptr", pCodec, "UInt", p ? p : 0)
else {
DllCall( "ole32\CreateStreamOnHGlobal", "UInt", 0, "Int", 1, "PtrP", pStream )
if !E := DllCall( "gdiplus\GdipSaveImageToStream", "Ptr", pBitmap, "Ptr", pStream, "Ptr", pCodec, "UInt", p ? p : 0 ) {
DllCall( "ole32\GetHGlobalFromStream", "Ptr", pStream, "PtrP", hData )
pData := DllCall( "GlobalLock", "Ptr", hData, "Ptr" )
nSize := DllCall( "GlobalSize", "Ptr", hData, "Ptr" )
VarSetCapacity( info, 0), VarSetCapacity( info, nSize, 0 )
DllCall( "RtlMoveMemory", "Ptr", &info, "Ptr", pData, "UInt", nSize )
DllCall( "GlobalUnlock", "Ptr", hData )
DllCall( "GlobalFree", "Ptr", hData )
}
ObjRelease(pStream)
}
return E ? -4 : tobuff ? nSize : 0
}
DisposeImage(pBitmap) {
return DllCall("gdiplus\GdipDisposeImage", "Ptr", pBitmap)
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GDI_CaptureScreenToClipboard( X, Y, W, H) {
Static SizeOfDIB := A_PtrSize = 8 ? 104 : 84 ; DIBSECTION
Static SizeOfBM := A_PtrSize = 8 ? 32 : 24 ; BITMAP
Static SizeOfBIH := 40 ; BITMAPINFOHEADER
Static OffBits := A_PtrSize = 8 ? 24 : 20 ; BITMAP -> bmBits
Static OffSize := A_PtrSize = 8 ? 52 : 44 ; BITMAPINFOHEADER -> biSizeImage
Local
hDC := DllCall("GetDC", "Ptr", 0, "UPtr")
cDC := DllCall("CreateCompatibleDC", "Ptr", hDC, "UPtr")
hBM := DllCall("CreateCompatibleBitmap", "Ptr", hDC, "Int", W, "Int", H, "UPtr")
hBM := DllCall("CopyImage", "Ptr", hBM, "UInt", 0, "Int", 0, "Int", 0, "UInt", 0x2008, "UPtr")
oBM := DllCall("SelectObject", "Ptr", cDC, "Ptr", hBM, "UPtr")
DllCall("BitBlt", "Ptr", cDC, "Int", 0, "Int", 0, "Int", W, "Int", H
, "Ptr", hDC, "Int", X, "Int", Y, "UInt", 0x40CC0020)
DllCall("SelectObject", "Ptr", cDC, "Ptr", oBM)
DllCall("DeleteDC", "Ptr", tDC)
DllCall("ReleaseDC", "Ptr", 0, "Ptr", hDC)
VarSetCapacity(DIB, SizeOfDIB, 0) ; DIBSECTION
DllCall("GetObject", "Ptr", hBM, "Int", SizeOfDIB, "Ptr", &DIB)
Size := NumGet(DIB, OffSize, "UInt")
Bits := NumGet(DIB, OffBits, "UPtr")
hDIB := DllCall("GlobalAlloc", "UInt", 2, "UInt", SizeOfBIH + Size, "UPtr")
pDIB := DllCall("GlobalLock", "Ptr", hDIB, "UPtr")
DllCall("RtlMoveMemory", "Ptr", pDIB, "Ptr", &DIB + SizeOfBM, "UInt", SizeOfBIH)
DllCall("RtlMoveMemory", "Ptr", pDIB + SizeOfBIH, "Ptr", Bits, "UInt", Size)
DllCall("GlobalUnlock", "Ptr", hDIB)
DllCall("DeleteObject", "Ptr", hBM)
DllCall("OpenClipboard", "Ptr", 0)
DllCall("EmptyClipboard")
DllCall("SetClipboardData", "UInt", 8, "Ptr", hDIB)
DllCall("CloseClipboard")
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Code: Select all
F2:: ; press F2 to save screenshot
hBM := ""
hBM := GDI_CaptureScreen( 0, 0, A_ScreenWidth, A_ScreenHeight )
SaveToImageFile(hBM, A_ScriptDir . "\ScreenshotImage.jpg", 100)
DllCall("DeleteObject", "Ptr", hBM) ; Clean-up
Return
F3:: ; press F3 to load screenshot to clipboard
GDI_CaptureScreenToClipboard(0, 0, A_ScreenWidth, A_ScreenHeight)
Return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GDI_CaptureScreen(X, Y, W, H) {
static flags := (SRCCOPY := 0x00CC0020) | (CAPTUREBLT := 0x40000000)
hDC := DllCall("GetDC", "Ptr", 0, "Ptr")
hBM := DllCall("CreateCompatibleBitmap", "Ptr", hDC, "Int", W, "Int", H, "Ptr")
hMDC := DllCall("CreateCompatibleDC", "Ptr", hDC, "Ptr")
hObj := DllCall("SelectObject", "Ptr", hMDC, "Ptr", hBM, "Ptr")
DllCall("BitBlt", "Ptr", hMDC, "Int", 0, "Int", 0, "Int", W, "Int", H
, "Ptr", hDC, "Int", X, "Int", Y, "UInt", flags)
DllCall("SelectObject", "Ptr", hMDC, "Ptr", hObj, "Ptr")
DllCall("DeleteDC", "Ptr", hMDC)
DllCall("ReleaseDC", "Ptr", 0, "Ptr", hDC)
Return hBM
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SaveToImageFile(hBM, destImageFilePath, jpegQuality := 75) {
gdip := new GDIplus()
pBM := gdip.CreateBitmapFromHBITMAP(hBM)
gdip.SaveBitmap(pBM, destImageFilePath, jpegQuality)
gdip.DisposeImage(pBM)
}
class GDIplus {
__New() {
this.hLib := DllCall("LoadLibrary", "Str", "gdiplus", "Ptr")
VarSetCapacity(si, 8 + A_PtrSize*2, 0), si := Chr(1)
DllCall("gdiplus\GdiplusStartup", "PtrP", pToken, "Ptr", &si, "Ptr", 0)
this.token := pToken
}
__Delete() {
DllCall("gdiplus\GdiplusShutdown", "Ptr", this.token)
DllCall("FreeLibrary", "Ptr", this.hLib)
}
CreateBitmapFromHBITMAP(hBM, Palette=0) {
DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Ptr", hBM, "Ptr", Palette, "PtrP", pBM)
return pBM
}
SaveBitmap(pBM, ByRef info, Quality := 75, tobuff := "")
{
; info — if copying to buffer, then file extension, if copying to file, then file path
if tobuff
Extension := info
else
SplitPath, info,,, Extension
if Extension not in BMP,DIB,RLE,JPG,JPEG,JPE,JFIF,GIF,TIF,TIFF,PNG
return -1
DllCall("gdiplus\GdipGetImageEncodersSize", "UintP", nCount, "UintP", nSize)
VarSetCapacity(ci, nSize)
DllCall("gdiplus\GdipGetImageEncoders", "UInt", nCount, "UInt", nSize, "Ptr", &ci)
if !(nCount && nSize)
return -2
Loop, % nCount {
sString := StrGet(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
if !InStr(sString, "*." Extension)
continue
pCodec := &ci+idx
break
}
if !pCodec
return -3
if RegExMatch(Extension, "i)^J(PG|PEG|PE|FIF)$") && Quality != 75 {
DllCall("gdiplus\GdipGetEncoderParameterListSize", "Ptr", pBM, "Ptr", pCodec, "UintP", nSize)
VarSetCapacity(EncoderParameters, nSize, 0)
DllCall("gdiplus\GdipGetEncoderParameterList", "Ptr", pBM, "Ptr", pCodec, "UInt", nSize, "Ptr", &EncoderParameters)
Loop, % NumGet(EncoderParameters, "UInt")
{
elem := (24+A_PtrSize)*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
if (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6)
{
p := elem+&EncoderParameters-pad-4
NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20, "UInt")), "UInt")
break
}
}
}
if !tobuff
E := DllCall("gdiplus\GdipSaveImageToFile", "Ptr", pBM, "WStr", info, "Ptr", pCodec, "UInt", p ? p : 0)
else {
DllCall( "ole32\CreateStreamOnHGlobal", "UInt", 0, "Int", 1, "PtrP", pStream )
if !E := DllCall( "gdiplus\GdipSaveImageToStream", "Ptr", pBM, "Ptr", pStream, "Ptr", pCodec, "UInt", p ? p : 0 ) {
DllCall( "ole32\GetHGlobalFromStream", "Ptr", pStream, "PtrP", hData )
pData := DllCall( "GlobalLock", "Ptr", hData, "Ptr" )
nSize := DllCall( "GlobalSize", "Ptr", hData, "Ptr" )
VarSetCapacity( info, 0), VarSetCapacity( info, nSize, 0 )
DllCall( "RtlMoveMemory", "Ptr", &info, "Ptr", pData, "UInt", nSize )
DllCall( "GlobalUnlock", "Ptr", hData )
DllCall( "GlobalFree", "Ptr", hData )
}
ObjRelease(pStream)
}
return E ? -4 : tobuff ? nSize : 0
}
DisposeImage(pBM) {
return DllCall("gdiplus\GdipDisposeImage", "Ptr", pBM)
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GDI_CaptureScreenToClipboard( X, Y, W, H) {
Static SizeOfDIB := A_PtrSize = 8 ? 104 : 84 ; DIBSECTION
Static SizeOfBM := A_PtrSize = 8 ? 32 : 24 ; BITMAP
Static SizeOfBIH := 40 ; BITMAPINFOHEADER
Static OffBits := A_PtrSize = 8 ? 24 : 20 ; BITMAP -> bmBits
Static OffSize := A_PtrSize = 8 ? 52 : 44 ; BITMAPINFOHEADER -> biSizeImage
Local
hDC := DllCall("GetDC", "Ptr", 0, "UPtr")
cDC := DllCall("CreateCompatibleDC", "Ptr", hDC, "UPtr")
hBM := DllCall("CreateCompatibleBitmap", "Ptr", hDC, "Int", W, "Int", H, "UPtr")
hBM := DllCall("CopyImage", "Ptr", hBM, "UInt", 0, "Int", 0, "Int", 0, "UInt", 0x2008, "UPtr")
oBM := DllCall("SelectObject", "Ptr", cDC, "Ptr", hBM, "UPtr")
DllCall("BitBlt", "Ptr", cDC, "Int", 0, "Int", 0, "Int", W, "Int", H
, "Ptr", hDC, "Int", X, "Int", Y, "UInt", 0x40CC0020)
DllCall("SelectObject", "Ptr", cDC, "Ptr", oBM)
DllCall("DeleteDC", "Ptr", tDC)
DllCall("ReleaseDC", "Ptr", 0, "Ptr", hDC)
VarSetCapacity(DIB, SizeOfDIB, 0) ; DIBSECTION
DllCall("GetObject", "Ptr", hBM, "Int", SizeOfDIB, "Ptr", &DIB)
Size := NumGet(DIB, OffSize, "UInt")
Bits := NumGet(DIB, OffBits, "UPtr")
hDIB := DllCall("GlobalAlloc", "UInt", 2, "UInt", SizeOfBIH + Size, "UPtr")
pDIB := DllCall("GlobalLock", "Ptr", hDIB, "UPtr")
DllCall("RtlMoveMemory", "Ptr", pDIB, "Ptr", &DIB + SizeOfBM, "UInt", SizeOfBIH)
DllCall("RtlMoveMemory", "Ptr", pDIB + SizeOfBIH, "Ptr", Bits, "UInt", Size)
DllCall("GlobalUnlock", "Ptr", hDIB)
DllCall("DeleteObject", "Ptr", hBM)
DllCall("OpenClipboard", "Ptr", 0)
DllCall("EmptyClipboard")
DllCall("SetClipboardData", "UInt", 8, "Ptr", hDIB)
DllCall("CloseClipboard")
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Code: Select all
DllCall("DeleteObject", "Ptr", hBM) ; Clean-up
Correct.
Correct.GEOVAN wrote: ↑Now, the reason you answer that the variable name does not matter, it is because the (i) is the ONLY one variable in the "MAIN" code of the script, while the (ii) and (iii) are variables that BELONG to functions which are something like INDEPENTED from the MAIN script, that is why there is no CONFLICT of the THREE different variables that have the same name.
Do i understand this matter correct, please?
Correct.