Jump to content

JPEG quality after screen capture and resizing


Recommended Posts

I've been reading a bit the forums and I simply couldn't find (yet) a solution to this small problem.

I have a piece of code that takes a screenshot of the full desktop (multiple monitors included) and saves it to disk. So far nothing too hard, I even setup a variable to reduce the JPEG quality if I want to.

However, I also used another variable to select screenshot percentage (for example, 50% of the original destop size). For that matter I need to do a few more bits of code to resize the image and then save it to disk.

Now the problem, whatever JPEG quality I chose, the final image is not the quality I set up. It's also never 100% full quality.

Here's an example code (just for testing) of what I mean:

#include <ScreenCapture.au3>

;These 2 are not needed as they are already included once in <ScreenCapture.au3>
;#include <WinAPI.au3>
;#include <GDIPlus.au3>

$file = @ScriptDir & "\xxx.jpg" ;File to save the screenshot (as an example)
$qua = 100 ;JPEG quality
$per = 75 ;Percentage of the original screenshot size

; Take a screenshot and save it to disc (I have 2 monitors)
_ScreenCapture_SetJPGQuality($qua) ;This setting seems to be ignored unless I use "_ScreenCapture_Capture"
$x1 = _WinAPI_GetSystemMetrics(76)
$y1 = _WinAPI_GetSystemMetrics(77)
$x2 = _WinAPI_GetSystemMetrics(78)
$y2 = _WinAPI_GetSystemMetrics(79)

If $per = 100 Then
    $pic = _ScreenCapture_Capture($file, $x1, $y1, $x2, $y2) ;JPEG is saved in whatever quality I chose in "$qua"
Else
    $pic = _ScreenCapture_Capture("", $x1, $y1, $x2, $y2)
    _GDIPlus_Startup()
    $bmp = _GDIPlus_BitmapCreateFromHBITMAP($pic)
    $scaled = _GDIPlus_ImageResize($bmp, $x2*$per/100, $y2*$per/100, 7) ;Scaling works as intended
    _GDIPlus_ImageSaveToFile($scaled, $file) ;Even if "$qua = 100" it seems to save it at a lesser quality. WHY?
    _GDIPlus_BitmapDispose($bmp)
    _GDIPlus_BitmapDispose($scaled)
    _GDIPlus_Shutdown()
EndIf
_WinAPI_DeleteObject($pic)

Sorry if this has already been answeared somewhere else but I don't seem to be able to find anything yet.

Link to comment
Share on other sites

Ok, seems I'm smart enough to look into the includes and figure this out myself. I copied some small code from one UDF function into another. Here's the result:

#include <ScreenCapture.au3>

;These 2 are not needed as they are already included once in <ScreenCapture.au3>
;#include <WinAPI.au3>
;#include <GDIPlus.au3>

$file = @ScriptDir & "\xxx.jpg" ;File to save the screenshot (as an example)
Global $qua = 100 ;JPEG quality
$per = 75 ;Percentage of the original screenshot size

; Take a screenshot and save it to disc (I have 2 monitors)
_ScreenCapture_SetJPGQuality($qua) ;This setting was previously ignored unless I used "_ScreenCapture_Capture"
$x1 = _WinAPI_GetSystemMetrics(76)
$y1 = _WinAPI_GetSystemMetrics(77)
$x2 = _WinAPI_GetSystemMetrics(78)
$y2 = _WinAPI_GetSystemMetrics(79)

If $per = 100 Then
    $pic = _ScreenCapture_Capture($file, $x1, $y1, $x2, $y2) ;JPEG is saved in whatever quality I chose in "$qua"
Else
    $pic = _ScreenCapture_Capture("", $x1, $y1, $x2, $y2)
    _GDIPlus_Startup()
    $bmp = _GDIPlus_BitmapCreateFromHBITMAP($pic)
    $scaled = _GDIPlus_ImageResize($bmp, $x2*$per/100, $y2*$per/100, 7) ;Scaling works as intended
   My_GDIPlus_ImageSaveToFile($scaled, $file) ;Used the altered function instead. Now it works.
    _GDIPlus_BitmapDispose($bmp)
    _GDIPlus_BitmapDispose($scaled)
    _GDIPlus_Shutdown()
EndIf
_WinAPI_DeleteObject($pic)


Exit


; Changed from original "_GDIPlus_ImageSaveToFile"
Func My_GDIPlus_ImageSaveToFile($hImage, $sFileName)
    Local $sExt = __GDIPlus_ExtractFileExt($sFileName)
    Local $sCLSID = _GDIPlus_EncodersGetCLSID($sExt)
    If $sCLSID = "" Then Return SetError(-1, 0, False)

    ; Added from here...
    Local $tData, $tParams
    $tParams = _GDIPlus_ParamInit(1)
    $tData = DllStructCreate("int Quality")
    DllStructSetData($tData, "Quality", $qua) ;Using here my variable instead
    _GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, DllStructGetPtr($tData))
    Local $pParams = 0
    If IsDllStruct($tParams) Then $pParams = $tParams
    ; ...to here.

    Local $bRet = _GDIPlus_ImageSaveToFileEx($hImage, $sFileName, $sCLSID, $pParams) ;Changed from "0" to "$pParams"
    Return SetError(@error, @extended, $bRet)
EndFunc

Basically I added to the function the option of chosing the JPEG quality. Shouldn't this be already in the UDF? Unless I'm missing something here...

Link to comment
Share on other sites

Try this:

$pic = _ScreenCapture_Capture("", $x1, $y1, $x2, $y2)
    _GDIPlus_Startup()
    $bmp = _GDIPlus_BitmapCreateFromHBITMAP($pic)
    $scaled = _GDIPlus_ImageResize($bmp, $x2*$per/100, $y2*$per/100, 7)
    $iJPGQual = 50
    $sCLSID = _GDIPlus_EncodersGetCLSID("JPG")
    $tParams = _GDIPlus_ParamInit(1)
    $tData = DllStructCreate("int Quality")
    DllStructSetData($tData, "Quality", $iJPGQual)
    $pData = DllStructGetPtr($tData)
    _GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, $pData)
    $pParams = DllStructGetPtr($tParams)
    _GDIPlus_ImageSaveToFileEx($scaled, $file, $sCLSID, $pParams)
    _GDIPlus_BitmapDispose($bmp)
    _GDIPlus_BitmapDispose($scaled)
    _GDIPlus_Shutdown()

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

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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...