Jump to content

GDI Screenshot + _WinHttp


Recommended Posts

Hi,

What I would like to accomplish is to take a screenshot and upload it to a remote php file via _winHTTP.

Previously, we were taking the screenshots and saving them to a network folder.

However, we would now like to alter this so that it posts the information instead through win http.

Please see the following code sample (note it does NOT run, it's just for reference).

$hbitmap = _ScreenCapture_Capture('', $iScreenCapDimensions[1] , $iScreenCapDimensions[2], $iScreenCapDimensions[3], $iScreenCapDimensions[4])
_SavehBitmapEx($hbitmap, 100000000, _WinAPI_GetSystemMetrics(78), _WinAPI_GetSystemMetrics(79))

Func _SavehBitmapEx($hbitmap, $iID, $iWidth, $iHeight)
Local $save_result = true
$bitmap = _GDIPlus_BitmapCreateFromHBITMAP($hbitmap)
$graphics = _GDIPlus_ImageGetGraphicsContext($bitmap)
$resizedbitmap = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $graphics)
$graphics2 = _GDIPlus_ImageGetGraphicsContext($resizedbitmap)
_GDIPLUS_GraphicsSetInterpolationMode($graphics2, $InterpolationModeHighQualityBicubic)
_GDIPlus_GraphicsDrawImageRect($graphics2, $bitmap, 0, 0, $iWidth, $iHeight)
;;; - CODE THAT REQUIRES UPDATE
Local $locImgFile = "C:\temp\" & _GetImageFolderPathFromId($iID, '')
$save_result = _GDIPlus_ImageSaveToFile($resizedbitmap, $locImgFile) ;saves to temp file
PostImage(_GetImageFolderPathFromId($iID, '/'), FileRead($locImgFile)) ;file reads image and uploads to http server
FileDelete($locImgFile) ;deletes image when done
;;; - END CODE THAT REQUIRES UPDATE
_GDIPlus_GraphicsDispose($graphics)
_GDIPlus_GraphicsDispose($graphics2)
_GDIPlus_BitmapDispose($bitmap)
_GDIPlus_BitmapDispose($resizedbitmap)
return $save_result
EndFunc ;==>_SavehBitmapEx

Func _GetImageFolderPathFromId($id, $sep = '\')
Local $aLastImageSplit
$aLastImageSplit = StringSplit(String($id), '')
$return = $aLastImageSplit[1] & $aLastImageSplit[2] & $aLastImageSplit[3] & $sep & _
$aLastImageSplit[4] & $aLastImageSplit[5] & $aLastImageSplit[6] & $sep & _
$aLastImageSplit[7] & $aLastImageSplit[8] & $aLastImageSplit[9] & $sep & _
$aLastImageSplit[10] & $aLastImageSplit[11] & $aLastImageSplit[12] & '.jpg'
return $return
EndFunc

Func _GDIPlus_SaveImage2BinaryString($hBitmap, $iQuality = 100) ;coded by Andreik, modified by UEZ
Local $sImgCLSID = _GDIPlus_EncodersGetCLSID("jpg")
Local $tGUID = _WinAPI_GUIDFromString($sImgCLSID)
Local $pEncoder = DllStructGetPtr($tGUID)
Local $tParams = _GDIPlus_ParamInit(1)
Local $tData = DllStructCreate("int Quality")
DllStructSetData($tData, "Quality", $iQuality) ;quality 0-100
Local $pData = DllStructGetPtr($tData)
_GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, $pData)
Local $pParams = DllStructGetPtr($tParams)
Local $hStream = DllCall("ole32.dll", "uint", "CreateStreamOnHGlobal", "ptr", 0, "bool", True, "ptr*", 0) ;http://msdn.microsoft.com/en-us/library/ms864401.aspx
If @error Then Return SetError(1, 0, 0)
$hStream = $hStream[3]
DllCall($ghGDIPDll, "uint", "GdipSaveImageToStream", "ptr", $hBitmap, "ptr", $hStream, "ptr", $pEncoder, "ptr", $pParams)
_GDIPlus_BitmapDispose($hBitmap)
Local $hMemory = DllCall("ole32.dll", "uint", "GetHGlobalFromStream", "ptr", $hStream, "ptr*", 0) ;http://msdn.microsoft.com/en-us/library/aa911736.aspx
If @error Then Return SetError(2, 0, 0)
$hMemory = $hMemory[2]
Local $iMemSize = _MemGlobalSize($hMemory)
Local $pMem = _MemGlobalLock($hMemory)
$tData = DllStructCreate("byte[" & $iMemSize & "]", $pMem)
Local $bData = DllStructGetData($tData, 1)
Local $tVARIANT = DllStructCreate("word vt;word r1;word r2;word r3;ptr data;ptr")
Local $aCall = DllCall("oleaut32.dll", "long", "DispCallFunc", "ptr", $hStream, "dword", 8 + 8 * @AutoItX64, "dword", 4, "dword", 23, "dword", 0, "ptr", 0, "ptr", 0, "ptr", DllStructGetPtr($tVARIANT)) ;http://msdn.microsoft.com/en-us/library/windows/desktop/ms221473(v=vs.85).aspx
_MemGlobalFree($hMemory)
Return $bData
EndFunc ;==>_GDIPlus_SaveImage2BinaryString

The above method works but I would like to change it.

It saves a temp jpg, file reads it, uploads to server and deletes the temp file.

I would like to utilize the "_GDIPlus_SaveImage2BinaryString" method instead rather than using a temp file.

Changing:

;;; - CODE THAT REQUIRES UPDATE
Local $locImgFile = "C:\temp\" & _GetImageFolderPathFromId($iID, '')
$save_result = _GDIPlus_ImageSaveToFile($resizedbitmap, $locImgFile) ;saves to temp file
PostImage(_GetImageFolderPathFromId($iID, '/'), FileRead($locImgFile)) ;file reads image and uploads to http server
FileDelete($locImgFile) ;deletes image when done
;;; - END CODE THAT REQUIRES UPDATE

To:

;;; - CODE THAT REQUIRES UPDATE
PostImage(_GetImageFolderPathFromId($iID, '/'), _GDIPlus_SaveImage2BinaryString($resizedbitmap)) ;sends binary image to server directly
;;; - END CODE THAT REQUIRES UPDATE

Does NOT work. Anyone have any ideas?

Thanks in advance.

[font="Impact"] I always thought dogs laid eggs, and I learned something today. [/font]
Link to comment
Share on other sites

Fyi: _ScreenCapture_Capture() produces a WinAPI bitmap not a GDI+ bitmap. That means you have to convert that image to a GDI+ image -> _GDIPlus_BitmapCreateHBITMAPFromBitmap()

PostImage(_GetImageFolderPathFromId($iID, '/'), _GDIPlus_SaveImage2BinaryString($resizedbitmap)) ;sends binary image to server dir

_GDIPlus_SaveImage2BinaryString() returns a binary string. What do you get and what is the binary size? Further what is PostImage() doing exactly?

Br,

UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

@mikell: I think his question was how to take a screenshot and upload it to any cloud services without saving the screenshot to hd first.

Br,

UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Thanks for responding UEZ.

Post image looks like this:

Func PostImage($iLoc, $img)
Local $sChunk, $s_Data
local $path = "sr_images_" & @YEAR & "_" & @MON & "/" & $user & "/" & StringLeft($iLoc, 11)
local $file = StringRight($iLoc, 7)
$hOpen = _WinHttpOpen("ImageUpload_"&$user&"_"&$iLoc)
$hConnect = _WinHttpConnect($hOpen, $sURL)
$hRequest = _WinHttpOpenRequest($hConnect, "POST", $sPURL)
$sData = ""
$sData &= '----------darker' & @CRLF
$sData &= 'Content-Disposition: form-data; name="path"' & @CRLF & @CRLF
$sData &= $path & @CRLF
$sData &= '----------darker' & @CRLF
$sData &= 'Content-Disposition: form-data; name="file_name"' & @CRLF & @CRLF
$sData &= $file & @CRLF
$sData &= '----------darker' & @CRLF
$sData &= 'Content-Disposition: form-data; name="image"; filename="'&$file&'"' & @CRLF
$sData &= 'Content-Type: image/jpg' & @CRLF & @CRLF
$sData &= $img & @CRLF
$sData &= '----------darker' & @CRLF
_WinHttpSendRequest($hRequest, "Content-Type: multipart/form-data; boundary=--------darker", Binary($sData))
_WinHttpReceiveResponse($hRequest)
_WinHttpCloseHandle($hRequest)
_WinHttpCloseHandle($hConnect)
_WinHttpCloseHandle($hOpen)
EndFunc

Am I not converting the bitmap properly with the following lines?

$hbitmap = _ScreenCapture_Capture('', $iScreenCapDimensions[1] , $iScreenCapDimensions[2], $iScreenCapDimensions[3], $iScreenCapDimensions[4])
$bitmap = _GDIPlus_BitmapCreateFromHBITMAP($hbitmap)
$graphics = _GDIPlus_ImageGetGraphicsContext($bitmap)
$resizedbitmap = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $graphics)
$graphics2 = _GDIPlus_ImageGetGraphicsContext($resizedbitmap)
_GDIPLUS_GraphicsSetInterpolationMode($graphics2, $InterpolationModeHighQualityBicubic)
_GDIPlus_GraphicsDrawImageRect($graphics2, $bitmap, 0, 0, $iWidth, $iHeight)
$bImage = _GDIPlus_SaveImage2BinaryString($resizedbitmap)

I would like to keep these settings (width, height, interpolationMode, etc.) when I transfer the image via http

[font="Impact"] I always thought dogs laid eggs, and I learned something today. [/font]
Link to comment
Share on other sites

I would use rather this way:

$hbitmap = _ScreenCapture_Capture('', $iScreenCapDimensions[1] , $iScreenCapDimensions[2], $iScreenCapDimensions[3], $iScreenCapDimensions[4])
$bitmap = _GDIPlus_BitmapCreateFromHBITMAP($hbitmap)
$resizedbitmap = _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight)
$graphics = _GDIPlus_ImageGetGraphicsContext($resizedbitmap)
_GDIPLUS_GraphicsSetInterpolationMode($graphics, $InterpolationModeHighQualityBicubic)
_GDIPlus_GraphicsDrawImageRect($graphics, $bitmap, 0, 0, $iWidth, $iHeight)
$bImage = _GDIPlus_SaveImage2BinaryString($resizedbitmap)

Br,

UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

I implemented the code above.

The size of the images using my initial method (SaveToFile, FileRead, HTTPPost, FileDelete) are ~75-100KB.

The size of the images using this binary method are ~200KB and they also do not work.

When viewing them in windows, I get an error "Windows Photo Viewer can't open this picture because the file appears to be damaged, corrupted, or is too large".

Any ideas?

[font="Impact"] I always thought dogs laid eggs, and I learned something today. [/font]
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...