Jump to content
Sign in to follow this  
ame1011

GDI Screenshot + _WinHttp

Recommended Posts

ame1011

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]

Share this post


Link to post
Share on other sites
UEZ

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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites
UEZ

@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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites
mikell

Yes, I saw this after posting and that's why I deleted my post just before you answered, sorry :unsure:

Edited by mikell

Share this post


Link to post
Share on other sites
ame1011

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]

Share this post


Link to post
Share on other sites
UEZ

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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites
ame1011

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]

Share this post


Link to post
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
Sign in to follow this  

  • Similar Content

    • bhns
      By bhns
      try it for make flyers old games xml + Gdi, i belive many sources had lost 
      AIT-ADRLIST.au3

    • mdepot
      By mdepot
      I have a situation where I am repeatedly capturing a region of the screen and feeding it into Tesseract OCR.  Since the OCR is a relatively slow operation, I would like to create an in memory cache of the ocr results.  An ideal hash key for this cache would be a checksum of the captured image.  With this I could capture the region, checksum it, and then only if I don't get a cache hit I would write the image out to disk for external OCR.
      Now I know I can do this by saving the captured image out to disk, and then summing the disk file with _Crypt_HashFile().  But that's still slower than I would like, and it shouldn't be necessary.  Ideally, it should be possible to checksum the image data directly in memory so I don't have to go to disk at all.  In order to do that, I need a way to dump a representation of the image into a string  (or some equivalent).  Then I could use the _Crypt_HashData() function against that string to create my cache hash key.
      Googling around I found an article here that shows a way to convert an image object to a byte array using System.Drawing.  This was the closest thing I found to what I'm trying to do.  I don't know if that method could be used from within AutoIT, or if perhaps there may be a better way I don't know about.  If someone could give me a shove in the right direction it would be a big help.  Thanks!
    • UEZ
      By UEZ
      Here some graphical examples written completely in FreeBasic just for fun.  
      3D Starfield Rotating Flight 3D Starfield Scrolling v1 Booster 3D Starfield Scrolling v3 Booster CreateWindowEx (hGUI) Example FB File2Bas Code Generator (AutoIt script) FB GFX Examples Fire Particles FMOD Examples GDI - GDI+ 3D Sinus Wave GDI - GDI+ Animated Pythagoras Tree GDI - GDI+ Particles - Repulsive Force Sim v2.0 GDI - GDI+ Plasma v5 Booster GDI - GDI+ Random Pattern GDI - GDI+ Space Flight GDI - GDI+ Tunnel Flight - WipeOut Style GDI Classic Raytraced Tunnel GDI Elastic Twister Effect GDI Exploding Pixels GDI Infinite Image Zoom Flight GDI Liquid Pixels GDI Particle Repulsion Grid GDI Particles Mouse Attraction GDI Starfield GDI The Nautilus Raymarcher GDI Worm Tunnel Flight GDI+ Impossible Possible GDI+ Kaleidoscope GDI+ Performance Test - Au3 vs FB GDI+ Polar Clock GDI+ Rotating Earth GDI+ Star Wars Scroller GDI+ Streamer GDI+ Swiss Railway Clock Ini Read - Write Mandelbrot Plasma Puristic Clock Rutt_Etra_Izer_Booster Tunnel Flight uFMOD _WinAPI_SetWindowTitleIcon  
      Download: FreeBasic Examples build 2018-07-10.rar
       
      I will add new examples from time to time.
       
      FreeBasic source codes are also included.
       
    • Surya
      By Surya
      Hi everyone its been loooong since I posted here 
      I have been trying to convert this curl executable parameters into autoit using the winhttp com object;
      curl -F data_file=@my_audio_file.mp3 -F model=en-US "https://api.speechmatics.com/v1.0/user/41049/jobs/?auth_token=MmQ5MTk4jdsgjhgghstOGU5YS00OWFhLWghdgjshgdhbshj017###" any ideas guys
       
      PS: I am excited to post here after a looong time
    • ammaul
      By ammaul
      Hi folks, I'm having problems with a screenshot capture script.
      Let me explain.
      Everyday I (and my colleagues at work) need to take some screenshots from a web-page. These screenshots are used to compile a report. Normally, I (and others) used to log in into the website and took screenshots of desired graphics and tables. This is tediuos and time consuming. To easy this task I made a script using autoit that basically logs into the website (user and password) and using some clicks, stroke send, coordinates, it is able to generate the graphics and save them to some folders into our network (this script saves arouund 50 pics. It works like a sharm.
      In order to make things easier, I tried to schedule this script (compiled to a Screnpics.exe file) using task scheduler from windows. We already use this (task scheduler) to run some vbs scripts, some vba excel scripts and so on. The computer used for this tasks is a windows 7 desktop computer. Due to security policies, the computer locks after some time. All this tasks run in the locked computer.
      My script screenpics.exe runs also from this locked computer. When the computer is unlocked, it does everything as expected. But, when it is locked, all the "pics" are BLACK. As I understand, it runs ok, but, as the "windows" are innactive, it prints what it "sees": a black rectangular.
      Some details: The web-page with hold the information I need, it only works in Firefox and, because of this it couldn`t be managed by vba or some "getobject" like commands. In fact, it has some flash things that make it impossible to control programatically. So my script is based on mouse move to coordinates, mouse click, screen capture and so one.
       
      So, I read many posts trying to figure out a way to overcome this, but... nothing came to mind. My first idea was try to unlock windows. Theses lead me to some posts with no solution. This is worse because I'm not a computer admin, so procedures that need to replace/change the register are not an option.
       
      If someone has any idea, I'll be gratefull.
×