Viet Posted July 10, 2016 Posted July 10, 2016 (edited) I made this little piece of code to crop images into circle shape using GDIPlus. When I try it with 96 DPI images, it works great. However, when the images are in 300 DPI, the results are incorrect (as you can see in the test image files >>> here). Here is the full script: expandcollapse popup#include <GDIplus.au3> clipCircle("96dpi.jpg", "96dpi_out.jpg") clipCircle("300dpi.jpg", "300dpi_out.jpg") Func clipCircle($sImageSource, $sImageDest) _GDIPlus_Startup() $hBitmapSource = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\" & $sImageSource) $hGraphicsSource = _GDIPlus_ImageGetGraphicsContext($hBitmapSource) _GDIPlus_GraphicsSetSmoothingMode($hGraphicsSource, $GDIP_SMOOTHINGMODE_HIGHQUALITY) $iX = _GDIPlus_ImageGetWidth($hBitmapSource) $iY = _GDIPlus_ImageGetHeight($hBitmapSource) ;~ Create an empty bitmap ;~ This does not work with 300 DPI images $hBitmapDest = _GDIPlus_BitmapCreateFromScan0($iX, $iY) $hGraphicsDest = _GDIPlus_ImageGetGraphicsContext($hBitmapDest) _GDIPlus_GraphicsSetSmoothingMode($hGraphicsDest, $GDIP_SMOOTHINGMODE_HIGHQUALITY) _GDIPlus_GraphicsClear($hGraphicsDest, 0xFFFFFFFF) $hPath = _GDIPlus_PathCreate() _GDIPlus_PathAddEllipse($hPath, 0, 0, $iX, $iY) _GDIPlus_GraphicsSetClipPath($hGraphicsDest, $hPath, 0) _GDIPlus_GraphicsDrawImage($hGraphicsDest, $hBitmapSource, 0, 0) _GDIPlus_ImageSaveToFile($hBitmapDest, @ScriptDir & "\" & $sImageDest) _GDIPlus_GraphicsDispose($hGraphicsSource) _GDIPlus_BitmapDispose($hBitmapSource) _GDIPlus_GraphicsDispose($hGraphicsDest) _GDIPlus_BitmapDispose($hBitmapDest) _GDIPlus_Shutdown() EndFunc Func clipCircle2($sImageSource, $sImageDest) _GDIPlus_Startup() $hBitmapSource = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\" & $sImageSource) $iX = _GDIPlus_ImageGetWidth($hBitmapSource) $iY = _GDIPlus_ImageGetHeight($hBitmapSource) ;~ Clone the source bitmap ;~ This works regardless of the image's DPI $hBitmapDest = _GDIPlus_BitmapCloneArea($hBitmapSource, 0, 0, $iX, $iY) $hGraphicsDest = _GDIPlus_ImageGetGraphicsContext($hBitmapDest) _GDIPlus_GraphicsSetSmoothingMode($hGraphicsDest, $GDIP_SMOOTHINGMODE_HIGHQUALITY) _GDIPlus_GraphicsClear($hGraphicsDest, 0xFFFFFFFF) $hPath = _GDIPlus_PathCreate() _GDIPlus_PathAddEllipse($hPath, 0, 0, $iX, $iY) _GDIPlus_GraphicsSetClipPath($hGraphicsDest, $hPath, 0) _GDIPlus_GraphicsDrawImage($hGraphicsDest, $hBitmapSource, 0, 0) _GDIPlus_ImageSaveToFile($hBitmapDest, @ScriptDir & "\" & $sImageDest) _GDIPlus_BitmapDispose($hBitmapSource) _GDIPlus_GraphicsDispose($hGraphicsDest) _GDIPlus_BitmapDispose($hBitmapDest) _GDIPlus_Shutdown() EndFunc So what am I doing wrong? Thanks. Edited July 10, 2016 by Viet
Synapsee Posted July 10, 2016 Posted July 10, 2016 (edited) expandcollapse popup#include <GDIplus.au3> clipCircle("96dpi.jpg", "96dpi_out.jpg") clipCircle("300dpi.jpg", "300dpi_out.jpg") clipCircle2("96dpi.jpg", "96dpi_out2.jpg") clipCircle2("300dpi.jpg", "300dpi_out2.jpg") Func clipCircle($sImageSource, $sImageDest) _GDIPlus_Startup() $hBitmapSource = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\" & $sImageSource) $hGraphicsSource = _GDIPlus_ImageGetGraphicsContext($hBitmapSource) _GDIPlus_GraphicsSetSmoothingMode($hGraphicsSource, $GDIP_SMOOTHINGMODE_HIGHQUALITY) $iX = _GDIPlus_ImageGetWidth($hBitmapSource) $iY = _GDIPlus_ImageGetHeight($hBitmapSource) ;~ Create an empty bitmap ;~ This does not work with 300 DPI images $hBitmapDest = _GDIPlus_BitmapCreateFromScan0($iX, $iY) ; New line : Fix DPI ===================================================================== _GDIPlus_BitmapSetResolution($hBitmapDest, _GDIPlus_ImageGetHorizontalResolution($hBitmapSource), _GDIPlus_ImageGetVerticalResolution($hBitmapSource)) $hGraphicsDest = _GDIPlus_ImageGetGraphicsContext($hBitmapDest) _GDIPlus_GraphicsSetSmoothingMode($hGraphicsDest, $GDIP_SMOOTHINGMODE_HIGHQUALITY) _GDIPlus_GraphicsClear($hGraphicsDest, 0xFFFFFFFF) $hPath = _GDIPlus_PathCreate() _GDIPlus_PathAddEllipse($hPath, 0, 0, $iX, $iY) _GDIPlus_GraphicsSetClipPath($hGraphicsDest, $hPath, 0) _GDIPlus_GraphicsDrawImage($hGraphicsDest, $hBitmapSource, 0, 0) ; New line =============================================================================== ; Improve Output Quality Local $sImgCLSID = _GDIPlus_EncodersGetCLSID("jpg") ;create CLSID for a JPG image file type Local $tGUID = _WinAPI_GUIDFromString($sImgCLSID) ;convert CLSID GUID to binary form and returns $tagGUID structure Local $tParams = _GDIPlus_ParamInit(1) ;initialize an encoder parameter list and return $tagGDIPENCODERPARAMS structure Local $tData = DllStructCreate("int Quality") ;create struct to set JPG quality setting DllStructSetData($tData, "Quality", 100) ;quality 0-100 (0: lowest, 100: highest) Local $pData = DllStructGetPtr($tData) ;get pointer from quality struct _GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, $pData) ;add a value to an encoder parameter list ; New line =============================================================================== _GDIPlus_ImageSaveToFileEx($hBitmapDest, @ScriptDir & "\" & $sImageDest, $sImgCLSID, $tParams ) _GDIPlus_GraphicsDispose($hGraphicsSource) _GDIPlus_BitmapDispose($hBitmapSource) _GDIPlus_GraphicsDispose($hGraphicsDest) _GDIPlus_BitmapDispose($hBitmapDest) _GDIPlus_Shutdown() EndFunc Func clipCircle2($sImageSource, $sImageDest) _GDIPlus_Startup() $hBitmapSource = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\" & $sImageSource) $iX = _GDIPlus_ImageGetWidth($hBitmapSource) $iY = _GDIPlus_ImageGetHeight($hBitmapSource) ;~ Clone the source bitmap ;~ This works regardless of the image's DPI $hBitmapDest = _GDIPlus_BitmapCloneArea($hBitmapSource, 0, 0, $iX, $iY) $hGraphicsDest = _GDIPlus_ImageGetGraphicsContext($hBitmapDest) _GDIPlus_GraphicsSetSmoothingMode($hGraphicsDest, $GDIP_SMOOTHINGMODE_HIGHQUALITY) _GDIPlus_GraphicsClear($hGraphicsDest, 0xFFFFFFFF) $hPath = _GDIPlus_PathCreate() _GDIPlus_PathAddEllipse($hPath, 0, 0, $iX, $iY) _GDIPlus_GraphicsSetClipPath($hGraphicsDest, $hPath, 0) _GDIPlus_GraphicsDrawImage($hGraphicsDest, $hBitmapSource, 0, 0) ; New line =============================================================================== ; Improve Output Quality Local $sImgCLSID = _GDIPlus_EncodersGetCLSID("jpg") ;create CLSID for a JPG image file type Local $tGUID = _WinAPI_GUIDFromString($sImgCLSID) ;convert CLSID GUID to binary form and returns $tagGUID structure Local $tParams = _GDIPlus_ParamInit(1) ;initialize an encoder parameter list and return $tagGDIPENCODERPARAMS structure Local $tData = DllStructCreate("int Quality") ;create struct to set JPG quality setting DllStructSetData($tData, "Quality", 100) ;quality 0-100 (0: lowest, 100: highest) Local $pData = DllStructGetPtr($tData) ;get pointer from quality struct _GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, $pData) ;add a value to an encoder parameter list ; New line =============================================================================== _GDIPlus_ImageSaveToFileEx($hBitmapDest, @ScriptDir & "\" & $sImageDest, $sImgCLSID, $tParams ) _GDIPlus_BitmapDispose($hBitmapSource) _GDIPlus_GraphicsDispose($hGraphicsDest) _GDIPlus_BitmapDispose($hBitmapDest) _GDIPlus_Shutdown() EndFunc ; https://www.autoitscript.com/forum/topic/120163-set-pixels-per-inch-using-gdi/?do=findComment&comment=834906 ; https://www.autoitscript.com/forum/topic/106021-gdipau3/ ; #FUNCTION# ==================================================================================================================== ; Name...........: _GDIPlus_BitmapSetResolution ; Description ...: Sets the resolution of this Bitmap object ; Syntax.........: _GDIPlus_BitmapSetResolution($hBitmap, $nDpiX, $nDpiY) ; Parameters ....: $hBitmap - Pointer to the Bitmap object ; $nDpiX - Value that specifies the horizontal resolution in dots per inch. ; $nDpiX - Value that specifies the vertical resolution in dots per inch. ; Return values .: Success - True ; Failure - False and either: ; |@error and @extended are set if DllCall failed ; |$GDIP_STATUS contains a non zero value specifying the error code ; Remarks .......: None ; Related .......: ; Link ..........; @@MsdnLink@@ GdipBitmapSetResolution ; Example .......; Yes ; =============================================================================================================================== Func _GDIPlus_BitmapSetResolution($hBitmap, $nDpiX, $nDpiY) Local $aResult = DllCall( $__g_hGDIPDll, "uint", "GdipBitmapSetResolution", "handle", $hBitmap, "float", $nDpiX, "float", $nDpiY) If @error Then Return SetError(@error, @extended, False) $GDIP_STATUS = $aResult[0] Return $aResult[0] = 0 EndFunc ;==>_GDIPlus_BitmapSetResolution Edited July 10, 2016 by Synapsee
Viet Posted July 10, 2016 Author Posted July 10, 2016 Thank you Synapsee very much, not only the script is fixed, but it's also improved to set the quality of the output file I would like to thank UEZ and the author of the GDIP.au3 script too Synapsee 1
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now