Jump to content

Recommended Posts

Posted (edited)

I enhanced the Delaunay function in my _GDIPlus_BitmapApplyFilter Dll and created a front-end GUI to generate Low-Polygon images:

Front-End-GUI.jpg

Code:

;Coded by UEZ v0.50 build 2026-02-07
;Requires 3.3.15.0+ version
#AutoIt3Wrapper_Version=p
#AutoIt3Wrapper_UseX64=y

#include <ComboConstants.au3>
#include <EditConstants.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <GuiStatusBar.au3>
#include <ScreenCapture.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include "_GDIPlus_BitmapApplyFilter.au3"

Global Const $hDLL = _GDIPlus_BitmapApplyFilter_Open()

Global Const $hGUI = GUICreate("Low-Polygon Maker v0.50", 252, 688, 4, 150, -1, $WS_EX_TOPMOST)
GUISetFont(8, 400, 0, "Consolas")
GUISetBkColor(0xABCDEF, $hGUI)

Global $aRet = _GDIPlus_BitmapCreateVerticalText("Coded by UEZ 2026", 21.75, "Consolas", 0x380000FF, 1)
Global Const $iPic_Label = GUICtrlCreatePic("", 204, 88, $aRet[1], $aRet[2])
_WinAPI_DeleteObject(GUICtrlSendMsg($iPic_Label, $STM_SETIMAGE, $IMAGE_BITMAP, $aRet[0]))

Global Const $iLbl_Title = GUICtrlCreateLabel("Low-Polygon Maker", 0, 8, 238, 32, $SS_CENTER)
GUICtrlSetFont(-1, 18, 400, 0, "Consolas")
Global Const $iLbl_EdgeDetection = GUICtrlCreateLabel("Edge Detection", 4, 58, 88, 17)
GUICtrlSetFont(-1, 8.5, 400, 0, "Consolas")
Global Const $iCombo_EdgeDetection = GUICtrlCreateCombo("", 96, 56, 145, 25, BitOR($CBS_DROPDOWNLIST, $CBS_AUTOHSCROLL))
GUICtrlSetFont(-1, 10, 400, 0, "Consolas")
GUICtrlSetData($iCombo_EdgeDetection, "SOBEL|" & _
                                      "SCHARR|" & _
                                      "PREWITT|" & _
                                      "FREI_CHEN|" & _
                                      "ROBERTS_CROSS|" & _
                                      "ROBINSON_COMPASS|" & _
                                      "KAYYALI|" & _
                                      "RIDGE_DETECTION|" & _
                                      "DIAGONAL_EDGES|" & _
                                      "SOVELVSPREWITT|" & _
                                      "OUTLINE3X3|" & _
                                      "LAPLACE3x3_1|" & _
                                      "LAPLACE3x3_2|" & _
                                      "LAPLACE5x5|" & _
                                      "EDGE_DETECTION1|" & _
                                      "EDGE_DETECTION2|" & _
                                      "EDGE_DETECTION3|" & _
                                      "EDGE_DETECTION4|" & _
                                      "EDGE_DETECTION5|" & _
                                      "EMBOSS1|" & _
                                      "EMBOSS2|" & _
                                      "EMBOSS3|" & _
                                      "EMBOSS4|" & _
                                      "KIRSCH|" & _
                                      "ISOTROPIC_SOBEL", _
                                      "DIAGONAL_EDGES")
Global $iInp_x = 96, $iInp_w = 100
Global Const $iLbl_Threshold = GUICtrlCreateLabel("ED Threshold", 4, 96, 76, 17)
GUICtrlSetFont(-1, 8.5, 400, 0, "Consolas")
Global Const $iInp_Threshold = GUICtrlCreateInput(0.35, $iInp_x, 92, $iInp_w, 21)
GUICtrlSetFont(-1, 10, 400, 0, "Consolas")
Global Const $iLbl_Blur = GUICtrlCreateLabel("Blur Level", 4, 128, 64, 17)
GUICtrlSetFont(-1, 8.5, 400, 0, "Consolas")
Global Const $iInp_Blur = GUICtrlCreateInput(4, $iInp_x, 124, $iInp_w, 21, BitOR($GUI_SS_DEFAULT_INPUT, $ES_NUMBER))
GUICtrlSetFont(-1, 10, 400, 0, "Consolas")
Global Const $iLbl_Colors = GUICtrlCreateLabel("Max. Colors", 4, 160, 70, 17)
GUICtrlSetFont(-1, 8.5, 400, 0, "Consolas")
Global Const $iInp_Colors = GUICtrlCreateInput(32, $iInp_x, 156, $iInp_w, 21, BitOR($GUI_SS_DEFAULT_INPUT, $ES_NUMBER))
GUICtrlSetFont(-1, 10, 400, 0, "Consolas")
Global Const $iLbl_MinSpace = GUICtrlCreateLabel("Min Space", 4, 192, 58, 17)
GUICtrlSetFont(-1, 8.5, 400, 0, "Consolas")
Global Const $iInp_MinSpace = GUICtrlCreateInput(4, $iInp_x, 188, $iInp_w, 21, BitOR($GUI_SS_DEFAULT_INPUT, $ES_NUMBER))
GUICtrlSetFont(-1, 10, 400, 0, "Consolas")
Global Const $iLbl_MaxSpace = GUICtrlCreateLabel("Max Space", 4, 224, 58, 17)
GUICtrlSetFont(-1, 8.5, 400, 0, "Consolas")
Global Const $iInp_MaxSpace = GUICtrlCreateInput(8, $iInp_x, 220, $iInp_w, 21, BitOR($GUI_SS_DEFAULT_INPUT, $ES_NUMBER))
GUICtrlSetFont(-1, 10, 400, 0, "Consolas")
Global Const $iLbl_BorderSpaceX = GUICtrlCreateLabel("Border Space X", 4, 256, 88, 17)
GUICtrlSetFont(-1, 8.5, 400, 0, "Consolas")
Global Const $iInp_BorderSpaceX = GUICtrlCreateInput(2, $iInp_x, 252, $iInp_w, 21, BitOR($GUI_SS_DEFAULT_INPUT, $ES_NUMBER))
GUICtrlSetFont(-1, 10, 400, 0, "Consolas")
Global Const $iLbl_BorderSpaceY = GUICtrlCreateLabel("Border Space Y", 4, 288, 88, 17)
GUICtrlSetFont(-1, 8.5, 400, 0, "Consolas")
Global Const $iInp_BorderSpaceY = GUICtrlCreateInput(2, $iInp_x, 284, $iInp_w, 21, BitOR($GUI_SS_DEFAULT_INPUT, $ES_NUMBER))
GUICtrlSetFont(-1, 10, 400, 0, "Consolas")
Global Const $iLbl_Alpha = GUICtrlCreateLabel("Edges Alpha", 4, 320, 70, 17)
GUICtrlSetFont(-1, 8.5, 400, 0, "Consolas")
Global Const $iInp_Alpha = GUICtrlCreateInput(32, $iInp_x, 316, $iInp_w, 21, BitOR($GUI_SS_DEFAULT_INPUT, $ES_NUMBER))
GUICtrlSetFont(-1, 10, 400, 0, "Consolas")
Global Const $iLbl_PosterizeLvl = GUICtrlCreateLabel("Posterize Lvl", 4, 352, 80, 17)
GUICtrlSetFont(-1, 8.5, 400, 0, "Consolas")
Global Const $iInp_PosterizeLvl = GUICtrlCreateInput(8, $iInp_x, 348, $iInp_w, 21, BitOR($GUI_SS_DEFAULT_INPUT, $ES_NUMBER))
GUICtrlSetFont(-1, 10, 400, 0, "Consolas")
GUICtrlSetTip(-1, "When the posterization level is set, the value for “Max. Colors” is ignored.")

Global Const $iChkB_ShowEdges = GUICtrlCreateCheckbox("Show Edges", 4, 386, 233, 17)
GUICtrlSetFont(-1, 8.5, 400, 0, "Consolas")
GUICtrlSetState(-1, $GUI_CHECKED)
Global Const $iChkB_Wireframe = GUICtrlCreateCheckbox("Show Wireframes only", 4, 414, 233, 17)
GUICtrlSetFont(-1, 8.5, 400, 0, "Consolas")

Global Const $iBtn_Apply = GUICtrlCreateButton("&Apply", 8, 448, 235, 57)
GUICtrlSetFont(-1, 12, 400, 0, "Consolas")
GUICtrlSetBkColor(-1, 0xCCCCFF)
Global Const $iBtn_Load = GUICtrlCreateButton("&Load Image", 8, 520, 235, 57)
GUICtrlSetFont(-1, 12, 400, 0, "Consolas")
GUICtrlSetBkColor(-1, 0xCCCCFF)
Global Const $iBtn_Save = GUICtrlCreateButton("&Save Image", 8, 592, 235, 57)
GUICtrlSetFont(-1, 12, 400, 0, "Consolas")
GUICtrlSetBkColor(-1, 0xCCCCFF)

Global $aParts[1] = [-1]
Global Const $hStatusBar = _GUICtrlStatusBar_Create($hGUI, $aParts, "Ready")
GUISetState(@SW_SHOW)

GUIRegisterMsg($WM_COMMAND, '_WM_COMMAND')

Global $aMsg, $hImage, $sImgFile, $hGUI_Display = 0, $hGDI_LowPoly, $sFileLowPoly

While 1
    $aMsg = GUIGetMsg(1)
    Switch $aMsg[1]
        Case $hGUI
            Switch $aMsg[0]
                Case $GUI_EVENT_CLOSE
                    GUIDelete($hGUI)
                    _GDIPlus_BitmapApplyFilter_Close()
                    Exit
                Case $iBtn_Load
                    $sImgFile = FileOpenDialog("Select a GDI+ supported image", "", "Images (*.bmp;*.gif;*.png;*.jpg;*.tif)", $FD_FILEMUSTEXIST, "", $hGUI)
                    If @error Then ContinueLoop
                    If Not FileExists($sImgFile) Then
                        MsgBox($MB_ICONERROR, "Error", $sImgFile & " doesn't exist", 30)
                        ContinueLoop
                    EndIf
                    If $hImage Then _GDIPlus_ImageDispose($hImage)
                    $hImage = _GDIPlus_ImageLoadFromFile($sImgFile)
                    If Not $hImage Then
                        MsgBox($MB_ICONERROR, "Error", "Unable to load file to GDI+", 30)
                        ContinueLoop
                    EndIf
                    EncodeAndDisplay($hImage)
                Case $iBtn_Save
                    If $sImgFile = "" Or $hGDI_LowPoly = 0 Then ContinueLoop
                    $sFileLowPoly = FileSaveDialog("Save Low-Polygone Image", "", "Images (*.bmp;*.gif;*.png;*.jp?g;*.tif?)", 0, StringRegExpReplace($sImgFile, "^.*\\([^\\]+)(\.[^.]+)$", "\1_Low-Polygon\2"), $hGUI)
                    If @error Or $sFileLowPoly = "" Then ContinueLoop
                    If _ScreenCapture_SaveImage($sFileLowPoly, $hGDI_LowPoly, False) Then
                        MsgBox($MB_ICONINFORMATION, "Information", "Low-Poly image saved.", 15, $hGUI)
                    Else
                        MsgBox($MB_ICONERROR, "Error", "Low-Poly image could not be save!", 15, $hGUI)
                    EndIf
                Case $iBtn_Apply
                    If $sImgFile = "" Or $hImage = 0 Then ContinueLoop
                    EncodeAndDisplay($hImage)
            EndSwitch
        Case $hGUI_Display
            Switch $aMsg[0]
                Case $GUI_EVENT_CLOSE
                    GUIDelete($hGUI_Display)
                    $hGUI_Display = 0
            EndSwitch
    EndSwitch
WEnd

Func EncodeAndDisplay($hImage)
    Local Const $iW = _GDIPlus_ImageGetWidth($hImage), $iH = _GDIPlus_ImageGetHeight($hImage)
    If $iW = 0 Or $iH = 0 Then Return SetError(1, 0, 0)
    Static $iWp = 0, $iHp = 0, $iPic_LowPoly
    If $iW <> $iWp Or $iH <> $iHp Then
        If $hGUI_Display Then GUIDelete($hGUI_Display)
        $hGUI_Display = GUICreate("", $iW, $iH, -1, -1, $WS_POPUP, $WS_EX_OVERLAPPEDWINDOW)
        $iPic_LowPoly = GUICtrlCreatePic("", 0, 0, $iW - 1, $iH - 1)
        GUISetState(@SW_SHOWNA, $hGUI_Display)
    EndIf
    $iWp = $iW
    $iHp = $iH

    If $hGDI_LowPoly Then _WinAPI_DeleteObject($hGDI_LowPoly)
    $hGDI_LowPoly = 0

;~ ConsoleWrite("Blur level: " & Number(GUICtrlRead($iInp_Blur)) & @CRLF & _
;~           "Kernel: " & Execute("$" & GUICtrlRead($iCombo_EdgeDetection)) & @CRLF & _
;~           "Threshold: " & Number(GUICtrlRead($iInp_Threshold), $NUMBER_DOUBLE) & @CRLF & _
;~           "Amount of Colors: " & Number(GUICtrlRead($iInp_Colors)) & @CRLF & _
;~           "Min Space: " & Number(GUICtrlRead($iInp_MinSpace)) & @CRLF & _
;~           "Max Space: " & Number(GUICtrlRead($iInp_MaxSpace)) & @CRLF & _
;~           "Border Space X: " & Number(GUICtrlRead($iInp_BorderSpaceX)) & @CRLF & _
;~           "Border Space Y: " & Number(GUICtrlRead($iInp_BorderSpaceY)) & @CRLF & _
;~           "Show Edges Checked: " & Int(BitAND(GUICtrlRead($iChkB_ShowEdges), $GUI_CHECKED) = $GUI_CHECKED) & @CRLF & _
;~           "Alpha Value: " & Number(GUICtrlRead($iInp_Alpha)) & @CRLF & _
;~           "Wireframe Checked: " & Int(BitAND(GUICtrlRead($iChkB_Wireframe), $GUI_CHECKED) = $GUI_CHECKED) & @CRLF & _
;~           "Posterize level: " & Number(GUICtrlRead($iInp_PosterizeLvl)) & @CRLF & _
;~           "GIF Mode Checked: " & Int(BitAND(GUICtrlRead($iChkB_GIFMode), $GUI_CHECKED) = $GUI_CHECKED) & @CRLF)
;~ ConsoleWrite("-----------------------------------------------------------------------" & @CRLF)

    Local $fTimer = TimerInit()
    $hGDI_LowPoly = _GDIPlus_BitmapApplyFilter_Delaunay3($hImage, Number(GUICtrlRead($iInp_Blur)), _
            Execute("$" & GUICtrlRead($iCombo_EdgeDetection)), _
            Number(GUICtrlRead($iInp_Threshold), $NUMBER_DOUBLE), _
            Number(GUICtrlRead($iInp_Colors)), _
            Number(GUICtrlRead($iInp_MinSpace)), _
            Number(GUICtrlRead($iInp_MaxSpace)), _
            Number(GUICtrlRead($iInp_BorderSpaceX)), _
            Number(GUICtrlRead($iInp_BorderSpaceY)), _
            Int(BitAND(GUICtrlRead($iChkB_ShowEdges), $GUI_CHECKED) = $GUI_CHECKED), _
            Number(GUICtrlRead($iInp_Alpha)), _
            Int(BitAND(GUICtrlRead($iChkB_Wireframe), $GUI_CHECKED) = $GUI_CHECKED), _
            Number(GUICtrlRead($iInp_PosterizeLvl)), _
            0, _
            True)
    If $hGDI_LowPoly = 0 Then
        GUIDelete($hGUI_Display)
        $hGUI_Display = 0
        Return SetError(1, 0, 0)
    EndIf
    _GUICtrlStatusBar_SetText($hStatusBar, "Generated in: " & Round(TimerDiff($fTimer), 2) & " ms", 0, $SBT_POPOUT)
    Local $hHBmp = GUICtrlSendMsg($iPic_LowPoly, $STM_SETIMAGE, $IMAGE_BITMAP, $hGDI_LowPoly)
    If $hHBmp Then _WinAPI_DeleteObject($hHBmp)
    _WinAPI_InvalidateRect($hGUI_Display)
    _WinAPI_RedrawWindow($hGUI_Display)
EndFunc   ;==>EncodeAndDisplay

Func _WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    Local $iNotifyCode = BitShift($wParam, 16)
    Local $iCtrlID = BitAND($wParam, 0x0000FFFF)
    Local $var
    If $iNotifyCode = $EN_KILLFOCUS Then
        Switch $iCtrlID
            Case $iInp_Blur
                $val = GUICtrlRead($iInp_Blur)
                If $val = "" Then $val = 4
                $val = Number($val)
                If $val < 1 Then $val = 1
                If $val > 127 Then $val = 127
                GUICtrlSetData($iInp_Blur, $val)

            Case $iInp_Threshold
                $val = GUICtrlRead($iInp_Threshold)
                If $val = "" Then $val = 0.35
                $val = Number($val)
                If $val < 0 Then $val = 0
                If $val > 10 Then $val = 10
                GUICtrlSetData($iInp_Threshold, StringFormat("%.2f", $val))

            Case $iInp_Colors
                $val = GUICtrlRead($iInp_Colors)
                If $val = "" Then $val = 32
                $val = Number($val)
                If $val < 2 Then $val = 2
                If $val > 255 Then $val = 255
                GUICtrlSetData($iInp_Colors, $val)

            Case $iInp_MinSpace
                $val = GUICtrlRead($iInp_MinSpace)
                If $val = "" Then $val = 3
                $val = Number($val)
                If $val < 1 Then $val = 1
                GUICtrlSetData($iInp_MinSpace, $val)

            Case $iInp_MaxSpace
                $val = GUICtrlRead($iInp_MaxSpace)
                If $val = "" Then $val = 8
                $val = Number($val)
                If $val < 1 Then $val = 1
                GUICtrlSetData($iInp_MaxSpace, $val)

            Case $iInp_BorderSpaceX, $iInp_BorderSpaceY
                $val = GUICtrlRead($iCtrlID)
                If $val = "" Then $val = 2
                $val = Number($val)
                If $val < 1 Then $val = 1
                If $val > 255 Then $val = 255
                GUICtrlSetData($iCtrlID, $val)

            Case $iInp_Alpha
                $val = GUICtrlRead($iInp_Alpha)
                If $val = "" Then $val = 32
                $val = Number($val)
                If $val < 0 Then $val = 0
                If $val > 255 Then $val = 255
                GUICtrlSetData($iInp_Alpha, $val)

            Case $iInp_PosterizeLvl
                $val = GUICtrlRead($iInp_PosterizeLvl)
                If $val = "" Then $val = 8
                $val = Number($val)
                If $val < 1 Then $val = 1
                If $val > 255 Then $val = 255
                GUICtrlSetData($iInp_PosterizeLvl, $val)

        EndSwitch
    EndIf

    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_COMMAND

Func _GDIPlus_BitmapCreateVerticalText($sString, $fFontSize = 10, $sFont = "Arial", $iColor_Text = 0xFF000000, $iFlip = 3)
    $iFlip = $iFlip <> 3 Or $iFlip <> 1 ? 3 : $iFlip
    _GDIPlus_Startup()
    Local Const $hDC = _WinAPI_GetWindowDC(0)
    Local Const $hGraphic = _GDIPlus_GraphicsCreateFromHDC($hDC)
    Local Const $hBrush = _GDIPlus_BrushCreateSolid($iColor_Text)
    Local Const $hFormat = _GDIPlus_StringFormatCreate()
    Local Const $hFamily = _GDIPlus_FontFamilyCreate($sFont)
    Local Const $hFont = _GDIPlus_FontCreate($hFamily, $fFontSize)
    Local $tLayout = _GDIPlus_RectFCreate()
    Local Const $aInfo = _GDIPlus_GraphicsMeasureString($hGraphic, $sString, $hFont, $tLayout, $hFormat)
    Local $iError = 1
    If Not @error Then
        Local Const $iW = Ceiling($aInfo[0].Width), $iH = Ceiling($aInfo[0].Height)
        Local Const $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH), $hCanvas = _GDIPlus_ImageGetGraphicsContext($hBitmap)
        _GDIPlus_GraphicsSetSmoothingMode($hCanvas, $GDIP_SMOOTHINGMODE_HIGHQUALITY)
        _GDIPlus_GraphicsSetTextRenderingHint($hCanvas, $GDIP_TEXTRENDERINGHINTANTIALIASGRIDFIT)
        $tLayout.X = 0
        $tLayout.Y = 0
        $tLayout.Width = $iW
        $tLayout.Height = $iH
        _GDIPlus_GraphicsDrawStringEx($hCanvas, $sString, $hFont, $tLayout, $hFormat, $hBrush)
        _GDIPlus_ImageRotateFlip($hBitmap, $iFlip)
        Local Const $hBitmap_GDI = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)
        _GDIPlus_GraphicsDispose($hCanvas)
        _GDIPlus_BitmapDispose($hBitmap)
        $iError = 0
    EndIf
    _GDIPlus_FontDispose($hFont)
    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_StringFormatDispose($hFormat)
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_GraphicsDispose($hGraphic)
    _WinAPI_ReleaseDC(0, $hDC)
    _GDIPlus_Shutdown()
    If $iError Then Return SetError(1, 0, 0)
    Local $aResult[3] = [$hBitmap_GDI, $iH, $iW]
    Return $aResult
EndFunc   ;==>_GDIPlus_BitmapCreateVerticalText

 

Examples:

Example1.jpg Example2.jpg Example3.jpg Example4.jpg Example5.jpg Example6.jpg Example7.jpg Example8.jpg

 

The required DLLs (_GDIPlus_BitmapApplyFilter.dll / _GDIPlus_BitmapApplyFilter_x64.dll) and  _GDIPlus_BitmapApplyFilter.au3 can be found on my OneDrive: _GDIPlus_BitmapApplyFilter

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

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
×
×
  • Create New...