Jump to content
Sign in to follow this  
NiVZ

GDI Scale and Crop

Recommended Posts

NiVZ

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
NiVZ

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
  • Like 1

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  

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.