Jump to content

Crop an image in a window


Zoldex
 Share

Recommended Posts

This is my attempt on loading and let the user select only a portion of an image.

I found some samples by Melba23 and UEZ and tried to glue things together.

I think I've almost done it but still have some problems:

  • Resizing and displaying image is not always proportional (just try the script with different resolution images, expecially big ones)

  • The rectangle selection to crop is wrong: it actually selects a different region of the screen

  • Function _GUICtrlStatic_SetImage does not work. Temporarily fixed using _WinAPI_DeleteObject instead...
Any hint would be greatly appreciated!

#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#Include <ScreenCapture.au3>
#Include <Misc.au3>
#include <StaticConstants.au3>
Global $iX1, $iY1, $iX2, $iY2, $aPos, $sMsg, $sBMP_Path
Global Const $IMAGE_BITMAP = 0 ; Needed for GUICtrlSendMsg.
Global Const $STM_SETIMAGE = 0x0172 ; Needed for GUICtrlSendMsg.

Local $GUIimg_title,$GUIwidth,$GUIheight,$GUILeft,$GUITop

Local $filename = FileOpenDialog("Select image", @ScriptDir, "Image (*.jpg;*.bmp)", 3)
$GUIimg_title = $filename

_GDIPlus_Startup()

Local $imagefromfile = _GDIPlus_ImageLoadFromFile($filename) ;Create an image object based on a file [OK] **NOTA PER LA ROTAZIONE VEDI HELP FILE!**
Local $GUIwidth = _GDIPlus_ImageGetWidth ($imagefromfile)
Local $GUIheight = _GDIPlus_ImageGetHeight ($imagefromfile)

;try to create a smaller window if the pictures is bigger than Desktop
If $GUIwidth > @DesktopWidth Then
$GUIwidth = @DesktopWidth - 6
EndIf
If $GUIheight > @DesktopHeight Then
$GUIheight = @DesktopHeight - 73 ; rought attempt to show the window bar...
EndIf
$GUILeft = (@DesktopWidth - $GUIwidth) / 2
$GUITop = (@DesktopHeight - $GUIheight) / 2

$hBitmap_resized = _GDIPlus_ScaleImage($imagefromfile, $GUIwidth, $GUIheight); attempts to scale the image but it not always proportional..

_GDIPlus_ImageDispose($imagefromfile)

; Display image
$hBitmap_GUI = GUICreate($GUIimg_title & " [" & $GUIwidth & "x" & $GUIheight & "]", $GUIwidth, $GUIheight,$GUILeft,$GUITop)
$hPic = GUICtrlCreatePic("", 0, 0, $GUIwidth, $GUIheight)
GUISetState()

Local $hHBitmap_resized = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap_resized); creates an handle
_WinAPI_DeleteObject(GUICtrlSendMsg($hPic, $STM_SETIMAGE, $IMAGE_BITMAP, $hHBitmap_resized)) ; Updates the GUI - It works instead of _GDIPlus_ImageDispose($hHBitmap_resized) [OK]
_WinAPI_DeleteObject($hHBitmap_resized)


;~ _GUICtrlStatic_SetImage($hPic, $hBitmap_resized); does not seems to work... using _WinAPI_DeleteObject above







_GDIPlus_Shutdown()

; Create GUI
;~ Local $GUITop =
$hMain_GUI = GUICreate("Select a function", 480, 50)

$hRect_Button = GUICtrlCreateButton("Crop", 10, 10, 80, 30)
$hRot_90_plus_Button = GUICtrlCreateButton("+90°", 95, 10, 50, 30)
$hRot_90_minus_Button = GUICtrlCreateButton("-90°", 150, 10, 50, 30)
$hOK_Button = GUICtrlCreateButton("OK", 305, 10, 50, 30)
$hCancel_Button = GUICtrlCreateButton("Cancel", 360, 10, 80, 30)

GUISetState()

While 1

Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE, $hCancel_Button
FileDelete(@ScriptDir & "Rect.bmp")
Exit
Case $hRect_Button
GUISetState(@SW_HIDE, $hMain_GUI)
Mark_Rect($GUIwidth,$GUIheight,$GUILeft,$GUITop);selects wrong area!!
; Capture selected area
$sBMP_Path = @ScriptDir & "Rect.bmp"
;~ _ScreenCapture_Capture($sBMP_Path, $iX1, $iY1, $iX2, $iY2, False)
_ScreenCapture_CaptureWnd($sBMP_Path, $hBitmap_GUI,$iX1, $iY1, $iX2, $iY2, False)
GUISetState(@SW_SHOW, $hMain_GUI)
GUIDelete($hBitmap_GUI)
; Display image
$hBitmap_GUI = GUICreate("Selected Rectangle", $iX2 - $iX1 + 1, $iY2 - $iY1 + 1, 100, 100)
$hPic = GUICtrlCreatePic(@ScriptDir & "Rect.bmp", 0, 0, $iX2 - $iX1 + 1, $iY2 - $iY1 + 1)
GUISetState()
case $hRot_90_plus_Button
; Rotate +90
case $hRot_90_minus_Button
;Rotate -90
case $hOK_Button
;should return the resulting picture object
EndSwitch

WEnd

; -------------

Func Mark_Rect($width = @DesktopWidth, $height = @DesktopHeight, $Left = 0, $Top = 0);Made by Melba23 - Arguments added by me

Local $aMouse_Pos, $hMask, $hMaster_Mask, $iTemp
Local $UserDLL = DllOpen("user32.dll")

Global $hRectangle_GUI = GUICreate("", $width, $height, $Left, $Top, $WS_POPUP, $WS_EX_TOOLWINDOW + $WS_EX_TOPMOST);create fading
_GUICreateInvRect($hRectangle_GUI, 0, 0, 1, 1)
GUISetBkColor(0)
WinSetTrans($hRectangle_GUI, "", 95)
GUISetState(@SW_SHOW, $hRectangle_GUI)
GUISetCursor(3, 1, $hRectangle_GUI)

; Wait until mouse button pressed
While Not _IsPressed("01", $UserDLL)
Sleep(10)
WEnd

; Get first mouse position
$aMouse_Pos = MouseGetPos()
$iX1 = $aMouse_Pos[0]
$iY1 = $aMouse_Pos[1]

; Draw rectangle while mouse button pressed
While _IsPressed("01", $UserDLL)

$aMouse_Pos = MouseGetPos()

; Set in correct order if required
If $aMouse_Pos[0] < $iX1 Then
$iX_Pos = $aMouse_Pos[0]
$iWidth = $iX1 - $aMouse_Pos[0]
Else
$iX_Pos = $iX1
$iWidth = $aMouse_Pos[0] - $iX1
EndIf
If $aMouse_Pos[1] < $iY1 Then
$iY_Pos = $aMouse_Pos[1]
$iHeight = $iY1 - $aMouse_Pos[1]
Else
$iY_Pos = $iY1
$iHeight = $aMouse_Pos[1] - $iY1
EndIf

_GUICreateInvRect($hRectangle_GUI, $iX_Pos, $iY_Pos, $iWidth, $iHeight)

Sleep(10)

WEnd

; Get second mouse position
$iX2 = $aMouse_Pos[0]
$iY2 = $aMouse_Pos[1]

; Set in correct order if required
If $iX2 < $iX1 Then
$iTemp = $iX1
$iX1 = $iX2
$iX2 = $iTemp
EndIf
If $iY2 < $iY1 Then
$iTemp = $iY1
$iY1 = $iY2
$iY2 = $iTemp
EndIf

GUIDelete($hRectangle_GUI)
DllClose($UserDLL)

EndFunc ;==>Mark_Rect

Func _GUICreateInvRect($hWnd, $iX, $iY, $iW, $iH)

$hMask_1 = _WinAPI_CreateRectRgn(0, 0, @DesktopWidth, $iY)
$hMask_2 = _WinAPI_CreateRectRgn(0, 0, $iX, @DesktopHeight)
$hMask_3 = _WinAPI_CreateRectRgn($iX + $iW, 0, @DesktopWidth, @DesktopHeight)
$hMask_4 = _WinAPI_CreateRectRgn(0, $iY + $iH, @DesktopWidth, @DesktopHeight)

_WinAPI_CombineRgn($hMask_1, $hMask_1, $hMask_2, 2)
_WinAPI_CombineRgn($hMask_1, $hMask_1, $hMask_3, 2)
_WinAPI_CombineRgn($hMask_1, $hMask_1, $hMask_4, 2)

_WinAPI_DeleteObject($hMask_2)
_WinAPI_DeleteObject($hMask_3)
_WinAPI_DeleteObject($hMask_4)

_WinAPI_SetWindowRgn($hWnd, $hMask_1, 1)

EndFunc








Func _GDIPlus_ScaleImage($hImage, $iW, $iH, $iInterpolationMode = 7) ;coded by UEZ 2012
Local $hBitmap = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromScan0", "int", $iW, "int", $iH, "int", 0, "int", 0x0026200A, "ptr", 0, "int*", 0)
If @error Then Return SetError(3, 0, 0)
$hBitmap = $hBitmap[6]
Local $hBmpCtxt = _GDIPlus_ImageGetGraphicsContext($hBitmap)
DllCall($ghGDIPDll, "uint", "GdipSetInterpolationMode", "handle", $hBmpCtxt, "int", $iInterpolationMode)
_GDIPlus_GraphicsDrawImageRect($hBmpCtxt, $hImage, 0, 0, $iW, $iH)
_GDIPlus_ImageDispose($hImage)
_GDIPlus_GraphicsDispose($hBmpCtxt)
Return $hBitmap
EndFunc




Func _GUICtrlStatic_SetImage($iCtrlId, $hBitmap)
Local Const $STM_SETIMAGE = 0x0172
Local Const $IMAGE_BITMAP = 0
Local Const $SS_BITMAP = 0xE
Local Const $GWL_STYLE = -16

If IsHWnd($iCtrlId) Then
If WinGetProcess($iCtrlId) <> @AutoItPID Then Return SetError(1,0,0)
Else
$iCtrlId = GUICtrlGetHandle($iCtrlId)
If Not $iCtrlId Then Return SetError(2,0,0)
EndIf
; set SS_BITMAP style to control
Local $oldStyle = DllCall("user32.dll", "long", "GetWindowLong", "hwnd", $iCtrlId, "int", $GWL_STYLE)
If @error Then Return SetError(3, 0, 0)
DllCall("user32.dll", "long", "SetWindowLong", "hwnd", $iCtrlId, "int", $GWL_STYLE, "long", BitOR($oldStyle[0], $SS_BITMAP))
If @error Then Return SetError(4, 0, 0)
Local $oldBmp = DllCall("user32.dll", "handle", "SendMessageW", "hwnd", $iCtrlId, "int", $STM_SETIMAGE, "wparam", $IMAGE_BITMAP, "handle", $hBitmap)
If @error Then Return SetError(5, 0, 0)
If $oldBmp[0] Then _WinAPI_DeleteObject($oldBmp[0])
Return 1
EndFunc
Link to comment
Share on other sites

use

_WinAPI_GetSystemMetrics

to get the TitleBar and the Border dimensions

My code:

PredictText: Predict Text of an Edit Control Like Scite. Remote Gmail: Execute your Scripts through Gmail. StringRegExp:Share and learn RegExp.

Run As System: A command line wrapper around PSEXEC.exe to execute your apps scripts as System (LSA). Database: An easier approach for _SQ_LITE beginners.

MathsEx: A UDF for Fractions and LCM, GCF/HCF. FloatingText: An UDF for make your text floating. Clipboard Extendor: A clipboard monitoring tool. 

Custom ScrollBar: Scroll Bar made with GDI+, user can use bitmaps instead. RestrictEdit_SRE: Restrict text in an Edit Control through a Regular Expression.

Link to comment
Share on other sites

Its better to Use only one GUI to carry out your Functions

If you use more than one then take care that you use GuiGetMsg(1)

orelse it will cause problems !!

My code:

PredictText: Predict Text of an Edit Control Like Scite. Remote Gmail: Execute your Scripts through Gmail. StringRegExp:Share and learn RegExp.

Run As System: A command line wrapper around PSEXEC.exe to execute your apps scripts as System (LSA). Database: An easier approach for _SQ_LITE beginners.

MathsEx: A UDF for Fractions and LCM, GCF/HCF. FloatingText: An UDF for make your text floating. Clipboard Extendor: A clipboard monitoring tool. 

Custom ScrollBar: Scroll Bar made with GDI+, user can use bitmaps instead. RestrictEdit_SRE: Restrict text in an Edit Control through a Regular Expression.

Link to comment
Share on other sites

This draws the right rectangle

#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>
#include <ScreenCapture.au3>
#include <Misc.au3>
#include <StaticConstants.au3>
Global $iX1, $iY1, $iX2, $iY2, $aPos, $sMsg, $sBMP_Path
Global Const $IMAGE_BITMAP = 0 ; Needed for GUICtrlSendMsg.
Global Const $STM_SETIMAGE = 0x0172 ; Needed for GUICtrlSendMsg.

Global Const $sysHeight = _WinAPI_GetSystemMetrics(4)
Global Const $sysWidth = _WinAPI_GetSystemMetrics(7)
Global Const $sysdHeifht = _WinAPI_GetSystemMetrics(8)

Local $GUIimg_title, $GUIwidth, $GUIheight, $GUILeft, $GUITop

Local $filename = FileOpenDialog("Select image", @ScriptDir, "Image (*.jpg;*.bmp)", 3)
If @error Then Exit 1
$GUIimg_title = $filename

_GDIPlus_Startup()

Local $imagefromfile = _GDIPlus_ImageLoadFromFile($filename) ;Create an image object based on a file [OK] **NOTA PER LA ROTAZIONE VEDI HELP FILE!**
Local $GUIwidth = _GDIPlus_ImageGetWidth($imagefromfile)
Local $GUIheight = _GDIPlus_ImageGetHeight($imagefromfile)

;try to create a smaller window if the pictures is bigger than Desktop
If $GUIwidth > @DesktopWidth Then
$GUIwidth = @DesktopWidth - 6
EndIf
If $GUIheight > @DesktopHeight Then
$GUIheight = @DesktopHeight - 73 ; rought attempt to show the window bar...
EndIf

$GUILeft = (@DesktopWidth - $GUIwidth) / 2
$GUITop = (@DesktopHeight - $GUIheight) / 2

$hBitmap_resized = _GDIPlus_ScaleImage($imagefromfile, $GUIwidth, $GUIheight); attempts to scale the image but it not always proportional..

_GDIPlus_ImageDispose($imagefromfile)

; Display image
$hBitmap_GUI = GUICreate($GUIimg_title & " [" & $GUIwidth & "x" & $GUIheight & "]", $GUIwidth + 50, $GUIheight + 50 + 100, $GUILeft, $GUITop)
$hPic = GUICtrlCreatePic("", 25, 25 + 100, $GUIwidth, $GUIheight)
GUISetState()

Local $hHBitmap_resized = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap_resized); creates an handle
_WinAPI_DeleteObject(GUICtrlSendMsg($hPic, $STM_SETIMAGE, $IMAGE_BITMAP, $hHBitmap_resized)) ; Updates the GUI - It works instead of _GDIPlus_ImageDispose($hHBitmap_resized) [OK]
_WinAPI_DeleteObject($hHBitmap_resized)

_GDIPlus_Shutdown()


$hRect_Button = GUICtrlCreateButton("Crop", 25, 25, 80, 30)
$hRot_90_plus_Button = GUICtrlCreateButton("+90°", 145, 25, 50, 30)
$hRot_90_minus_Button = GUICtrlCreateButton("-90°", 245, 25, 50, 30)

GUISetState()

While 1

Switch GUIGetMsg()
Case -3
;
Case $hRect_Button
$pPos = WinGetPos($hBitmap_GUI)
Mark_Rect($GUIwidth, $GUIheight, $pPos[0] + 25 + $sysWidth, $pPos[1] + 125 + $sysHeight + $sysdHeifht);selects wrong area!!
GUISwitch($hBitmap_GUI)
EndSwitch

WEnd

; -------------

Func Mark_Rect($width = @DesktopWidth, $height = @DesktopHeight, $Left = 0, $Top = 0);Made by Melba23 - Arguments added by me

Local $aMouse_Pos, $hMask, $hMaster_Mask, $iTemp
Local $UserDLL = DllOpen("user32.dll")

Global $hRectangle_GUI = GUICreate("", $width, $height, $Left, $Top, $WS_POPUP, $WS_EX_TOOLWINDOW + $WS_EX_TOPMOST);create fading
_GUICreateInvRect($hRectangle_GUI, 0, 0, 1, 1)
GUISetBkColor(0)
WinSetTrans($hRectangle_GUI, "", 95)
GUISetState(@SW_SHOW, $hRectangle_GUI)
GUISetCursor(3, 1, $hRectangle_GUI)

; Wait until mouse button pressed
While Not _IsPressed("01", $UserDLL)
Sleep(10)
WEnd

; Get first mouse position
$aMouse_Pos = MouseGetPos()
$iX1 = $aMouse_Pos[0]
$iY1 = $aMouse_Pos[1]

; Draw rectangle while mouse button pressed
While _IsPressed("01", $UserDLL)

$aMouse_Pos = MouseGetPos()

; Set in correct order if required
If $aMouse_Pos[0] < $iX1 Then
$iX_Pos = $aMouse_Pos[0]
$iWidth = $iX1 - $aMouse_Pos[0]
Else
$iX_Pos = $iX1
$iWidth = $aMouse_Pos[0] - $iX1
EndIf
If $aMouse_Pos[1] < $iY1 Then
$iY_Pos = $aMouse_Pos[1]
$iHeight = $iY1 - $aMouse_Pos[1]
Else
$iY_Pos = $iY1
$iHeight = $aMouse_Pos[1] - $iY1
EndIf

_GUICreateInvRect($hRectangle_GUI, $iX_Pos, $iY_Pos, $iWidth, $iHeight)

Sleep(10)

WEnd

; Get second mouse position
$iX2 = $aMouse_Pos[0]
$iY2 = $aMouse_Pos[1]

; Set in correct order if required
If $iX2 < $iX1 Then
$iTemp = $iX1
$iX1 = $iX2
$iX2 = $iTemp
EndIf
If $iY2 < $iY1 Then
$iTemp = $iY1
$iY1 = $iY2
$iY2 = $iTemp
EndIf

GUIDelete($hRectangle_GUI)
DllClose($UserDLL)

EndFunc   ;==>Mark_Rect

Func _GUICreateInvRect($hWnd, $iX, $iY, $iW, $iH)

$hMask_1 = _WinAPI_CreateRectRgn(0, 0, @DesktopWidth, $iY)
$hMask_2 = _WinAPI_CreateRectRgn(0, 0, $iX, @DesktopHeight)
$hMask_3 = _WinAPI_CreateRectRgn($iX + $iW, 0, @DesktopWidth, @DesktopHeight)
$hMask_4 = _WinAPI_CreateRectRgn(0, $iY + $iH, @DesktopWidth, @DesktopHeight)

_WinAPI_CombineRgn($hMask_1, $hMask_1, $hMask_2, 2)
_WinAPI_CombineRgn($hMask_1, $hMask_1, $hMask_3, 2)
_WinAPI_CombineRgn($hMask_1, $hMask_1, $hMask_4, 2)

_WinAPI_DeleteObject($hMask_2)
_WinAPI_DeleteObject($hMask_3)
_WinAPI_DeleteObject($hMask_4)

_WinAPI_SetWindowRgn($hWnd, $hMask_1, 1)

EndFunc   ;==>_GUICreateInvRect

Func _GDIPlus_ScaleImage($hImage, $iW, $iH, $iInterpolationMode = 7) ;coded by UEZ 2012
Local $hBitmap = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromScan0", "int", $iW, "int", $iH, "int", 0, "int", 0x0026200A, "ptr", 0, "int*", 0)
If @error Then Return SetError(3, 0, 0)
$hBitmap = $hBitmap[6]
Local $hBmpCtxt = _GDIPlus_ImageGetGraphicsContext($hBitmap)
DllCall($ghGDIPDll, "uint", "GdipSetInterpolationMode", "handle", $hBmpCtxt, "int", $iInterpolationMode)
_GDIPlus_GraphicsDrawImageRect($hBmpCtxt, $hImage, 0, 0, $iW, $iH)
_GDIPlus_ImageDispose($hImage)
_GDIPlus_GraphicsDispose($hBmpCtxt)
Return $hBitmap
EndFunc   ;==>_GDIPlus_ScaleImage

Edited by PhoenixXL

My code:

PredictText: Predict Text of an Edit Control Like Scite. Remote Gmail: Execute your Scripts through Gmail. StringRegExp:Share and learn RegExp.

Run As System: A command line wrapper around PSEXEC.exe to execute your apps scripts as System (LSA). Database: An easier approach for _SQ_LITE beginners.

MathsEx: A UDF for Fractions and LCM, GCF/HCF. FloatingText: An UDF for make your text floating. Clipboard Extendor: A clipboard monitoring tool. 

Custom ScrollBar: Scroll Bar made with GDI+, user can use bitmaps instead. RestrictEdit_SRE: Restrict text in an Edit Control through a Regular Expression.

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

×
×
  • Create New...