Fun with GDIPlus (GDI+)

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Fun with GDIPlus (GDI+)

23 Jan 2015, 04:39

Fun with GDIPlus (GDI+)

This is a topic for GDIPlus-Experiments

Feel free to add more (but don't forget to post source + screenshots)

Usefull GDI+ References:
GDI+ Functions
GDI+ Constants
GDI+ Enumerations
GDI+ Structures
GDI+ Flat API

About GDI+
Using GDI+
Security Considerations: GDI+
Last edited by jNizM on 23 Jan 2015, 09:25, edited 2 times in total.
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
Soft
Posts: 174
Joined: 07 Jan 2015, 13:18
Location: Seoul
Contact:

Re: Fun with GDIPlus

23 Jan 2015, 06:37

interesting!!
AutoHotkey & AutoHotkey_H v1.1.22.07
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Fun with GDIPlus

23 Jan 2015, 08:54

Wave (by Jerome Herr)

Code: Select all

#NoEnv
#SingleInstance Force
SetBatchLines -1

; ===============================================================================================================================

global pi     := 3.14159265
global two_pi := pi * 2
global num    := 25
global step   := 20
global maxrad := num * step - 15
global gui_w  := maxrad
global gui_h  := maxrad
global theta  := 0
global hue    := 0

; ===============================================================================================================================

hSHLWAPI := DllCall("LoadLibrary", "Str", "shlwapi.dll", "Ptr")
hGDIPLUS := DllCall("LoadLibrary", "Str", "GdiPlus.dll", "Ptr")
VarSetCapacity(SI, 24, 0), Numput(1, SI, 0, "Int")
DllCall("GdiPlus.dll\GdiplusStartup", "UPtr*", pToken, "Ptr", &SI, "Ptr", 0)

; ===============================================================================================================================

Gui, +LastFound +hwndhGDIPFun
Gui, Show, w%gui_w% h%gui_h%

DllCall("GdiPlus.dll\GdipCreateFromHWND", "Ptr", hGDIPFun, "Ptr*", pGraphics)
DllCall("GdiPlus.dll\GdipCreateBitmapFromGraphics", "Int", gui_w, "Int", gui_h, "Ptr", pGraphics, "Ptr*", pBitmap)
DllCall("Gdiplus.dll\GdipGetImageGraphicsContext", "Ptr", pBitmap, "Ptr*", pGraphicsCtxt)
DllCall("Gdiplus.dll\GdipSetSmoothingMode", "Ptr", pGraphicsCtxt, "Int", 2)
DllCall("Gdiplus.dll\GdipCreatePen1", "UInt", 0xFFFFFFFF, "Float", 3, "Int", 2, "Ptr*", pPen)

loop
{
    DllCall("GdiPlus.dll\GdipGraphicsClear", "Ptr", pGraphicsCtxt, "UInt", 0x7F000000)
    loop % num
    {
        i := A_Index - 1, sz := i * step, offset := maxrad / 2 - sz / 2
        , arcend := (pi + (two_pi - pi) * ((sin(theta + (two_pi / num * i)) - -1) / 2) - pi) * 57.2957795130823
        , DllCall("GdiPlus.dll\GdipSetPenColor", "Ptr", pPen, "UInt", "0xFF" ColorHLSToRGB(hue + i, 120, 240))
        , DllCall("GdiPlus.dll\GdipDrawArc", "Ptr", pGraphicsCtxt, "Ptr", pPen, "Float", offset, "Float", offset, "Float", sz, "Float", sz, "Float",   0, "Float", arcend)
        , DllCall("GdiPlus.dll\GdipDrawArc", "Ptr", pGraphicsCtxt, "Ptr", pPen, "Float", offset, "Float", offset, "Float", sz, "Float", sz, "Float", 180, "Float", arcend)
    }
    theta += 0.0523, theta := (theta > two_pi) ? mod(theta, two_pi) : theta, hue += 0.5, hue := (hue > 239) ? mod(hue, 239) : hue
    , DllCall("Gdiplus.dll\GdipDrawImage", "Ptr", pGraphics, "Ptr", pBitmap, "Float", 0, "Float", 0)
    ;, DllCall("Sleep", "UInt", 1)
}
return

; ===============================================================================================================================

ColorHLSToRGB(hue, lum, sat)
{
    clr := DllCall("shlwapi.dll\ColorHLSToRGB", "UShort", hue, "UShort", lum, "UShort", sat)
    return Format("{:06X}", ((clr & 0xff00) | ((clr & 0xff) << 16) | ((clr & 0xff0000) >> 16)))
}

; ===============================================================================================================================

GuiClose:
GuiEscape:
    DllCall("GdiPlus.dll\GdipDeletePen", "Ptr", pPen)
    DllCall("GdiPlus.dll\GdipDeleteGraphics", "Ptr", pGraphicsCtxt)
    DllCall("Gdiplus.dll\GdipDisposeImage", "Ptr", pBitmap)
    DllCall("GdiPlus.dll\GdipDeleteGraphics", "Ptr", pGraphics)
    DllCall("GdiPlus.dll\GdiplusShutdown", "Ptr", pToken)
    DllCall("FreeLibrary", "Ptr", hGDIPLUS)
    DllCall("FreeLibrary", "Ptr", hSHLWAPI)
    ExitApp
return
Image
Last edited by jNizM on 29 Jan 2015, 01:50, edited 1 time in total.
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Fun with GDIPlus

23 Jan 2015, 09:38

Exuberant Wave (by Jerome Herr)

Code: Select all

#NoEnv
#SingleInstance Force
SetBatchLines -1

; ===============================================================================================================================

global pi     := 3.14159265
global two_pi := pi * 2
global num    := 25
global step   := 20
global maxrad := num * step - 15
global gui_w  := maxrad
global gui_h  := maxrad
global theta  := 0
global hue    := 0

; ===============================================================================================================================

hSHLWAPI := DllCall("LoadLibrary", "Str", "shlwapi.dll", "Ptr")
hGDIPLUS := DllCall("LoadLibrary", "Str", "GdiPlus.dll", "Ptr")
VarSetCapacity(SI, 24, 0), Numput(1, SI, 0, "Int")
DllCall("GdiPlus.dll\GdiplusStartup", "UPtr*", pToken, "Ptr", &SI, "Ptr", 0)

; ===============================================================================================================================

Gui, +LastFound +hwndhGDIPFun
Gui, Show, w%gui_w% h%gui_h%

DllCall("GdiPlus.dll\GdipCreateFromHWND", "Ptr", hGDIPFun, "Ptr*", pGraphics)
DllCall("GdiPlus.dll\GdipCreateBitmapFromGraphics", "Int", gui_w, "Int", gui_h, "Ptr", pGraphics, "Ptr*", pBitmap)
DllCall("Gdiplus.dll\GdipGetImageGraphicsContext", "Ptr", pBitmap, "Ptr*", pGraphicsCtxt)
DllCall("Gdiplus.dll\GdipSetSmoothingMode", "Ptr", pGraphicsCtxt, "Int", 2)
DllCall("Gdiplus.dll\GdipCreatePen1", "UInt", 0xFFFFFFFF, "Float", 3, "Int", 2, "Ptr*", pPen)

loop
{
    DllCall("GdiPlus.dll\GdipGraphicsClear", "Ptr", pGraphicsCtxt, "UInt", 0x7F000000)
    loop % num
    {
        i := A_Index - 1, sz := i * step, offset := maxrad / 2 - sz / 2
        , arcend := (pi + ((two_pi + pi / 2)- pi) * ((sin(theta + (two_pi / num * i) / 2) - -1) / 2) - pi) * 57.2957795130823
        , DllCall("GdiPlus.dll\GdipSetPenColor", "Ptr", pPen, "UInt", "0xFF" ColorHLSToRGB(hue + i, 120, 240))
        , DllCall("GdiPlus.dll\GdipDrawArc", "Ptr", pGraphicsCtxt, "Ptr", pPen, "Float", offset, "Float", offset, "Float", sz, "Float", sz, "Float", 180, "Float", arcend)
    }
    theta += 0.0523, theta := (theta > two_pi) ? mod(theta, two_pi) : theta, hue += 0.5, hue := (hue > 239) ? mod(hue, 239) : hue
    , DllCall("Gdiplus.dll\GdipDrawImage", "Ptr", pGraphics, "Ptr", pBitmap, "Float", 0, "Float", 0)
    ;, DllCall("Sleep", "UInt", 1)
}
return

; ===============================================================================================================================

ColorHLSToRGB(hue, lum, sat)
{
    clr := DllCall("shlwapi.dll\ColorHLSToRGB", "UShort", hue, "UShort", lum, "UShort", sat)
    return Format("{:06X}", ((clr & 0xff00) | ((clr & 0xff) << 16) | ((clr & 0xff0000) >> 16)))
}

; ===============================================================================================================================

GuiClose:
GuiEscape:
    DllCall("GdiPlus.dll\GdipDeletePen", "Ptr", pPen)
    DllCall("GdiPlus.dll\GdipDeleteGraphics", "Ptr", pGraphicsCtxt)
    DllCall("Gdiplus.dll\GdipDisposeImage", "Ptr", pBitmap)
    DllCall("GdiPlus.dll\GdipDeleteGraphics", "Ptr", pGraphics)
    DllCall("GdiPlus.dll\GdiplusShutdown", "Ptr", pToken)
    DllCall("FreeLibrary", "Ptr", hGDIPLUS)
    DllCall("FreeLibrary", "Ptr", hSHLWAPI)
    ExitApp
return
Image
Last edited by jNizM on 29 Jan 2015, 01:51, edited 2 times in total.
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
joedf
Posts: 8940
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: Fun with GDIPlus

23 Jan 2015, 11:36

Very nice!
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
User avatar
Learning one
Posts: 173
Joined: 04 Oct 2013, 13:59
Location: Croatia
Contact:

Re: Fun with GDIPlus

28 Jan 2015, 15:56

joedf wrote:Very nice!
+1 :)
Were you inspired by this? :)
geek
Posts: 1052
Joined: 02 Oct 2013, 22:13
Location: GeekDude
Contact:

Re: Fun with GDIPlus

28 Jan 2015, 16:05

Would my GDI creation fit in here?

Image

Code:
Spoiler
Edit: Also this (actually using GDI+)

Image

Code:
Spoiler
User avatar
joedf
Posts: 8940
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: Fun with GDIPlus

28 Jan 2015, 20:56

@GeekDude nice fractal!
Learning one wrote:
joedf wrote:Very nice!
+1 :)
Were you inspired by this? :)
here we go! http://www.openprocessing.org/sketch/152169
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Fun with GDIPlus

29 Jan 2015, 01:35

@Learning one (and joedf)
yes yes yes :D
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
Nextron
Posts: 1391
Joined: 01 Oct 2013, 08:23
Location: Netherlands OS: Win10 AHK: Unicode x32

Re: Fun with GDIPlus

29 Jan 2015, 08:50

This would be cool as a mouse sonar replacement (the circles radiating from the cursor in case you lose it), but making the window transparent proves difficult. The black background is actually a mix of almost black (010101, 010001, 010100) and the anti aliasing makes it look ugly.
geek
Posts: 1052
Joined: 02 Oct 2013, 22:13
Location: GeekDude
Contact:

Re: GDI+ standard library 1.45 by tic

02 Apr 2015, 21:11

Had some fun with dithering algorithms.

Code: Select all

#SingleInstance, Force
#NoEnv
SetBatchLines, -1
SetMouseDelay, 2
CoordMode, Mouse, Screen

; Start gdi+
If !pToken := Gdip_Startup()
{
    MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
    ExitApp
}
OnExit, ExitSub
Gui, +HwndHwnd
Gui, Show, w640 h480

hDC := GetDC(hWnd)
return

^+x::
MouseGetPos, StartX, StartY
FileSelectFile, FilePath

pBitmap := Gdip_CreateBitmapFromFile(FilePath)
Width := Gdip_GetImageWidth(pBitmap)
Height := Gdip_GetImageHeight(pBitmap)

Gdip_LockBits(pBitmap, x, y, Width, Height, Stride, Scan0, BitmapData)

n := 2
StartX += (445-Width*n)/2
StartY += (330-Height*n)/2
State := 0

Loop, %Height%
{
	y := A_Index - 1
	Loop, %Width%
	{
		x := A_Index - 1
		ARGB := Gdip_GetLockBitPixel(Scan0, x, y, Stride)
		Average := Round(((ARGB>>16&0xFF) + (ARGB>>8&0xFF) + (ARGB&0xFF)) / 3)
		Gdip_SetLockBitPixel(Average, Scan0, x, y, Stride)
	}
}

hMemDC := CreateCompatibleDC(hDC)
pBitmap := CreateCompatibleBitmap(hDC, Width, Height)
oBitmap := SelectObject(hMemDC, pBitmap) ; Original Bitmap is stored to later be restored

Loop, %Height%
{
	y := A_Index - 1
	Loop, %Width%
	{
		x := A_Index - 1
		
		Shade := Gdip_GetLockBitPixel(Scan0, x, y, Stride)
		NewShade := Shade > 0x7F ? 0xFF : 0
		
		Error := Shade - NewShade
		
		ShiftLockBitPixel(Error * 7/16, Scan0, x+1, y,   Stride, Width, Height)
		ShiftLockBitPixel(Error * 3/16, Scan0, x-1, y+1, Stride, Width, Height)
		ShiftLockBitPixel(Error * 5/16, Scan0, x,   y+1, Stride, Width, Height)
		ShiftLockBitPixel(Error * 1/16, Scan0, x+1, y+1, Stride, Width, Height)
		
		DllCall("SetPixel", "UPtr", hMemDC, "Int", x, "Int", y, "UInt", NewShade<<16|NewShade<<8|NewShade)
	}
	BitBlt(hDC, 0, 0, Width, Height, hMemDC, 0, 0)
}

SelectObject(hMemDC, oBitmap)
DeleteObject(hBitmap)
DeleteDC(hMemDC)

Gdip_UnlockBits(pBitmap, BitmapData)
Gdip_DisposeImage(pBitmap)
return

ExitSub:
Gdip_Shutdown(pToken)
ExitApp
Return

ShiftLockBitPixel(Offset, Scan0, x, y, Stride, w, h)
{
	if (x < 0 || x >= w || y >= h || y < 0)
		return
	Pixel := Gdip_GetLockBitPixel(Scan0, x, y, Stride)
	Gdip_SetLockBitPixel(Clamp(Pixel+Offset, 0, 0xFF), Scan0, x, y, Stride)
}

AverageARGB(ARGB)
{
	return 
}

Clamp(Var, Min, Max)
{
	return Var < Min ? Min : Var > Max ? Max : Var
}
Spoiler
vasili111
Posts: 747
Joined: 21 Jan 2014, 02:04
Location: Georgia

Re: Fun with GDIPlus

03 Apr 2015, 06:29

Very nice thread with beautiful examples.
DRAKON-AutoHotkey: Visual programming for AutoHotkey.
serg
Posts: 56
Joined: 21 Mar 2015, 05:33

Re: Fun with GDIPlus

04 Apr 2015, 12:35

interesting stuff!
User avatar
tomoe_uehara
Posts: 213
Joined: 05 Oct 2013, 12:37
Contact:

Re: Fun with GDIPlus (GDI+)

15 Sep 2015, 12:46

Draw a Cuboid
Spoiler

Code: Select all

#SingleInstance, Force
#NoEnv
SetBatchLines, -1

C1 := 0xff0000aa, C2 := 0xff00aa00, C3 := 0xffaa0000

; Uncomment if Gdip.ahk is not in your standard library
;#Include, Gdip.ahk

If !pToken := Gdip_Startup()
{
   MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
   ExitApp
}
OnExit, Exit

Width := A_ScreenWidth, WC := Width//2 , Height := A_ScreenHeight, HC := Height//2
    , TopLeftX := (A_ScreenWidth - Width)//2, TopLeftY := (A_ScreenHeight - Height)//2

Gui, 1: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs
Gui, 1: Show, NA

hwnd1 := WinExist(), hbm := CreateDIBSection(Width, Height), hdc := CreateCompatibleDC()
    , obm := SelectObject(hdc, hbm), G := Gdip_GraphicsFromHDC(hdc), Gdip_SetSmoothingMode(G, 4)
    , speed := 1, s := 120, d := 20, h := 120, 2h := h + h

Loop {
    mcx := (mc := Cos(a := Mod(A_Index, 90)* 0.01745329252)) * s
        , mcy := mc * d
        , msx := (ms := Sin(a)) * s
        , msy := ms * d
    
    ; Points
    x1 := WC - mcx,  y1 := HC - msy - h
        , x2  := WC + msx, y2 := HC - mcy - h
        , x3  := WC + mcx, y3 := HC + msy - h
        , x4  := WC - msx, y4 := HC + mcy - h
        , yb1 := y1 + 2h, yb2 := y2 + 2h
        , yb3 := y3 + 2h, yb4 := y4 + 2h
    
    ; Fill Top
    P1 := x1 "," y1 "|" x2 "," y2 "|" x3 "," y3 "|" x4 "," y4
        , DrawFace(P1, C3, G)
    
    ; Fill Vertical Faces
    P1 := x1 "," y1 "|" x4 "," y4 "|" x4 "," yb4 "|" x1 "," yb1
        , P2 := x4 "," y4 "|" x3 "," y3 "|" x3 "," yb3 "|" x4 "," yb4
        , P3 := x2 "," y2 "|" x2 "," yb2 "|" x3 "," yb3 "|" x3 "," y3
        , i :=Mod(A_Index, 360)
    if (i < 90 || (i < 270 && i >= 180))
        DrawFace(x1 < x4 ? P1 : P3, C1, G)
            , DrawFace(P2, C2, G)
    else {
        if (x1 < x4) 
            DrawFace(P1, C2, G)
                , DrawFace(P2, C1, G)
        else 
            DrawFace(P2, C1, G)
                , DrawFace(P3, C2, G)
    }

    UpdateLayeredWindow(hwnd1, hdc, TopLeftX, TopLeftY, Width, Height)
    if (!Mod(A_Index, speed))
        Sleep, 30
    Gdip_GraphicsClear(G)
}

DrawFace(Points, Color, G) {
    pBrush := Gdip_BrushCreateSolid(Color)
        , Gdip_FillPolygon(G, pBrush, Points, 1)
        , Gdip_DeleteBrush(pBrush)
    return
}

p::Pause

Right::
s++
Set_TT("s", s)
return

Left::
s--
Set_TT("s", s)
return

Up::
d++
Set_TT("d", d)
return

Down::
if (d > 0)
    d--
Set_TT("d", d)
return

PGUP::
h++
2h := h + h
Set_TT("h", h)
return

PGDN::
if (h > 0)
    h--
2h := h + h
Set_TT("h", h)
return

Home::
If (Speed < 3)
    Speed++
Set_TT("Speed", Speed)
return

End::
If (Speed > 1)
    Speed--
Set_TT("Speed", Speed)
return

Set_TT(s, v) {
    ToolTip, % s ": " v
    SetTimer, TT, -1500
    return
}

TT:
ToolTip
return

Esc::
Exit:
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
    , Gdip_DeleteGraphics(G), Gdip_Shutdown(pToken)
ExitApp
Return
Source: http://rosettacode.org/wiki/Draw_a_cuboid
User avatar
tomoe_uehara
Posts: 213
Joined: 05 Oct 2013, 12:37
Contact:

Re: Fun with GDIPlus (GDI+)

15 Sep 2015, 12:57

2D Fractals
Spoiler

Code: Select all

; L-system: http://en.wikipedia.org/wiki/L-system
#SingleInstance, Off
#NoEnv

Mem() ; include library

	setbatchlines -1
	process, priority, , high

	pToken := Gdip_Startup()
	OnExit, Cleanup

	;*** ;90deg Koch curve
	Koch90Iter  := 5
	Koch90Rules := "F>F+F-F-F+F"
	Koch90Start := "F"
	Koch90Cmds  := "F+-"
	Koch90Cmds2 := "draw 5,angle -90,angle +90"
	;*
	
	;*** ;Koch snowflake
	KochSnowFlakeIter  := 4
	KochSnowFlakeRules := "F>F-F++F-F"
	KochSnowFlakeStart := "F++F++F"
	KochSnowFlakeCmds  := "F+-"
	KochSnowFlakeCmds2 := "draw 5,angle -60,angle +60"
	;*

	;*** ;Sierpinski triangle
	SierpinskiIter  := 10
	SierpinskiRules := "A>B-A-B,B>A+B+A"
	SierpinskiStart := "A"
	SierpinskiCmds  := "AB+-"
	SierpinskiCmds2 := "draw 2,draw 2,angle -60,angle +60"
	;*

	;*** ;Dragon curve
	DragonCurveIter  := 15
	DragonCurveRules := "X>X+YF,Y>FX-Y"
	DragonCurveStart := "FX"
	DragonCurveCmds  := "F+-"
	DragonCurveCmds2 := "draw 3,angle -90,angle +90"
	;*

	;*** ;Penrose tiling
	PenroseP3Iter := 7
	PenroseP3Rules = 
	(LTrim Join,
		6 > 81++91----71[-81----61]++
		7 > +81--91[---61--71]+
		8 > -61++71[+++81++91]-
		9 > --81++++61[+91++++71]--71
		1 >
	)
	PenroseP3Start := "[7]++[7]++[7]++[7]++[7]"
	PenroseP3Cmds  := "1+-[]"
	PenroseP3Cmds2 := "draw 10,angle -36,angle +36,save,restore"
	;*

	;*** ;Fractal plant
	FractalPlantIter  := 7
	FractalPlantRules := "X>F-[[X]+X]+F[+FX]-X,F>FF"
	FractalPlantStart := "&X"
	FractalPlantCmds  := "F+-[]&"
	FractalPlantCmds2 := "draw 3,angle -25,angle +25,save,restore,angle -60"
	;*

	;*** ; triangles
	trianglesIter  := 7
	trianglesRules := "F>F+F-F"
	trianglesStart := "F-F-F"
	trianglesCmds  := "+-F"
	trianglesCmds2 := "angle -120,angle +120,draw 6" 
	;*

	;*** ; squares1
	squares1Iter  := 720
	squares1Rules := "A>A+B,B>2B"
	squares1Start := "A"
	squares1Cmds  := "12345+"
	squares1Cmds2 := "draw 1,draw 2,draw 3,draw 4,draw 5,angle +91"
	;*

	;*** ; squares2
	squares2Iter  := 90
	squares2Rules := "A>A+B,B>2B,2>21"
	squares2Start := "A"
	squares2Cmds  := "12345+"
	squares2Cmds2 := "draw .25,draw .5,draw .75,draw 1,draw 1.25,angle +91"
	;*

	; ----- choose the style from option below -----
	;	name = triangles
	;	name = KochSnowFlake
	;	name = Sierpinski
	;	name = DragonCurve
	;	name = PenroseP3
		name = FractalPlant
	;	name = triangles
	;	name = squares1
	;	name = squares2

	linecount := DispLSystem( %name%Iter, %name%Rules, %name%Start, %name%Cmds, %name%Cmds2, 0 )

	MsgBox % "Done!`nThere are " linecount " lines in this L-System.`nCreated in " errorlevel " seconds.`nThis is an average of " (linecount / errorlevel) " lines per second."
return

Esc::ExitApp

GuiClose:
Cleanup:
	Gdip_Shutdown(pToken)
	ExitApp

DispLSystem( iter, rules, start, names, commands, live = 0 ) {
	DllCall("QueryPerformanceFrequency", "int64*", qpcf), DllCall("QueryPerformanceCounter", "int64*", qpcs)
	
	turtle := LSystem( iter, rules, start )
	cnt := LSys2Lines( turtle, names, commands, lines, w, h )
	
	MakeLayeredWindow( hwnd, hdc, hbm, obm, gfx, w, h )
;	UpdateLayeredWindow(hwnd, hdc)
	DrawLinesToLayeredWindow( lines, cnt, hwnd, hdc, gfx, live )
	UpdateLayeredWindow(hwnd, hdc)
	CleanupLayeredWindow( hwnd, hdc, hbm, obm, gfx )
	
	DllCall("QueryPerformanceCounter", "int64*", qpce)
	return cnt, ErrorLevel := (qpce - qpcs) / qpcf
}

LSystem( cn, Vr, st ) {
;
; cn: iterations
; Vr: list of variables and their rules
;    (V>Result)[,...]
;    Where
;      V: Any single-character variable (must be valid as an AHK variable)
;          a-z 1-9 _ (case insensitive)
;      Result: The rule that this variable results in when replaced
;          [All characters except for comma] (must not start with a quote char: ")
;          OR
;          "[All characters]" (starts and ends with quote char. any literal quote chars inside must be duplicated)
; st : start string
;
; Any non-variable character is treated as a constant
; 
	it := 1
	while it := RegExMatch(Vr, "\s*(\w)\s*>\s*(?:(?!"")([^,]*)|""((?:[^""]|"""")*)"")\s*(?:,|$)", __, it + StrLen(__))
		%__1% := __2 RegExReplace(__3, """""", """"), Vl .= __1 ;parse Variables+Rules
	loop % cn
	{
		tp := "" st, st := ""
		loop, parse, tp
			st .= InStr(Vl, A_LoopField) ? %A_LoopField% : A_LoopField
	}
	return st
}
LSys2Lines( ls, chars, commands, byref lines, byref w, byref h ) { ;based on l-system
	l := 0
	, st%l%x := 0
	, st%l%y := 0
	, st%l%a := 0
	, i := 0
	lines_cap := VarSetCapacity(lines, strlen(ls) * 8)
	maxx := maxy := minx := miny := 0
	loop, parse, commands, `,, %A_Space%%A_Tab%
		cmd%A_Index% := A_LoopField
	loop, parse, ls
	{
		if !p := InStr(chars, A_LoopField)
			continue
		else if inStr(cmd%p%, "save")
			ol := l++
			, st%l%x := st%ol%x
			, st%l%y := st%ol%y
			, st%l%a := st%ol%a
		else if inStr(cmd%p%, "restore")
			l--
		else if inStr(cmd%p%, "angle")
			st%l%a += substr(cmd%p%, 6)
		else if inStr(cmd%p%, "draw")
		{
			d  := SubStr(cmd%p%, 5) + 0     ;distance (in pixels)
			AddLine( lines, i
				, Round(st%l%x)
				, Round(st%l%y)                           
				, Round(st%l%x += cos(st%l%a/57.2957795) * d)
				, Round(st%l%y += sin(st%l%a/57.2957795) * d) )
			, maxx := maxx > st%l%x ? maxx : st%l%x
			, maxy := maxy > st%l%y ? maxy : st%l%y
			, minx := minx < st%l%x ? minx : st%l%x
			, miny := miny < st%l%y ? miny : st%l%y
		}
	}
	xoff := round(abs(minx)) + 5
	yoff := round(abs(miny)) + 5
	w := round(maxx) + xoff + 5
	h := round(maxy) + yoff + 5
	
	OffsetPoints(lines, i, xoff, yoff)
	return i//4
}

AddLine( ByRef lines, ByRef i, x1, y1, x2, y2 ) {
	static lines_sz = 0
	if (i = 0 || lines_sz = 0)
		lines_sz := VarSetCapacity(lines)
	if (lines_sz < i * 4 + 16)
		MemPreAlloc(lines, lines_sz, i + 16), lines_sz := VarSetCapacity(lines) 
	  NumPut(x1, lines, 4 * i++, "int")
	, NumPut(y1, lines, 4 * i++, "int")
	, NumPut(x2, lines, 4 * i++, "int")
	, NumPut(y2, lines, 4 * i++, "int")
}

OffsetPoints( ByRef lines, cnt, xoff, yoff ) {
	i := 0
	while i < cnt
		NumPut(NumGet(lines, i * 4, "int") + (i & 1 ? yoff : xoff), lines, 4 * i++, "int")
}

DrawLinesToLayeredWindow( ByRef lines, cnt, hwnd, hdc, gfx, live = 0, color = 0xFF009900, lnw = 1 ) {
	cnt *= 4
	i := 0
	pPen := Gdip_CreatePen(color, 1)
	while i < cnt
	{
		Gdip_DrawLine(gfx, pPen
			, NumGet(lines, 4 * i++, "int")
			, NumGet(lines, 4 * i++, "int")
			, NumGet(lines, 4 * i++, "int")
			, NumGet(lines, 4 * i++, "int"))
	;	if live && !Mod(A_Index, live)
	;		UpdateLayeredWindow(hwnd, hdc)
	}
	Gdip_DeletePen(pPen)
}



; Display functions
MakeLayeredWindow( ByRef hwnd, ByRef hdc, ByRef hbm, ByRef obm, ByRef gfx, w, h, bg = 0xFFCCccCC, guiNum = 5 ) {
	w += 1, h += 1
	Gui, %guiNum%:+LastFound +AlwaysOnTop +Owner +E0x80000 -Caption
	Gui, %guiNum%:Show, w%w% h%h%
	OnMessage(0x201, "WM_LBUTTONDOWN")

	;gdi
	hwnd := WinExist()
	hdc  := CreateCompatibleDC()
	hbm  := CreateDIBSection(w, h) ;needs to be the same size as gui
	obm  := SelectObject(hdc, hbm)
	gfx  := Gdip_GraphicsFromHDC(hdc)

	;background
	pBr := Gdip_BrushCreateSolid(bg)
	Gdip_FillRoundedRectangle(gfx, pBr, 0, 0, w, h, 3)
	Gdip_DeleteBrush(pBr)
}
CleanupLayeredWindow( ByRef hwnd, ByRef hdc, ByRef hbm, ByRef obm, ByRef gfx ) {
	SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
	, Gdip_DeleteGraphics(gfx)
}
WM_LBUTTONDOWN() { ;for dragging the gui
		static mx, my, wx, wy, hwnd
		hwnd := WinExist()
		CoordMode, Mouse, Screen
		mousegetpos, mx, my
		WinGetPos, wx, wy
		settimer, GuiDrag, 10
	return

	GuiDrag:
		CoordMode, Mouse, Screen
		setwindelay, -1
		if !GetKeyState( "LButton", "P" )
			settimer, %A_ThisLabel%, Off
		else
		{
			MouseGetPos, nmx, nmy
			WinMove, ahk_id %hwnd%, , wx + (nmx - mx), wy + (nmy - my)
		}
	return
}


; CX( a, len ) { ;change in x for an angle and length
; 	return cos(a/57.2957795) * len
; }
; CY( a, len ) { ;change in y for an angle and length
; 	return sin(a/57.2957795) * len
; }

; memory functions
; by infogulch

;*** ; testing
;	text := "the quick brown fox jumps over the lazy dog"
;	a := " aaa "
;	VarSetCapacity(text2, StrLen(text), 0)
;	
;	MemMove(&text2, &text, StrLen(text)+1)
;	VarSetCapacity(text2, -1)
;	MsgBox % "_" text "_`n_" text2 "_"
;	
;	While 0 != p := MemChr(&text2, Asc( " " ), len:=StrLen(text2))
;		MemDel(text2, len, p-&text2, 1)
;	VarSetCapacity(text2, -1)
;	MsgBox % "_" text2 "_"
;	
;	MemAdd(text, StrLen(text), a, StrLen(a))
;	VarSetCapacity(text, -1)
;	MsgBox % "_" text "_"
;
;	MemIns(text, StrLen(text), a, StrLen(a), 4)
;	VarSetCapacity(text, -1)
;	MsgBox % "_" text "_"
;*   ;

Mem() {
}

MemDel( ByRef var, varlen, off, b = 1 ) {
	; may need to call VarSetCapacity(var, -1) afterwards for display
	MemMove( &var+off, &var+off+b, varlen-off)
}
MemIns( ByRef var, varlen, ByRef add, addlen, off ) {
	; may need to call VarSetCapacity(var, -1) afterwards for display
	len := varlen + addlen
	VarSetCapacity(tp, len, 0)       ; create tp
	MemMove( &tp, &var, off )        ; copy beginning of var to tp
	MemMove( &tp+off, &add, addlen ) ; copy add into tp at off
	MemMove( &tp+off+addlen, &var+off, varlen-off) ; copy remaining var to tp
	VarSetCapacity(var, len, 0)      ; resize var
	MemMove( &var, &tp, len )        ; copy finished tp back to var
}
MemAdd( ByRef var, varlen, ByRef add, addlen ) {
	; may need to call VarSetCapacity(var, -1) afterwards for display
	len := varlen + addlen
	VarSetCapacity(tp, len, 0)          ; setup tp var
	MemMove(&tp, &var, varlen)          ; copy var into tp
	MemMove(&tp + varlen, &add, addlen) ; copy add to end of tp
	VarSetCapacity(var, len, 0)         ; resize var
	MemMove(&var, &tp, len)             ; copy finished tp back to var
}

MemPreAlloc( ByRef var, len, add, fillbyte = 0 ) {
	VarSetCapacity(t, len+add, fillbyte)
	MemMove(&t, &var, len)
	VarSetCapacity(var, len+add, 0)
	MemMove(&var, &t, len+add)
}

MemChr( ptr, chr, len ) { ;finds chr from ptr through len (char as ascii value)
	; returns pointer
	return DllCall( "msvcrt\memchr", "UInt", ptr+0, "Int", chr & 0xFF, "Int", len, "Cdecl UInt")
}
MemMove( dest, src, len ) {
	; may need to call VarSetCapacity(var, -1) afterwards for display
	DllCall( "msvcrt\memmove", "UInt", dest+0, "UInt", src+0, "Int", len, "Cdecl int" )
}
Author: InfoGulch aka InfoG
geek
Posts: 1052
Joined: 02 Oct 2013, 22:13
Location: GeekDude
Contact:

Re: Fun with GDIPlus (GDI+)

15 Sep 2015, 13:14

@tomoe_uehara: Reminds me of some stuff I did a while ago. I'm not sure where the code went.
Spoiler
vasili111
Posts: 747
Joined: 21 Jan 2014, 02:04
Location: Georgia

Re: Fun with GDIPlus (GDI+)

18 Jan 2016, 04:14

Next step will be 3d shooter game with AutoHotkey :)
DRAKON-AutoHotkey: Visual programming for AutoHotkey.
User avatar
joedf
Posts: 8940
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: Fun with GDIPlus (GDI+)

20 Jan 2016, 12:48

Haha yes, that's Uberi for ya 8-)
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
vasili111
Posts: 747
Joined: 21 Jan 2014, 02:04
Location: Georgia

Re: Fun with GDIPlus (GDI+)

20 Jan 2016, 14:32

Wow! thats nice :D
DRAKON-AutoHotkey: Visual programming for AutoHotkey.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 122 guests