;Coded by UEZ 2009.12.23
#include <GUIConstantsEx.au3>
#include <GDIplus.au3>
#include <SliderConstants.au3>
#Include <GuiStatusBar.au3>
#include <WindowsConstants.au3>
#include <Misc.au3>


Opt('MustDeclareVars', 1)

Global $file, $msg

Do
    $file = FileOpenDialog("Select Image to load", @ScriptDir, "Images (*.jpg;*.png; *.bmp;*.gif)")
    If @error Then
        $msg = MsgBox(20, "Error", "Please select an image!")
        If $msg = 7 Then
            Exit
        Else
            SetError(1)
        EndIf
    EndIf
Until Not @error
Global $dll = DllOpen("user32.dll")
Global $date, $nMsg, $d, $date, $path, $suffix, $sCLSID
Global $encoder = "PNG"
_GDIPlus_Startup()
Global $hImage = _GDIPlus_BitmapCreateFromFile($file)
Global $iX = _GDIPlus_ImageGetWidth($hImage)
Global $iY = _GDIPlus_ImageGetHeight($hImage)
Global $hwnd = GUICreate("GDI+ Image Rotation by UEZ 2009", $iX + 200, $iY + 80, -1, -1)
Global $Button1 = GUICtrlCreateButton("Rotate_Image", $iX + 63, 36, 75, 25)
Global $Button2 = GUICtrlCreateButton("Save Image", $iX + 63, 92, 75, 25)
GUICtrlSetTip($Button2, "Image will be saved to " & @ScriptDir)
Global $Button3 = GUICtrlCreateButton("Exit", $iX + 63, $iY + 12, 75, 25)
Global $Input1 = GUICtrlCreateInput("", $iX + 63, 10, 73, 21)
GUICtrlSetTip($Input1, "Enter degree -359° - 359° here")
Global $Label = GUICtrlCreateLabel("Degree:", $iX + 20, 12, 40, 17)
Global $Slider = GUICtrlCreateSlider(10, $iY + 10, $iX - 10, 40, $TBS_AUTOTICKS + $TBS_ENABLESELRANGE)
GUICtrlSetTip($Slider, "-90° to 90°")
GUICtrlSetLimit($Slider, 90, -90)
GUICtrlSetData($Slider, 0)
Dim $aParts[4] = [106, 148, 250, -1]
Global $StatusBar = _GUICtrlStatusBar_Create($hwnd, $aParts)
GUISetState()
_GUICtrlStatusBar_SetText($StatusBar, "Degree from Slider:", 0)
_GUICtrlStatusBar_SetText($StatusBar, "Image Dimension:", 2)
_GUICtrlStatusBar_SetText($StatusBar, $iX & " x " & $iY, 3)
Global $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hwnd)
Global $hBitmap = _GDIPlus_BitmapCreateFromGraphics($iX, $iY, $hGraphic)
Global $hBackbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
Global $hMatrix = _GDIPlus_MatrixCreate()
_GDIPlus_MatrixTranslate($hMatrix, $iX / 2, $iY / 2)
Rotate_Image(0)

$d = GUICtrlRead($Slider)
_GUICtrlStatusBar_SetText($StatusBar, $d & "°   ", 1)
While Sleep(30)
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE, $Button3
            _GDIPlus_BitmapDispose($hBitmap)
            _GDIPlus_GraphicsDispose($hBackbuffer)
            _GDIPlus_MatrixDispose($hMatrix)
            _GDIPlus_GraphicsDispose($hGraphic)
            _GDIPlus_Shutdown()
            DllClose($dll)
            Exit
        Case $Button1
            $d = GUICtrlRead($Input1)
            If StringIsInt($d) Then
                Rotate_Image(Int($d))
            Else
                MsgBox(16, "Error", "Please enter an integer from -359 - 359!")
            EndIf
        Case $Button2
            $sCLSID = _GDIPlus_EncodersGetCLSID ($encoder)
            $path = @ScriptDir & "\Saved_"
            $date = @YEAR & "-" & @MON & "-" & @MDAY & "_" & @HOUR & @MIN & @SEC
            $suffix = "." & StringLower($encoder)
            _GDIPlus_Save_to_Image($path & $date & $suffix, $hwnd, $encoder, $iX, $iY)
            If Not @error Then
                MsgBox(0, "Information", "Image successfully save to: " & $path & $date & $suffix)
            Else
                MsgBox(16, "Error", "Image could not be saved!")
            EndIf
        Case $Slider, _IsPressed("01")
            $d = GUICtrlRead($Slider)
            _GUICtrlStatusBar_SetText($StatusBar, $d & "°   ", 1)
            Rotate_Image(Int($d))
    EndSwitch
WEnd

Func Rotate_Image($degree)
    _GDIPlus_GraphicsClear($hBackbuffer, 0xFFF0F0F0)
    _GDIPlus_MatrixRotate($hMatrix, $degree, "False")
    _GDIPlus_GraphicsSetTransform($hBackbuffer, $hMatrix)
    _GDIPlus_GraphicsDrawImageRect($hBackbuffer, $hImage, -$iX / 2, -$iY / 2, $iX, $iY)
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, 0, 0, $iX, $iY)
EndFunc

; #FUNCTION# =============================================================================
; Name...........: _GDIPlus_Save_to_Image
; Description ...: INTERNAL FUNCTION - save drawn image to file
; Syntax.........: _GDIPlus_Save_to_Image($file, $hWnd, $CLSID, $w, $h)
; Parameters ....: $file - filename
;                  $hWnd - handle to GUI
; Autor .........: ptrex, ProgAndy, UEZ
; =========================================================================================
Func _GDIPlus_Save_to_Image($file, $hWnd,  $CLSID = "PNG", $w = 0, $h = 0)
    Local $hDC, $memBmp, $memDC, $hImage, $size, $sCLSID
    If $file <> "" Or $hWnd <> "" Then
        If $w = 0 Or $h = 0 Then
            $size = WinGetClientSize($hWnd)
            $w = $size[0]
            $h = $size[1]
        EndIf
        $hDC = _WinAPI_GetDC($hWnd)
        $memDC = _WinAPI_CreateCompatibleDC($hDC)
        $memBmp = _WinAPI_CreateCompatibleBitmap($hDC, $w, $h)
        _WinAPI_SelectObject ($memDC, $memBmp)
        _WinAPI_BitBlt($memDC, 0, 0, $w, $h, $hDC, 0, 0, 0x00CC0020) ;  0x00CC0020 = $SRCCOPY
        $hImage = _GDIPlus_BitmapCreateFromHBITMAP ($memBmp)
        $sCLSID = _GDIPlus_EncodersGetCLSID ($CLSID)
        _GDIPlus_ImageSaveToFileEx ($hImage, $file, $sCLSID)
        If @error Then
            Return SetError(1, 0, 0)
        Else
            Return SetError(0, 0, 0)
        EndIf
        _GDIPlus_ImageDispose ($hImage)
        _WinAPI_ReleaseDC($hWnd, $hDC)
        _WinAPI_DeleteDC($memDC)
        _WinAPI_DeleteObject ($memBmp)
    Else
        Return SetError(1, 0, 0)
    EndIf
EndFunc
