Jump to content

Rotating a resized image in GDIPlus


ChrisL
 Share

Recommended Posts

I'm using the UDF by smashly but modifying it for my needs, but I'm a bit stuck with rotating the image.

If you try the example below and choose a vertical image then all is fine it creates a large image, if you choose a horizontal image it needs to rotate it but I can't get that bit to work.

#include <GDIPlus.au3>
#include <WinAPI.au3>
;24 x 16
;24 x 36

$file = FileOpenDialog("Load",@MyDocumentsDir,"All (*.*)" )
If @error then Exit

_ImageResize($file, @ScriptDir & "\RIP.jpg", 24 * 300, 36 * 300)


; #FUNCTION# =========================================================================================
; Name...........: _ImageResize
; Description....: Resize an image and optionally convert it to the format you want.
; Syntax.........: _ImageResize($sInImage, $sOutImage, $iW, $iH)
; Parameters ....: $sInImage  - Full path to the image to resize / convert.
;                              In types: *.bmp, *.gif, *.ico, *.jpg, *.jpeg, *.png, *.tif, *.tiff
;                 $sOutImage - Full path where to save the resized / converted image.
;                              Out types: *.bmp, *.gif, *.jpg, *.jpeg, *.png, *.tif, *.tiff
;                 $iW       - Width to resize image to.
;                 $iH       - Height to resize image to.
; Return values .: Success  - Return 1 and @error 0
;                 Failure   - Return 0 and @error 1~5
;                              @error 1 = In File does not exist
;                              @error 2 = In File format not supported
;                              @error 3 = Out File path does not exist
;                              @error 4 = Out file format not supported
;                              @error 5 = Resize Width or Height not an integer
; Author ........: smashly
; ====================================================================================================




Func _ImageResize($sInImage, $sOutImage, $iW, $iH)
    Local $sOP, $sOF, $sInExt, $Ext, $hBitmap, $hImage1, $hImage2, $hGraphic, $CLSID, $i = 0
    Local $sType = "BMP|GIF|ICO|JPG|JPEG|PNG|TIF|TIFF"
    
    If Not FileExists($sInImage) Then Return SetError(1, 0, 0)
    $sInExt = StringUpper(StringTrimLeft($sInImage, StringInStr($sInImage, ".", 0, -1)))
    If Not StringRegExp($sInExt, "\A(" & $sType & ")\z", 0) Then Return SetError(2, 0, 0)
    
  ;OutFile path, to use later on.
    $sOP = StringLeft($sOutImage, StringInStr($sOutImage, "\", 0, -1))
    If Not FileExists($sOP) Then Return SetError(3, 0, 0)
    
  ;OutFile name, to use later on.
    $sOF = StringTrimLeft($sOutImage, StringInStr($sOutImage, "\", 0, -1))

  ;OutFile extension , to use for the encoder later on.
    $Ext = StringUpper(StringTrimLeft($sOutImage, StringInStr($sOutImage, ".", 0, -1)))
    If Not StringRegExp($Ext, "\A(" & $sType & ")\z", 0) Or $Ext = "ICO" Then Return SetError(4, 0, 0)

    If Not IsInt($iW) And Not IsInt($iH) Then Return SetError(5, 0, 0)
    
    
  ;Start GDIPlus
    _GDIPlus_Startup()
    
  ;Load the image you want to resize.
    $hImage2 = _GDIPlus_ImageLoadFromFile($sInImage)
    $iOriginalHeight = _GDIPlus_ImageGetHeight($hImage2)
    $iOriginalWidth = _GDIPlus_ImageGetWidth($hImage2)
    
;create a blank DIBSection
    If $iOriginalHeight > $iOriginalWidth then 
        $hBitmap = _WinAPI_CreateCompatibleBitmapSection($iW,$iH)
    Else
        $hBitmap = _WinAPI_CreateCompatibleBitmapSection($iH,$iW)
    EndIf
    
    
    $hImage1 = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
    
  ;Get the graphic context of the blank bitmap
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage1)

  ;Draw the loaded image onto the blank bitmap at the new size 
    If $iOriginalHeight > $iOriginalWidth then 
        _GDIPlus_GraphicsDrawImageRect($hGraphic, $hImage2, 0, 0, $iW, $iH)
    Else
        _GDIPlus_GraphicsDrawImageRect($hGraphic, $hImage2, 0, 0, $iH, $iW)
        
    EndIf
    
;see if the image needs to be saved rotated
    $Rotate = 0
    If $iW < $iH and $iOriginalHeight < $iOriginalWidth  then $Rotate = 1   
    If  $iW > $iH and $iOriginalHeight > $iOriginalWidth then $Rotate = 1

;Get the encoder of to save the resized image in the format you want.
    $CLSID = _GDIPlus_EncodersGetCLSID($Ext)


    If $Rotate = 1 then 
; Set up parameters for 90 degree rotation
        $tData = DllStructCreate("int Data")
        DllStructSetData($tData, "Data", $GDIP_EVTTRANSFORMROTATE90)
        $tParams = _GDIPlus_ParamInit (1)
        _GDIPlus_ParamAdd ($tParams, $GDIP_EPGTRANSFORMATION, 1, $GDIP_EPTLONG, DllStructGetPtr($tData, "Data"))        
    EndIf

  ;Save the new resized image.
    If $Rotate = 1 then 
        Msgbox(0,"Save Rotated",_GDIPlus_ImageSaveToFileEx($hImage1, $sOutImage, $CLSID, DllStructGetPtr($tParams)) )
    Else
        Msgbox(0,"Save",_GDIPlus_ImageSaveToFileEx($hImage1, $sOutImage, $CLSID))
    EndIf

  ;Clean up and shutdown GDIPlus.
    _GDIPlus_ImageDispose($hImage1)
    _GDIPlus_ImageDispose($hImage2)
    _GDIPlus_GraphicsDispose($hGraphic)
    _WinAPI_DeleteObject($hBitmap)
    _GDIPlus_Shutdown()
    Return SetError(0, 0, 1)
EndFunc ;==>_ImageResize



Func _WinAPI_CreateCompatibleBitmapSection($iWidth,$iHeight,$iBitCount=24)
    
    $tBMI = DllStructCreate($tagBITMAPINFO)
    DllStructSetData($tBMI, "Size", DllStructGetSize($tBMI) - 4)
    DllStructSetData($tBMI, "Width", $iWidth)
    DllStructSetData($tBMI, "Height", $iHeight)
    DllStructSetData($tBMI, "Planes", 1)
    DllStructSetData($tBMI, "BitCount", $iBitCount)

    $aDIB = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', _
            'ptr', 0, _
            'ptr', DllStructGetPtr($tBMI), _
            'uint', 1, _
            'ptr*', 0, _
            'ptr', 0, _
            'uint', 0)  
    Return $aDib[0]
    
EndFunc
Edited by ChrisL
Link to comment
Share on other sites

Well the only way I can get this to work is to sav it to disk and re-open it which is rubbish

There must be a better way

#include <GDIPlus.au3>
#include <WinAPI.au3>

;24 x 16
;24 x 36

$file = FileOpenDialog("Load",@MyDocumentsDir,"All (*.*)" )
If @error then Exit

;$timer = TimerInit()
_ImageResize($file, @ScriptDir & "\RIP.jpg", 24 * 300, 36 * 300)
;MSgbox(0,"","Rip time = " & Round(TimerDiff($timer) / 1000,2) & " Seconds")

; #FUNCTION# =========================================================================================
; Name...........: _ImageResize
; Description....: Resize an image and optionally convert it to the format you want.
; Syntax.........: _ImageResize($sInImage, $sOutImage, $iW, $iH)
; Parameters ....: $sInImage  - Full path to the image to resize / convert.
;                              In types: *.bmp, *.gif, *.ico, *.jpg, *.jpeg, *.png, *.tif, *.tiff
;                 $sOutImage - Full path where to save the resized / converted image.
;                              Out types: *.bmp, *.gif, *.jpg, *.jpeg, *.png, *.tif, *.tiff
;                 $iW       - Width to resize image to.
;                 $iH       - Height to resize image to.
; Return values .: Success  - Return 1 and @error 0
;                 Failure   - Return 0 and @error 1~5
;                              @error 1 = In File does not exist
;                              @error 2 = In File format not supported
;                              @error 3 = Out File path does not exist
;                              @error 4 = Out file format not supported
;                              @error 5 = Resize Width or Height not an integer
; Author ........: smashly
; ====================================================================================================



Func _ImageResize($sInImage, $sOutImage, $iW, $iH)
    Local $sOP, $sOF, $sInExt, $Ext, $hBitmap, $hImage1, $hImage2, $hGraphic, $CLSID, $i = 0
    Local $sType = "BMP|GIF|ICO|JPG|JPEG|PNG|TIF|TIFF"
    
    If Not FileExists($sInImage) Then Return SetError(1, 0, 0)
    $sInExt = StringUpper(StringTrimLeft($sInImage, StringInStr($sInImage, ".", 0, -1)))
    If Not StringRegExp($sInExt, "\A(" & $sType & ")\z", 0) Then Return SetError(2, 0, 0)
    
   ;OutFile path, to use later on.
    $sOP = StringLeft($sOutImage, StringInStr($sOutImage, "\", 0, -1))
    If Not FileExists($sOP) Then Return SetError(3, 0, 0)
    
   ;OutFile name, to use later on.
    $sOF = StringTrimLeft($sOutImage, StringInStr($sOutImage, "\", 0, -1))

   ;OutFile extension , to use for the encoder later on.
    $Ext = StringUpper(StringTrimLeft($sOutImage, StringInStr($sOutImage, ".", 0, -1)))
    If Not StringRegExp($Ext, "\A(" & $sType & ")\z", 0) Or $Ext = "ICO" Then Return SetError(4, 0, 0)

    If Not IsInt($iW) And Not IsInt($iH) Then Return SetError(5, 0, 0)
    
    
   ;Start GDIPlus
    _GDIPlus_Startup()
    
   ;Load the image you want to resize.
    $hImage2 = _GDIPlus_ImageLoadFromFile($sInImage)
    $iOriginalHeight = _GDIPlus_ImageGetHeight($hImage2)
    $iOriginalWidth = _GDIPlus_ImageGetWidth($hImage2)
    
;create a blank DIBSection
    If $iOriginalHeight > $iOriginalWidth then 
        $hBitmap = _WinAPI_CreateCompatibleBitmapSection($iW,$iH)
    Else
        $hBitmap = _WinAPI_CreateCompatibleBitmapSection($iH,$iW)
    EndIf
    
    
    $hImage1 = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
    
   ;Get the graphic context of the blank bitmap
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage1)

   ;Draw the loaded image onto the blank bitmap at the new size 
    If $iOriginalHeight > $iOriginalWidth then 
        _GDIPlus_GraphicsDrawImageRect($hGraphic, $hImage2, 0, 0, $iW, $iH)
    Else
        _GDIPlus_GraphicsDrawImageRect($hGraphic, $hImage2, 0, 0, $iH, $iW)
        
    EndIf
    
;see if the image needs to be saved rotated
    $Rotate = 0
    If $iW < $iH and $iOriginalHeight < $iOriginalWidth  then $Rotate = 1   
    If  $iW > $iH and $iOriginalHeight > $iOriginalWidth then $Rotate = 1

;Get the encoder of to save the resized image in the format you want.
    $CLSID = _GDIPlus_EncodersGetCLSID($Ext)

   ;Save the new resized image.
    If $Rotate = 1 then 
        _GDIPlus_ImageSaveToFileEx($hImage1, $sOutImage & ".tmp", $CLSID);save the image temporarily
        $hImage = _GDIPlus_ImageLoadFromFile($sOutImage & ".tmp");reload the tmp image
        $tData = DllStructCreate("int Data")
        DllStructSetData($tData, "Data", $GDIP_EVTTRANSFORMROTATE90)
        $tParams = _GDIPlus_ParamInit (1)
        _GDIPlus_ParamAdd ($tParams, $GDIP_EPGTRANSFORMATION, 1, $GDIP_EPTLONG, DllStructGetPtr($tData, "Data"))
        _GDIPlus_ImageSaveToFileEx ($hImage, $sOutImage, $CLSID, DllStructGetPtr($tParams));resave with the rotate
        _GDIPlus_ImageDispose($hImage)

    Else
        Msgbox(0,"Save",_GDIPlus_ImageSaveToFileEx($hImage1, $sOutImage, $CLSID))
    EndIf

   ;Clean up and shutdown GDIPlus.
    _GDIPlus_ImageDispose($hImage1)
    _GDIPlus_ImageDispose($hImage2)
    _GDIPlus_GraphicsDispose($hGraphic)
    _WinAPI_DeleteObject($hBitmap)
    
    While FileExists($sOutImage & ".tmp");delete the .tmp
        FileDelete($sOutImage & ".tmp")
    Wend
        
    _GDIPlus_Shutdown()
    Return SetError(0, 0, 1)
EndFunc  ;==>_ImageResize



Func _WinAPI_CreateCompatibleBitmapSection($iWidth,$iHeight,$iBitCount=24)
    
    $tBMI = DllStructCreate($tagBITMAPINFO)
    DllStructSetData($tBMI, "Size", DllStructGetSize($tBMI) - 4)
    DllStructSetData($tBMI, "Width", $iWidth)
    DllStructSetData($tBMI, "Height", $iHeight)
    DllStructSetData($tBMI, "Planes", 1)
    DllStructSetData($tBMI, "BitCount", $iBitCount)

    $aDIB = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', _
            'ptr', 0, _
            'ptr', DllStructGetPtr($tBMI), _
            'uint', 1, _
            'ptr*', 0, _
            'ptr', 0, _
            'uint', 0)  
    Return $aDib[0]
    
EndFunc
Link to comment
Share on other sites

Well the only way I can get this to work is to sav it to disk and re-open it which is rubbish

There must be a better way

#include <GDIPlus.au3>
#include <WinAPI.au3>

;24 x 16
;24 x 36

$file = FileOpenDialog("Load",@MyDocumentsDir,"All (*.*)" )
If @error then Exit

;$timer = TimerInit()
_ImageResize($file, @ScriptDir & "\RIP.jpg", 24 * 300, 36 * 300)
;MSgbox(0,"","Rip time = " & Round(TimerDiff($timer) / 1000,2) & " Seconds")

; #FUNCTION# =========================================================================================
; Name...........: _ImageResize
; Description....: Resize an image and optionally convert it to the format you want.
; Syntax.........: _ImageResize($sInImage, $sOutImage, $iW, $iH)
; Parameters ....: $sInImage  - Full path to the image to resize / convert.
;                              In types: *.bmp, *.gif, *.ico, *.jpg, *.jpeg, *.png, *.tif, *.tiff
;                 $sOutImage - Full path where to save the resized / converted image.
;                              Out types: *.bmp, *.gif, *.jpg, *.jpeg, *.png, *.tif, *.tiff
;                 $iW       - Width to resize image to.
;                 $iH       - Height to resize image to.
; Return values .: Success  - Return 1 and @error 0
;                 Failure   - Return 0 and @error 1~5
;                              @error 1 = In File does not exist
;                              @error 2 = In File format not supported
;                              @error 3 = Out File path does not exist
;                              @error 4 = Out file format not supported
;                              @error 5 = Resize Width or Height not an integer
; Author ........: smashly
; ====================================================================================================






Func _ImageResize($sInImage, $sOutImage, $iW, $iH)
    Local $sOP, $sOF, $sInExt, $Ext, $hBitmap, $hImage1, $hImage2, $hGraphic, $CLSID, $i = 0
    Local $sType = "BMP|GIF|ICO|JPG|JPEG|PNG|TIF|TIFF"
    
    If Not FileExists($sInImage) Then Return SetError(1, 0, 0)
    $sInExt = StringUpper(StringTrimLeft($sInImage, StringInStr($sInImage, ".", 0, -1)))
    If Not StringRegExp($sInExt, "\A(" & $sType & ")\z", 0) Then Return SetError(2, 0, 0)
    
;OutFile path, to use later on.
    $sOP = StringLeft($sOutImage, StringInStr($sOutImage, "\", 0, -1))
    If Not FileExists($sOP) Then Return SetError(3, 0, 0)
    
;OutFile name, to use later on.
    $sOF = StringTrimLeft($sOutImage, StringInStr($sOutImage, "\", 0, -1))

;OutFile extension , to use for the encoder later on.
    $Ext = StringUpper(StringTrimLeft($sOutImage, StringInStr($sOutImage, ".", 0, -1)))
    If Not StringRegExp($Ext, "\A(" & $sType & ")\z", 0) Or $Ext = "ICO" Then Return SetError(4, 0, 0)

    If Not IsInt($iW) And Not IsInt($iH) Then Return SetError(5, 0, 0)
    
    
;Start GDIPlus
    _GDIPlus_Startup()
    
;Load the image you want to resize.
    $hImage2 = _GDIPlus_ImageLoadFromFile($sInImage)
    $iOriginalHeight = _GDIPlus_ImageGetHeight($hImage2)
    $iOriginalWidth = _GDIPlus_ImageGetWidth($hImage2)
    
;create a blank DIBSection
    If $iOriginalHeight > $iOriginalWidth then 
        $hBitmap = _WinAPI_CreateCompatibleBitmapSection($iW,$iH)
    Else
        $hBitmap = _WinAPI_CreateCompatibleBitmapSection($iH,$iW)
    EndIf
    
    
    $hImage1 = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
    
;Get the graphic context of the blank bitmap
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage1)

;Draw the loaded image onto the blank bitmap at the new size 
    If $iOriginalHeight > $iOriginalWidth then 
        _GDIPlus_GraphicsDrawImageRect($hGraphic, $hImage2, 0, 0, $iW, $iH)
    Else
        _GDIPlus_GraphicsDrawImageRect($hGraphic, $hImage2, 0, 0, $iH, $iW)
        
    EndIf
    
;see if the image needs to be saved rotated
    $Rotate = 0
    If $iW < $iH and $iOriginalHeight < $iOriginalWidth  then $Rotate = 1   
    If  $iW > $iH and $iOriginalHeight > $iOriginalWidth then $Rotate = 1

;Get the encoder of to save the resized image in the format you want.
    $CLSID = _GDIPlus_EncodersGetCLSID($Ext)

;Save the new resized image.
    If $Rotate = 1 then 
        _GDIPlus_ImageSaveToFileEx($hImage1, $sOutImage & ".tmp", $CLSID);save the image temporarily
        $hImage = _GDIPlus_ImageLoadFromFile($sOutImage & ".tmp");reload the tmp image
        $tData = DllStructCreate("int Data")
        DllStructSetData($tData, "Data", $GDIP_EVTTRANSFORMROTATE90)
        $tParams = _GDIPlus_ParamInit (1)
        _GDIPlus_ParamAdd ($tParams, $GDIP_EPGTRANSFORMATION, 1, $GDIP_EPTLONG, DllStructGetPtr($tData, "Data"))
        _GDIPlus_ImageSaveToFileEx ($hImage, $sOutImage, $CLSID, DllStructGetPtr($tParams));resave with the rotate
        _GDIPlus_ImageDispose($hImage)

    Else
        Msgbox(0,"Save",_GDIPlus_ImageSaveToFileEx($hImage1, $sOutImage, $CLSID))
    EndIf

;Clean up and shutdown GDIPlus.
    _GDIPlus_ImageDispose($hImage1)
    _GDIPlus_ImageDispose($hImage2)
    _GDIPlus_GraphicsDispose($hGraphic)
    _WinAPI_DeleteObject($hBitmap)
    
    While FileExists($sOutImage & ".tmp");delete the .tmp
        FileDelete($sOutImage & ".tmp")
    Wend
        
    _GDIPlus_Shutdown()
    Return SetError(0, 0, 1)
EndFunc;==>_ImageResize



Func _WinAPI_CreateCompatibleBitmapSection($iWidth,$iHeight,$iBitCount=24)
    
    $tBMI = DllStructCreate($tagBITMAPINFO)
    DllStructSetData($tBMI, "Size", DllStructGetSize($tBMI) - 4)
    DllStructSetData($tBMI, "Width", $iWidth)
    DllStructSetData($tBMI, "Height", $iHeight)
    DllStructSetData($tBMI, "Planes", 1)
    DllStructSetData($tBMI, "BitCount", $iBitCount)

    $aDIB = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', _
            'ptr', 0, _
            'ptr', DllStructGetPtr($tBMI), _
            'uint', 1, _
            'ptr*', 0, _
            'ptr', 0, _
            'uint', 0)  
    Return $aDib[0]
    
EndFunc
I suppose the problem is that in your first post $image1 is a bitmap which you are trying to save to file as though it was an image. When you save it and load it as an image you are effectively converting the bitmap to an image.

EDIT: Or rather I should say that presumably the parameter for the JPEG encoder CLSID can't be applied to a bitmap.

Edited by martin
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

I suppose the problem is that in your first post $image1 is a bitmap which you are trying to save to file as though it was an image. When you save it and load it as an image you are effectively converting the bitmap to an image.

EDIT: Or rather I should say that presumably the parameter for the JPEG encoder CLSID can't be applied to a bitmap.

But it can use the CLSID because I can save it as a JPG I just can't rotate it, I can save it as a jpg and reload it as an image object.

I can even re-load it as a _GDIPlus_BitmapCreateFromFile($sOutImage & ".tmp") and it will then rotate on save as jpg.

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