Sign in to follow this  
Followers 0
NiVZ

GDI Scale and Crop

3 posts in this topic

Hello,

I wondered if someone could show me how to do the following using GDI:

1. Scale an image so the shortest edge is 88 pixels (keeping aspect ratio)

2. Crop the scaled image to select the center 88x88 pixels

Here is the code I have so far (with help from Prog@ndy) which squahes the entire image to 88x88

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#include <GuiListView.au3>
#include <GDIPlus.au3>
; Hide system tray icon
#NoTrayIcon
; Use Event mode
Opt("GUIOnEventMode", 1)
; Setup some constants
Const $ProgramName  = "Cropper"
Const $Version  = "v1.00"
Const $WindowTitle = $ProgramName & " " & $Version & " by NiVZ"
#Region ### START Koda GUI section ### Form=
$Form   = GUICreate($WindowTitle, 520, 520)
$TabHost  = GUICtrlCreateTab(10, 10, 504, 500)
$TabPhoto  = GUICtrlCreateTabItem("Photos")
   $grpPhotos   = GUICtrlCreateGroup("Photo List", 20, 40, 300, 460)
   $lvPhotos   = GUICtrlCreateListView("Photo Title", 30, 60, 280, 390, BitOR($LVS_SHOWSELALWAYS, $LVS_SINGLESEL, $LVS_REPORT, $LVS_NOCOLUMNHEADER))
   GUICtrlSetBKColor(-1, $GUI_BKCOLOR_LV_ALTERNATE)
   _GUICtrlListView_SetColumnWidth(-1, 0, 259)
   $btnAddPhoto  = GUICtrlCreateButton("Add Photo", 30, 460, 90, 30)
   GUICtrlCreateGroup("", -99, -99, 1, 1)
   Global $grpPThumb  = GUICtrlCreateGroup("Thumbnail", 330, 40, 170, 160)
   Global $imgPIcon   = GUICtrlCreatePic("", 370, 60, 88, 88, -1, $WS_EX_CLIENTEDGE)
   ;Global $butChange = GUICtrlCreateButton("Change Thumbnail", 360, 158, 108, 30)
   GUICtrlCreateGroup("", -99, -99, 1, 1) ;close group

#EndRegion ### END Koda GUI section ###
GUISetOnEvent($GUI_EVENT_CLOSE,   "SpecialEvents")
GUISetOnEvent($GUI_EVENT_MINIMIZE,   "SpecialEvents")
GUISetOnEvent($GUI_EVENT_RESTORE,   "SpecialEvents")
GUICtrlSetOnEvent($btnAddPhoto,   "AddPhoto")
_GDIPlus_Startup()
GUISetState(@SW_SHOW)

While 1
   ; Wait for events
WEnd


Func AddPhoto()
  
   ; Show the add videos dialog
   Local $aFiles = FileOpenDialog("Add Photo", @DesktopDir, "Photos (*.jpg)", 1 + 2 + 4, "", $Form)
  
   If @error Then
   ; Do nothing
   Else
  
   CropImage($aFiles)
  
  
   EndIf
  
EndFunc

Func CropImage($inFilename)
   ; Function written by [email="Prog@ndy"]Prog@ndy[/email] - many thanks
   Local $hLblDC = _WinAPI_GetDC(GUICtrlGetHandle($imgPIcon))
   Local $hBitmap = _WinAPI_CreateCompatibleBitmap($hLblDC, 88, 88)
   Local $hDC = _WinAPI_CreateCompatibleDC($hLblDC)
   _WinAPI_SelectObject($hDC, $hBitmap)
  
   Local $hImg = _GDIPlus_ImageLoadFromFile($inFilename)
   Local $hGraph = _GDIPlus_GraphicsCreateFromHDC($hDC)
   _GDIPlus_GraphicsDrawImageRect($hGraph, $hImg, 0, 0, 88, 88)
   _GDIPlus_GraphicsDispose($hGraph)
   _GDIPlus_ImageDispose($hImg)
   Local $tData = DllStructCreate("byte[15488]")
   Local $tBITMAPINFOHEADER  = DllStructCreate("DWORD biSize;LONG  biWidth;LONG  biHeight;WORD  biPlanes;WORD  biBitCount;DWORD biCompression;DWORD biSizeImage;LONG  biXPelsPerMeter;LONG  biYPelsPerMeter;DWORD biClrUsed;DWORD biClrImportant; DWORD colormap[3]")
   DllStructSetData($tBITMAPINFOHEADER, 1, DllStructGetSize($tBITMAPINFOHEADER))
   DllStructSetData($tBITMAPINFOHEADER, 2, 88)
   DllStructSetData($tBITMAPINFOHEADER, 3, -88)
   DllStructSetData($tBITMAPINFOHEADER, 4, 1)
   DllStructSetData($tBITMAPINFOHEADER, 5, 16)
   ; use default GDI32 16 bit format: 5-5-5
   DllStructSetData($tBITMAPINFOHEADER,  6, 0)
   ; Choose Colormask manually, example for 5-5-5
   ;~ DllStructSetData($tBITMAPINFOHEADER,  6, 3) ;BI_BITFIELDS
   ;~ DllStructSetData($tBITMAPINFOHEADER, "colormap", 0x7C00, 1) ;- Red mask
   ;~ DllStructSetData($tBITMAPINFOHEADER, "colormap", 0x03E0, 2) ;- Green mask
   ;~ DllStructSetData($tBITMAPINFOHEADER, "colormap", 0x001F, 3) ;- Blue mask
   _WinAPI_GetDIBits($hLblDC, $hBitmap, 0, 88, DllStructGetPtr($tData), DllStructGetPtr($tBITMAPINFOHEADER), 1)
   _WinAPI_ReleaseDC(GUICtrlGetHandle($imgPIcon), $hLblDC)
   _WinAPI_DeleteDC($hDC)
   _GUICtrlStatic_SetImage($imgPIcon, $hBitmap)
  
EndFunc


Func SpecialEvents()
    Select
   Case @GUI_CtrlId = $GUI_EVENT_CLOSE
   _GDIPlus_Shutdown()
            Exit
        ;Case @GUI_CtrlId = $GUI_EVENT_MINIMIZE
            ;MsgBox(0, "Window Minimized", "ID=" & @GUI_CtrlId & " WinHandle=" & @GUI_WinHandle)
        ;Case @GUI_CtrlId = $GUI_EVENT_RESTORE
            ;MsgBox(0, "Window Restored", "ID=" & @GUI_CtrlId & " WinHandle=" & @GUI_WinHandle)
    EndSelect
EndFunc   ;==>SpecialEvents

Func _GUICtrlStatic_SetImage($iCtrlId, $hBitmap)
  
   ; Function written by [email="Prog@ndy"]Prog@ndy[/email] - many thanks
  
   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

Thanks,

NiVZ

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Figured it out ;)

[/sup]
[sup]#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#include <GuiListView.au3>
#include <GDIPlus.au3>[/sup]
[sup]; Hide system tray icon
#NoTrayIcon[/sup]
[sup]; Use Event mode
Opt("GUIOnEventMode", 1)[/sup]
[sup]; Setup some constants
Const $ProgramName  = "Cropper"
Const $Version  = "v1.00"
Const $WindowTitle = $ProgramName & " " & $Version & " by NiVZ"[/sup]
[sup]#Region ### START Koda GUI section ### Form=
$Form   = GUICreate($WindowTitle, 520, 520)[/sup]
[sup]$TabHost  = GUICtrlCreateTab(10, 10, 504, 500)[/sup]
[sup]$TabPhoto  = GUICtrlCreateTabItem("Photos")[/sup]
[sup]   $grpPhotos   = GUICtrlCreateGroup("Photo List", 20, 40, 300, 460)
   $lvPhotos   = GUICtrlCreateListView("Photo Title", 30, 60, 280, 390, BitOR($LVS_SHOWSELALWAYS, $LVS_SINGLESEL, $LVS_REPORT, $LVS_NOCOLUMNHEADER))
   GUICtrlSetBKColor(-1, $GUI_BKCOLOR_LV_ALTERNATE)
   _GUICtrlListView_SetColumnWidth(-1, 0, 259)
   $btnAddPhoto  = GUICtrlCreateButton("Add Photo", 30, 460, 90, 30)[/sup]
[sup]   GUICtrlCreateGroup("", -99, -99, 1, 1)[/sup]
[sup]   Global $grpPThumb  = GUICtrlCreateGroup("Thumbnail", 330, 40, 170, 160)
   Global $imgPIcon   = GUICtrlCreatePic("", 370, 60, 88, 88, -1, $WS_EX_CLIENTEDGE)
   ;Global $butChange = GUICtrlCreateButton("Change Thumbnail", 360, 158, 108, 30)
   GUICtrlCreateGroup("", -99, -99, 1, 1) ;close group
 [/sup]
[sup]#EndRegion ### END Koda GUI section ###[/sup]
[sup]GUISetOnEvent($GUI_EVENT_CLOSE,   "SpecialEvents")
GUISetOnEvent($GUI_EVENT_MINIMIZE,   "SpecialEvents")
GUISetOnEvent($GUI_EVENT_RESTORE,   "SpecialEvents")
GUICtrlSetOnEvent($btnAddPhoto,   "AddPhoto")[/sup]
[sup]_GDIPlus_Startup()[/sup]

[sup]GUISetState(@SW_SHOW)[/sup]

[sup]While 1
   ; Wait for events
WEnd[/sup]
[sup] [/sup]

[sup]Func AddPhoto()
  
   ; Show the add photos dialog
   Local $aFiles = FileOpenDialog("Add Photo", @DesktopDir, "Photos (*.jpg)", 1 + 2, "", $Form)
  
   If @error Then
   ; Do nothing
   Else
  
   CropImage($aFiles)
  
  
   EndIf
  
EndFunc[/sup]
[sup] [/sup]
[sup]Func CropImage($inFilename)[/sup]
[sup]   ; Function written by [email="Prog@ndy"]Prog@ndy[/email] - many thanks[/sup]
[sup]   Local $newwidth, $newheight, $x, $y[/sup]
[sup]   Local $hLblDC = _WinAPI_GetDC(GUICtrlGetHandle($imgPIcon))
   Local $hBitmap = _WinAPI_CreateCompatibleBitmap($hLblDC, 88, 88)
   Local $hDC = _WinAPI_CreateCompatibleDC($hLblDC)
   _WinAPI_SelectObject($hDC, $hBitmap)
  
   Local $hImg = _GDIPlus_ImageLoadFromFile($inFilename)[/sup]
[sup]   Local $width  = _GDIPlus_ImageGetWidth($hImg)
   Local $height  = _GDIPlus_ImageGetHeight($hImg)
  
   If $width > $height Then
   ; Landscape
  
   $x = ($width - $height) /2
   $y = 0
  
   $newwidth = $height
   $newheight = $height
 
   ElseIf $height > $width Then
   ; Portrait
  
   $x = 0
   $y = ($height-$width) /2
  
   $newwidth = $width
   $newheight = $width  [/sup]
[sup]   Else
   ; Square
   $x = 0
   $y = 0
   $newwidth = $width
   $newheight = $width
   EndIf
     
   Local $hGraph = _GDIPlus_GraphicsCreateFromHDC($hDC)[/sup]
[sup]   ;_GDIPlus_GraphicsDrawImageRect($hGraph, $hImg, 0, 0, 88, 88)
   _GDIPlus_GraphicsDrawImageRectRect($hGraph, $hImg, $x, $y, $newwidth, $newheight, 0, 0, 88, 88)[/sup]
[sup]  
   _GDIPlus_GraphicsDispose($hGraph)
   _GDIPlus_ImageDispose($hImg)[/sup]
[sup]   Local $tData = DllStructCreate("byte[15488]")[/sup]
[sup]   Local $tBITMAPINFOHEADER  = DllStructCreate("DWORD biSize;LONG  biWidth;LONG  biHeight;WORD  biPlanes;WORD  biBitCount;DWORD biCompression;DWORD biSizeImage;LONG  biXPelsPerMeter;LONG  biYPelsPerMeter;DWORD biClrUsed;DWORD biClrImportant; DWORD colormap[3]")
   DllStructSetData($tBITMAPINFOHEADER, 1, DllStructGetSize($tBITMAPINFOHEADER))
   DllStructSetData($tBITMAPINFOHEADER, 2, 88)
   DllStructSetData($tBITMAPINFOHEADER, 3, -88)
   DllStructSetData($tBITMAPINFOHEADER, 4, 1)
   DllStructSetData($tBITMAPINFOHEADER, 5, 16)[/sup]
[sup]   ; use default GDI32 16 bit format: 5-5-5
   DllStructSetData($tBITMAPINFOHEADER,  6, 0)[/sup]
[sup]   ; Choose Colormask manually, example for 5-5-5
   ;~ DllStructSetData($tBITMAPINFOHEADER,  6, 3) ;BI_BITFIELDS
   ;~ DllStructSetData($tBITMAPINFOHEADER, "colormap", 0x7C00, 1) ;- Red mask
   ;~ DllStructSetData($tBITMAPINFOHEADER, "colormap", 0x03E0, 2) ;- Green mask
   ;~ DllStructSetData($tBITMAPINFOHEADER, "colormap", 0x001F, 3) ;- Blue mask[/sup]
[sup]   _WinAPI_GetDIBits($hLblDC, $hBitmap, 0, 88, DllStructGetPtr($tData), DllStructGetPtr($tBITMAPINFOHEADER), 1)[/sup]
[sup]   _WinAPI_ReleaseDC(GUICtrlGetHandle($imgPIcon), $hLblDC)
   _WinAPI_DeleteDC($hDC)[/sup]
[sup]   _GUICtrlStatic_SetImage($imgPIcon, $hBitmap)
  
EndFunc[/sup]

[sup]Func SpecialEvents()[/sup]
[sup]    Select
   Case @GUI_CtrlId = $GUI_EVENT_CLOSE
   _GDIPlus_Shutdown()
            Exit[/sup]
[sup]       ;Case @GUI_CtrlId = $GUI_EVENT_MINIMIZE
            ;MsgBox(0, "Window Minimized", "ID=" & @GUI_CtrlId & " WinHandle=" & @GUI_WinHandle)[/sup]
[sup]       ;Case @GUI_CtrlId = $GUI_EVENT_RESTORE
            ;MsgBox(0, "Window Restored", "ID=" & @GUI_CtrlId & " WinHandle=" & @GUI_WinHandle)[/sup]
[sup]    EndSelect[/sup]
[sup]EndFunc   ;==>SpecialEvents[/sup]

[sup]Func _GUICtrlStatic_SetImage($iCtrlId, $hBitmap)
  
   ; Function written by [email="Prog@ndy"]Prog@ndy[/email] - many thanks
  
   Local Const $STM_SETIMAGE = 0x0172
   Local Const $IMAGE_BITMAP = 0
   Local Const $SS_BITMAP = 0xE
   Local Const $GWL_STYLE = -16[/sup]
[sup]   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[/sup]
[sup]
Edited by NiVZ
1 person likes this

Share this post


Link to post
Share on other sites

Thanks for sharing this!

Share this post


Link to post
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
Sign in to follow this  
Followers 0