Jump to content

Simple Rotate By Degree, plus Trim and Resize


Recommended Posts

1 hour ago, UEZ said:

Here a fast hack how to rotate the image by drawing a line on the edge of the CD cover.

Thanks for that @UEZ, you are the GDI+ Master, and I shall indeed check it out and look into the crop side of it too. :) 

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Link to comment
Share on other sites

@UEZ,  nice.
I've fiddled with the UEZ listing a bit
you can now rotate the image visually with a slider
you can also finely adjust the rotation with two buttons
I also added 2 "rulers", one vertical and one horizontal, which you can move by clicking on them and dragging them, in order to have a reference to control the orientation of the image

;Coded by UEZ 2024-03-16
; [few mods by Gianni :) ]
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>

; --- rulers -----
Global $iThickness = 4
Global $hGUI1 = GUICreate("", @DesktopWidth, $iThickness, 0, @DesktopHeight / 2, $WS_POPUP, $WS_EX_TOPMOST)
GUICtrlCreateLabel("", 0, 0, @DesktopWidth, $iThickness, -1, $GUI_WS_EX_PARENTDRAG)
GUISetBkColor(0x00ff00, $hGUI1)
WinSetTrans($hGUI1, "", 127)
GUISetState(@SW_SHOW, $hGUI1)
Global $hGUI2 = GUICreate("", $iThickness, @DesktopHeight, @DesktopWidth / 2, 0, $WS_POPUP, $WS_EX_TOPMOST)
GUICtrlCreateLabel("", 0, 0, $iThickness, @DesktopHeight, -1, $GUI_WS_EX_PARENTDRAG)
GUISetBkColor(0x00ff00, $hGUI2)
WinSetTrans($hGUI2, "", 127)
GUISetState(@SW_SHOW, $hGUI2)
; ----------------

Global $sFile = "cover.jpg" ;FileOpenDialog("Select an image", "", "Images (*.jpg;*.png;*.gif;*.bmp)")
If @error Then Exit

Const $fPI = ACos(-1)
_GDIPlus_Startup()
Global $hImage = _GDIPlus_ImageLoadFromFile($sFile)
Global $aDim = _GDIPlus_ImageGetDimension($hImage)
Global Const $hGUI = GUICreate("Image Rotate", $aDim[0], $aDim[1] + 50)

Global Const $hDC = _WinAPI_GetDC($hGUI)
Global Const $hHBitmap = _WinAPI_CreateCompatibleBitmap($hDC, $aDim[0], $aDim[1])
Global Const $hDC_backbuffer = _WinAPI_CreateCompatibleDC($hDC)
Global Const $DC_obj = _WinAPI_SelectObject($hDC_backbuffer, $hHBitmap)
Global Const $hCanvas = _GDIPlus_GraphicsCreateFromHDC($hDC_backbuffer)
Global Const $hPen = _GDIPlus_PenCreate(0xFFFFFFFF)
_GDIPlus_GraphicsSetSmoothingMode($hCanvas, 4)
_GDIPlus_GraphicsDrawImageRect($hCanvas, $hImage, 0, 0, $aDim[0], $aDim[1])

Global $hButton1 = GUICtrlCreateButton(' < ', 10, $aDim[1] + 10, 40)
Global $Slider = GUICtrlCreateSlider(60, $aDim[1] + 10, 360, 25)
GUICtrlSetLimit(-1, 360, 0)         ; change min/max value
Global $hButton2 = GUICtrlCreateButton(' > ', 430, $aDim[1] + 10, 40)

Global $hSlider = GUICtrlGetHandle($Slider)
Global $Dummy = GUICtrlCreateDummy()
GUIRegisterMsg($WM_HSCROLL, "WM_HVSCROLL") ;horz slider

GUISetState(@SW_SHOW, $hGUI)
_ImageRefresh()

; Loop until the user exits.
While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop
        Case $Dummy
            _GDIPlus_ImageRotate($hImage, GUICtrlRead($Slider))
            _ImageRefresh()
        Case $hButton1
            _FineTuning(1)
        Case $hButton2
            _FineTuning(2)
    EndSwitch
WEnd

_WinAPI_SelectObject($hDC_backbuffer, $DC_obj)
_WinAPI_ReleaseDC($hGUI, $hDC)
_WinAPI_DeleteDC($hDC_backbuffer)
_WinAPI_DeleteObject($hHBitmap)
_GDIPlus_PenDispose($hPen)
_GDIPlus_ImageDispose($hImage)
_GDIPlus_Shutdown()

Func _FineTuning($iDirection)
    Local Static $iAngle
    Local Static $iSliderPos = GUICtrlRead($Slider)
    If $iSliderPos <> GUICtrlRead($Slider) Then
        $iAngle = 0
        $iSliderPos = GUICtrlRead($Slider)
    EndIf

    Switch $iDirection
        Case 1
            $iAngle -= .1
            If $iAngle < 0 Then
                $iAngle = .9
                $iSliderPos -= 1
                If $iSliderPos < 0 Then $iSliderPos = 359
                GUICtrlSetData($Slider, $iSliderPos)
            EndIf

        Case 2
            $iAngle += .1
            If $iAngle > .9 Then
                $iAngle = 0
                $iSliderPos += 1
                If $iSliderPos > 359 Then $iSliderPos = 0
                GUICtrlSetData($Slider, $iSliderPos)
            EndIf
    EndSwitch

    _GDIPlus_ImageRotate($hImage, $iSliderPos + $iAngle)
    _ImageRefresh()

EndFunc   ;==>_FineTuning

Func _ImageRefresh()
    _GDIPlus_GraphicsClear($hCanvas)
    _GDIPlus_GraphicsDrawImageRect($hCanvas, $hImage, 0, 0, $aDim[0], $aDim[1])
    _WinAPI_BitBlt($hDC, 0, 0, $aDim[0], $aDim[1], $hDC_backbuffer, 0, 0, $SRCCOPY)
EndFunc   ;==>_ImageRefresh


Func _GDIPlus_ImageRotate($hImage, $fDegree)
    ; ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $fDegree = ' & $fDegree & @TAB & '>Error code: ' & @error & @CRLF) ;### Debug Console
    Local $hMatrix = _GDIPlus_MatrixCreate()
    _GDIPlus_MatrixTranslate($hMatrix, $aDim[0] / 2, $aDim[1] / 2)
    _GDIPlus_MatrixRotate($hMatrix, $fDegree)
    _GDIPlus_MatrixTranslate($hMatrix, -$aDim[0] / 2, -$aDim[1] / 2)
    _GDIPlus_GraphicsSetTransform($hCanvas, $hMatrix)
    _GDIPlus_MatrixDispose($hMatrix)
EndFunc   ;==>_GDIPlus_ImageRotate

Func WM_HVSCROLL($hwnd, $iMsg, $wParam, $lParam)
    #forceref $hwnd, $iMsg, $wParam, $lParam
    Switch $iMsg
        Case $WM_HSCROLL
            Switch $lParam
                Case $hSlider
                    GUICtrlSendToDummy($Dummy, GUICtrlRead($Slider))
            EndSwitch
        Case $WM_VSCROLL
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_HVSCROLL

 

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Link to comment
Share on other sites

4 hours ago, UEZ said:

@Gianni There are certainly many ways to design TheSaint's app. 😉

more ideas, more fun... 🙂
added a crop and copy to clipboard function (UDF download required. see link in list)

I hope there are no bugs

;Coded by UEZ 2024-03-16
; [few mods by Gianni :) ]
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>

#include <Clipboard.au3>
#include <ScreenCapture.au3>

#include <.\CropTool.au3> ; <-- get this from below link
; https://www.autoitscript.com/forum/topic/203545-%E2%9C%82%EF%B8%8F-quick-crop-tool/

Opt("GUICloseOnESC", 0)
; --- rulers -----
Global $iThickness = 5
Global $hGUI1 = GUICreate("", @DesktopWidth, $iThickness, 0, @DesktopHeight / 2, $WS_POPUP, $WS_EX_TOPMOST)
GUICtrlCreateLabel("", 0, 0, @DesktopWidth, $iThickness, -1, $GUI_WS_EX_PARENTDRAG)
GUISetBkColor(0x00ff00, $hGUI1)
WinSetTrans($hGUI1, "", 127)
GUISetState(@SW_HIDE, $hGUI1)
Global $hGUI2 = GUICreate("", $iThickness, @DesktopHeight, @DesktopWidth / 2, 0, $WS_POPUP, $WS_EX_TOPMOST)
GUICtrlCreateLabel("", 0, 0, $iThickness, @DesktopHeight, -1, $GUI_WS_EX_PARENTDRAG)
GUISetBkColor(0x00ff00, $hGUI2)
WinSetTrans($hGUI2, "", 127)
GUISetState(@SW_HIDE, $hGUI2)
; ----------------

Global $sFile = "cover.jpg" ; FileOpenDialog("Select an image", "", "Images (*.jpg;*.png;*.gif;*.bmp)")

If @error Then Exit
Global $aRect, $bResult, $hBmp, $aTemp, $bPreviousStatus, $aBKcolor[2] = [0x008800, 0x00ff00]

_GDIPlus_Startup()
Global $hImage = _GDIPlus_ImageLoadFromFile($sFile)
Global $aDim = _GDIPlus_ImageGetDimension($hImage)
Global Const $hGUI = GUICreate("Image Rotate", $aDim[0], $aDim[1] + 50)

Global Const $hDC = _WinAPI_GetDC($hGUI)
Global Const $hHBitmap = _WinAPI_CreateCompatibleBitmap($hDC, $aDim[0], $aDim[1])
Global Const $hDC_backbuffer = _WinAPI_CreateCompatibleDC($hDC)
Global Const $DC_obj = _WinAPI_SelectObject($hDC_backbuffer, $hHBitmap)
Global Const $hCanvas = _GDIPlus_GraphicsCreateFromHDC($hDC_backbuffer)
Global Const $hPen = _GDIPlus_PenCreate(0xFFFFFFFF)
_GDIPlus_GraphicsSetSmoothingMode($hCanvas, 4)
_GDIPlus_GraphicsDrawImageRect($hCanvas, $hImage, 0, 0, $aDim[0], $aDim[1])

Global $hButton1 = GUICtrlCreateButton(' < ', 10, $aDim[1] + 10, 40)
GUICtrlSetTip(-1, 'fine rotation to the left')
Global $Slider = GUICtrlCreateSlider(60, $aDim[1] + 10, 360, 25)
GUICtrlSetLimit(-1, 360, 0)         ; change min/max value
GUICtrlSetTip(-1, 'slide to rotate the image')
Global $hButton2 = GUICtrlCreateButton(' > ', 430, $aDim[1] + 10, 40)
GUICtrlSetTip(-1, 'fine rotation to the right')
Global $hCrop = GUICtrlCreateButton(' # ', 480, $aDim[1] + 10, 40)
GUICtrlSetTip(-1, '1) move & resize the tool' & @CR & '2) right-click inside the tool area to copy the image' & @CR & '3) hit ESC to cancel cropping', 'Crop Tool')
Global $hButton3 = GUICtrlCreateButton(' + ', 530, $aDim[1] + 10, 40)
GUICtrlSetBkColor(-1, $aBKcolor[_SwitcRuler()])
GUICtrlSetTip(-1, 'show/hide ruler')

Global $hSlider = GUICtrlGetHandle($Slider)
Global $Dummy = GUICtrlCreateDummy()
GUIRegisterMsg($WM_HSCROLL, "WM_HVSCROLL") ;horz slider

GUISetState(@SW_SHOW, $hGUI)
_ImageRefresh()

; Loop until the user exits.
While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop
        Case $Dummy
            _GDIPlus_ImageRotate($hImage, GUICtrlRead($Slider))
            _ImageRefresh()
        Case $hButton1
            _FineTuning(1)
        Case $hButton2
            _FineTuning(2)
        Case $hCrop
            $bPreviousStatus = _SwitcRuler(0)
            $aTemp = WinGetPos($hGUI)
            $aRect = _Crop($aTemp[0] + ($aTemp[2] / 2) - 50, $aTemp[1] + ($aTemp[3] / 2) - 50)
            If Not @extended Then
                ; below snippet by UEZ
                ; https://www.autoitscript.com/forum/topic/129333-screen-capture-to-clipboard/?do=findComment&comment=898287
                $hBmp = _ScreenCapture_Capture('', $aRect[0], $aRect[1], $aRect[0] + $aRect[2] - 1, $aRect[1] + $aRect[3] - 1, False)
                $bResult = _ClipBoard_Open(0) + _ClipBoard_Empty() + Not _ClipBoard_SetDataEx($hBmp, $CF_BITMAP)
                _ClipBoard_Close()
                If $bResult = 2 Then
                    MsgBox($MB_ICONINFORMATION, '', "the area was copied to the clipboard", 2)
                Else
                    MsgBox($MB_ICONERROR, '', "Something went wrong", 2)
                EndIf
            Else

            EndIf
            _SwitcRuler($bPreviousStatus)
        Case $hButton3
            _SwitcRuler(Not _SwitcRuler())
            GUICtrlSetBkColor($hButton3, $aBKcolor[_SwitcRuler()])

    EndSwitch
WEnd

_WinAPI_SelectObject($hDC_backbuffer, $DC_obj)
_WinAPI_ReleaseDC($hGUI, $hDC)
_WinAPI_DeleteDC($hDC_backbuffer)
_WinAPI_DeleteObject($hHBitmap)
_GDIPlus_PenDispose($hPen)
_GDIPlus_ImageDispose($hImage)
_GDIPlus_Shutdown()

Func _FineTuning($iDirection)
    Local Static $iAngle
    Local Static $iSliderPos = GUICtrlRead($Slider)
    If $iSliderPos <> GUICtrlRead($Slider) Then
        $iAngle = 0
        $iSliderPos = GUICtrlRead($Slider)
    EndIf

    Switch $iDirection
        Case 1
            $iAngle -= .1
            If $iAngle < 0 Then
                $iAngle = .9
                $iSliderPos -= 1
                If $iSliderPos < 0 Then $iSliderPos = 359
                GUICtrlSetData($Slider, $iSliderPos)
            EndIf

        Case 2
            $iAngle += .1
            If $iAngle > .9 Then
                $iAngle = 0
                $iSliderPos += 1
                If $iSliderPos > 359 Then $iSliderPos = 0
                GUICtrlSetData($Slider, $iSliderPos)
            EndIf
    EndSwitch

    _GDIPlus_ImageRotate($hImage, $iSliderPos + $iAngle)
    _ImageRefresh()

EndFunc   ;==>_FineTuning

Func _ImageRefresh()
    _GDIPlus_GraphicsClear($hCanvas)
    _GDIPlus_GraphicsDrawImageRect($hCanvas, $hImage, 0, 0, $aDim[0], $aDim[1])
    _WinAPI_BitBlt($hDC, 0, 0, $aDim[0], $aDim[1], $hDC_backbuffer, 0, 0, $SRCCOPY)
EndFunc   ;==>_ImageRefresh

Func _SwitcRuler($bOn = 2)
    Local Static $bStatus = 0
    Local $bReturn = $bStatus
    If $bOn = 1 Then
        GUISetState(@SW_SHOW, $hGUI1)
        GUISetState(@SW_SHOW, $hGUI2)
        $bStatus = 1
    ElseIf $bOn = 0 Then
        GUISetState(@SW_HIDE, $hGUI1)
        GUISetState(@SW_HIDE, $hGUI2)
        $bStatus = 0
    EndIf ; Else

    Return $bReturn
EndFunc   ;==>_SwitcRuler


Func _GDIPlus_ImageRotate($hImage, $fDegree)
    ; ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $fDegree = ' & $fDegree & @TAB & '>Error code: ' & @error & @CRLF) ;### Debug Console
    Local $hMatrix = _GDIPlus_MatrixCreate()
    _GDIPlus_MatrixTranslate($hMatrix, $aDim[0] / 2, $aDim[1] / 2)
    _GDIPlus_MatrixRotate($hMatrix, $fDegree)
    _GDIPlus_MatrixTranslate($hMatrix, -$aDim[0] / 2, -$aDim[1] / 2)
    _GDIPlus_GraphicsSetTransform($hCanvas, $hMatrix)
    _GDIPlus_MatrixDispose($hMatrix)
EndFunc   ;==>_GDIPlus_ImageRotate

Func WM_HVSCROLL($hwnd, $iMsg, $wParam, $lParam)
    #forceref $hwnd, $iMsg, $wParam, $lParam
    Switch $iMsg
        Case $WM_HSCROLL
            Switch $lParam
                Case $hSlider
                    GUICtrlSendToDummy($Dummy, GUICtrlRead($Slider))
            EndSwitch
        Case $WM_VSCROLL
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_HVSCROLL

 

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Link to comment
Share on other sites

few mods by Gianni

slightly understated 😉

 

Now we have hijacked TheSaint's topic... 👉👈

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

...it would be useful to modify the main window so that, instead of adapting to the size of the loaded image, it should allow you to load the image in a fixed-size (and/or resizable) window, allowing you to scroll the image within it. ...

Edited by Gianni
reduced post length

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Link to comment
Share on other sites

Nice to know I have inspired you two masterminds.

I am looking forward to checking these out. BIG THANKS.


On 3/18/2024 at 7:37 PM, Gianni said:

...it would be useful to modify the main window so that, instead of adapting to the size of the loaded image, it should allow you to load the image in a fixed-size (and/or resizable) window, allowing you to scroll the image within it. ...

I'm not sure about that, but certainly the major flaw of my code, is that you only see the end result image, so it is somewhat of a painstaking process of trial and error. The only real known is the final required 600x600 pixel size for the CD artwork that I embed in my music files. Admittedly most of the time I can source good enough CD covers from Discogs (primarily). It is only the odd rare instance when I need to crop, and even rarer to rotate. Trial and error guesses though, can waste a lot of time, so once again BIG THANKS.

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Link to comment
Share on other sites

@KaFu Thanks. Not sure why that did not turn up in my search here the other day ... or maybe it did and I didn't browse far enough.

Anyway, I've downloaded it to have a bit of a play when I get the time.


Normally, in the past, I have always used the free IrfanView for most of my image needs, often via its command-line, but I mostly try to avoid any kind of dependency these days, if I can. I could have just edited with that, as I have done so many times in the past. One issue for me though, has always been what JPG quality to save at, and GDIPlus simplifies that for me. That is especially the case, where the source file is not very large, and so not much quality to play around with, and so quite possibly I will end up with some even poorer looking image, without there seeming much I can do about that. I mostly care with my CD covers, because they are displayed big on my TV, and any faults can be glaring.

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Link to comment
Share on other sites

With using GDI to create JPGs to colors are always off.

The problem (after reading your edits) is probably due to the fact that GDI+ uses 4:1:1 subsampling for JPG files in it's default Encoder.
 The issue is that GDI+ enables chroma subsampling which modifies the color values accordingly.

That's why I use this program in BIC. I first write any resulting bitmap to a lossless temporary PNG file, and then convert it using "jpge".

https://code.google.com/archive/p/jpeg-compressor/

Alternatively you can always convert the output to PNG, where the output files are similarly small as with JPG imho (with the right settings), but lossless and with correct colors.

Edited by KaFu
Link to comment
Share on other sites

13 hours ago, KaFu said:

Alternatively you can always convert the output to PNG, where the output files are similarly small as with JPG imho (with the right settings), but lossless and with correct colors.

When not doing CD covers I tend to use PNG, but my recollection is that the embedded artwork in an MP3 or FLAC file needs to be JPG. I also use JPG for the folder image, as in Folder.jpg. which is what Windows or devices use.

I can't say I have noticed that color issue when I use GDI+.

The problem for me with an otherwise great program like IrfanView, is the quality when saving. If I go for 100%, I often end up with a file size multiple times bigger than the original, which I don't want and concerns me. So in the past I have had to play around with the degree of quality to get a better all-round result. The concern for me though, is a whether it is a bit like the old MP3 editors, that would convert to WAV so you could edit, and then reconvert back to MP3, having reduced the quality of the MP3 even more in the process.

With GDI+ I get a decent size file without any obvious or major difference in size or look, reduction or enlargement amounts aside. I have it set to the value recommended, which is 7 I think.

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Link to comment
Share on other sites

In your code you do not set the Quality for the output. Setting it manually I stumbled over an odd behavior.

What baffles me is the huge difference in JPG size, depending on the input file, and the behavior of the encoder.

  • When the input file is either BMP or PNG, the JPG encoder seems to default to a Quality of 75
  • When the input file is JPG, the JPG encoder does not seem to perform a re-encoding, but uses exactly the same Quality as the input file (I assume, as it's the same file size in KB)

 

  • Input BMP = 6076
  • Output JPG default = 216
  • Output JPG 75 = 216
  • Input PNG = 221
  • Output JPG default = 216
  • Output JPG 75 = 216
  • Input JPG = 734
  • Output JPG default = 734
  • Output JPG 75 = 208

You might save some KBs when you set the encoder Quality explicitly in your code, depends on the input quality. I always default to 95, but 92 is still very good (I think default for IrfanView).

#include <GDIPlus.au3>
#include <ScreenCapture.au3>

_GDIPlus_Startup()

_Screenshot("bmp")
_Screenshot("png")
_Screenshot("jpg")

Func _Screenshot($sExtension)

    _ScreenCapture_Capture(@ScriptDir & "\GDIPlus_Image_" & $sExtension & "." & $sExtension)

    Local $hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\GDIPlus_Image_" & $sExtension & "." & $sExtension)

    ; JPG, no quality param set
    Local $tParams
    Local $sCLSID = _GDIPlus_EncodersGetCLSID("JPG")
    _GDIPlus_ImageSaveToFileEx($hImage, @ScriptDir & "\GDIPlus_Image_" & $sExtension & "_00_Default.jpg", $sCLSID, $tParams)

    ; JPG, set to 75
    Local $tParams = _GDIPlus_ParamInit(1)
    Local $tData = DllStructCreate("int Quality")
    DllStructSetData($tData, "Quality", 75)
    Local $pData = DllStructGetPtr($tData)
    _GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, $pData)
    Local $pParams = DllStructGetPtr($tParams)
    _GDIPlus_ImageSaveToFileEx($hImage, @ScriptDir & "\GDIPlus_Image_" & $sExtension & "_75.jpg", $sCLSID, $pParams)

    ; JPG, set to 92
    Local $tParams = _GDIPlus_ParamInit(1)
    Local $tData = DllStructCreate("int Quality")
    DllStructSetData($tData, "Quality", 92)
    Local $pData = DllStructGetPtr($tData)
    _GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, $pData)
    Local $pParams = DllStructGetPtr($tParams)
    _GDIPlus_ImageSaveToFileEx($hImage, @ScriptDir & "\GDIPlus_Image_" & $sExtension & "_92.jpg", $sCLSID, $pParams)

    ; JPG, set to 95
    Local $tParams = _GDIPlus_ParamInit(1)
    Local $tData = DllStructCreate("int Quality")
    DllStructSetData($tData, "Quality", 95)
    Local $pData = DllStructGetPtr($tData)
    _GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, $pData)
    Local $pParams = DllStructGetPtr($tParams)
    _GDIPlus_ImageSaveToFileEx($hImage, @ScriptDir & "\GDIPlus_Image_" & $sExtension & "_95.jpg", $sCLSID, $pParams)

    ; JPG, set to 100
    Local $tParams = _GDIPlus_ParamInit(1)
    Local $tData = DllStructCreate("int Quality")
    DllStructSetData($tData, "Quality", 100)
    Local $pData = DllStructGetPtr($tData)
    _GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, $pData)
    Local $pParams = DllStructGetPtr($tParams)
    _GDIPlus_ImageSaveToFileEx($hImage, @ScriptDir & "\GDIPlus_Image_" & $sExtension & "_100.jpg", $sCLSID, $pParams)

EndFunc   ;==>_Screenshot

_GDIPlus_Shutdown()

Edit: Regarding the bad quality of the GDI JPG encoder, compare the PNG & BMP screenshot with their JPG pendants.

Edited by KaFu
Link to comment
Share on other sites

  • 2 months later...

@KaFu My apologies for not replying to you, but I did not get any notification that you had replied.

I am here now for a related reason, and will read your post ... and it might assist me with one aspect of my latest issue ... quality.

That issue, is in regard to Progressive JPG.

I have a need to detect when a JPG is such, using code, plus re-save the JPG as standard rather than Progressive, because my NeoTV 550 hardware media player does not support a Progressive JPG.

As you may be aware, I have been steadily going through my CD collection and ripping them to WAV files, and then at some future point converting to both FLAC and MP3, as well as embedding CD cover artwork.

A couple of days ago, I discovered that many of my CD images were not displaying on my hardware player. Alas I had temporarily forgotten about the Progressive JPG issue, and now I have a lot of albums to fix ... not only the folder image (Folder.jpg), but also the replacement of that image in my FLAC and MP3 files. So a fair bit of work to do, and of course I want to avoid that in future, so I need a way to quickly and easily detect that a JPG is a Progressive JPG one, and then deal with it with the least amount of quality loss.

I am already using a dropbox program I created, to more often than not just rename the folder cover image to just 'Folder.jpg', before then using that image to embed in my FLAC and MP3 files. If it needs to, it also converts to JPG from other formats and even resizes (to either 600x600 pixels or failing that 500x500) and in some cases it also crops.

Doing a trial, I discovered that if I pretend to resize, then a Progressive JPG image is converted to a standard one. By pretend, I mean resizing to the existing size.

But I noticed that the file size went from 218 Kb to 117 Kb, and that has me concerned, because I don't really want to lose any more quality than I have to, especially as some cover images I have are quite a bit smaller file size wise and not exactly great quality already in some cases.

In the distant past, when I found a non working image file that was a Progressive JPG image, I just used IrfanView to re-save as a standard JPG. I was always concerned about the image quality loss though, especially as IrfanView only really gives you options to recompress ... at least as far as I could tell.

Anyway, it may be that I am just going to make a bad situation worse, with no choice over the matter, after reading about what a Progressive JPG is.

Quote from Wikipedia.

Quote

There is also an interlaced progressive JPEG format, in which data is compressed in multiple passes of progressively higher detail. This is ideal for large images that will be displayed while downloading over a slow connection, allowing a reasonable preview after receiving only a portion of the data. However, support for progressive JPEGs is not universal. When progressive JPEGs are received by programs that do not support them (such as versions of Internet Explorer before Windows 7)  the software displays the image only after it has been completely downloaded.

Now to search the forum for some code to detect 'Progressive JPG' in the Exif data.

 

Edited by TheSaint

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Link to comment
Share on other sites

On 3/21/2024 at 4:03 AM, KaFu said:

When the input file is either BMP or PNG, the JPG encoder seems to default to a Quality of 75

Yep I have noticed that too.

On 3/21/2024 at 4:03 AM, KaFu said:

When the input file is JPG, the JPG encoder does not seem to perform a re-encoding, but uses exactly the same Quality as the input file (I assume, as it's the same file size in KB)

As you may have noticed in my prior post, I did a pretend resize (dimensions), and the resulting file size was almost half that of the original.

On my first attempt, I just loaded the JPG file and then re-saved it, but that did not change the Progressive JPG state, and the file size remained the same.

So I tried a resize, resizing from 600x600 to 600x600, so no change at all to dimensions, but significantly reduced in file size, but it did convert to a standard JPG rather than the original Progressive JPG state.

On 3/21/2024 at 4:03 AM, KaFu said:

In your code you do not set the Quality for the output.

That was a deliberate choice, as I was trying to avoid recompressing.

Edited by TheSaint

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Link to comment
Share on other sites

Here's a simple little dropbox based script for checking if a JPG file is a Progressive JPG.

NOTE - This may be imperfect, because it is counting on a specific byte set to be in the first 200 bytes or not. It has worked for me with a lot of files so far, without a failure.

FYI - I did attempt to leverage some help from ChatGPT, and it provided a basic script that did not work. For some weird reason it just looked at the first two bytes of a JPG file, which from my checking is the same for every JPG file. So I kept a few lines of code, while adding many more of my own after some trial and error. An online search provided me with the two bytes I needed (ÿÂ or FFC2). But I found they could also exist later in every file, so I limited the check to the first 200 bytes. I had of course tried to work further with ChatGPT, but ended up faring better on my own.

#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.14.2
 Author:         TheSaint

 Script Function:  Check a JPG image file to see if it is a Progressive JPG
    Template AutoIt script.

#ce ----------------------------------------------------------------------------

; FUNCTIONS
; DropboxGUI()
; IsProgressiveJPG($filepath)

#include <Constants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <AutoItConstants.au3>
#include <Misc.au3>

_Singleton("check-if-progressive-thsaint")

Global $filepath

DropboxGUI()

Exit

Func DropboxGUI()
    Local $Label_drop
    ;
    Local $attrib, $Dropbox, $path, $target
    ;
    $Dropbox = GuiCreate("Dropbox", 82, 90, Default, Default, $WS_OVERLAPPED + $WS_CAPTION + $WS_SYSMENU + $WS_VISIBLE _
                                        + $WS_CLIPSIBLINGS, $WS_EX_ACCEPTFILES + $WS_EX_TOPMOST + $WS_EX_TOOLWINDOW)
    ;
    $Label_drop = GUICtrlCreateLabel("", 0, 0, 80, 88, $SS_CENTER + $SS_NOTIFY)
    GUICtrlSetState($Label_drop, $GUI_DROPACCEPTED)
    GUICtrlSetFont($Label_drop, 8, 400)
    GUICtrlSetTip($Label_drop, "Drop an image file Here!")
    ;
    ; SETTINGS
    $target = "Drop an Image" & @LF & "File HERE" & @LF & "to" & @LF & "See If It Is" & @LF & "Progressive"
    GUICtrlSetData($Label_drop, @LF & $target)

    GuiSetState()
    While 1
        $msg = GuiGetMsg()
        Select
        Case $msg = $GUI_EVENT_CLOSE ;Or $msg = $Item_exit
            ; Close the Dropbox
            GUIDelete($Dropbox)
            ExitLoop
        Case $msg = $GUI_EVENT_DROPPED
            ; Image file checked by drag and drop
            If @GUI_DragId = -1 Then
                If FileExists(@GUI_DragFile) Then
                    $attrib = FileGetAttrib(@GUI_DragFile)
                    If StringInStr($attrib, "D") < 1 Then
                        $path = @GUI_DragFile
                        If IsProgressiveJPG($path) Then
                            MsgBox(262144, "Progressive JPG", "The file is a Progressive JPG.", 2, $Dropbox)
                        Else
                            MsgBox(262144, "Not Progressive JPG", "The file is NOT a Progressive JPG.", 1, $Dropbox)
                        EndIf
                    Else
                        MsgBox(262192, "Drag Error", "Needs to be a file not folder.", 0, $Dropbox)
                    EndIf
                Else
                    MsgBox(262192, "Drag Error", "Drag & Drop path doesn't exist.", 0, $Dropbox)
                EndIf
            Else
                MsgBox(262192, "Drag Error", "Drag & Drop failed.", 0, $Dropbox)
            EndIf
        Case Else
            ;;;
        EndSelect
    WEnd
EndFunc ;=> DropboxGUI

Func IsProgressiveJPG($filepath)
    Local $data, $file
    ;
    $file = FileOpen($filepath, $FO_BINARY)
    If $file = -1 Then
        Return False
    EndIf
    $data = FileRead($file, 200)
    FileClose($file)
    ;MsgBox(262144, "Data", $data)
    ;If StringInStr($data, "ÿÂ") > 0 Then
    If StringInStr($data, "FFC2") > 0 Then
        Return True
    Else
        Return False
    EndIf
EndFunc

P.S. Please reply here if you have a failure or can improve something. :) 

Edited by TheSaint

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

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...