GDIP Art ?

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
flyingDman
Posts: 2791
Joined: 29 Sep 2013, 19:01

GDIP Art ?

21 Jun 2019, 20:33

I have been playing with this for a few years. I use GDIP (make sure it's in one of your LIBs) to draw forms that resemble the spirograph designs or at times kaleidoscope images. I have looked around if this had been done yet but could not find anything quite similar. Have a look. This one regenerates based on some random input:

Code: Select all

#SingleInstance, Force
#NoEnv
SetBatchLines, -1

gui, white:	Color, eeeeee
gui, white:	show,w%a_screenwidth% h%a_screenheight%,white
WinSet, Transparent, 210, white

reload:
gui, 1: destroy
gui, 1:	+AlwaysOnTop +E0x20 +E0x80000 +ToolWindow +Hwndhwnd1 		;-DPIScale 
gui, 1: Show,, Spirograph


pToken 	:= Gdip_Startup()
hbm 	:= CreateDIBSection(A_ScreenWidth, A_ScreenHeight)
hdc 	:= CreateCompatibleDC()
obm 	:= SelectObject(hdc, hbm)
g 		:= Gdip_GraphicsFromHDC(hdc)


pPen 	:= Gdip_CreatePen("0xFF000000", 1)							;set the color and the thickness of the line (thin is 1)  0xFFb90b0b

pPen1 	:= Gdip_BrushCreateSolid(0xaa323baa)
pPen2 	:= Gdip_BrushCreateSolid(0xaa126d11)
pPen3 	:= Gdip_BrushCreateSolid(0xaab90b0b)
pPen4 	:= Gdip_BrushCreateSolid(0xaaffe13f)
pPen5 	:= Gdip_BrushCreateSolid(0xaaa30ba5)
pPen6 	:= Gdip_BrushCreateSolid(0xaaC65e1e)
pPen7 	:= Gdip_BrushCreateSolid(0xaa5fe30F)
pPen8 	:= Gdip_BrushCreateSolid(0xaa3dc6d7)
pPen9 	:= Gdip_BrushCreateSolid(0xaaFF0000)

Gdip_SetSmoothingMode(g, 5)

Random, rdm1, 1, 25
Random, rdm2, 1, 25
Random, rds3, 1, 50
	
loop,1000
	{	
	if a_index < 100
		continue
	if mod(a_index,10)
		continue
	rds1 :=  rdm1 / 50 * a_index - 50
	rds2 := - rdm2 / 50 * a_index + 50
	tpcrnrx1 := (cntrx := a_screenwidth / 2) - rds1
	tpcrnry1 := (cntry := a_screenheight / 2) - rds1
	tpcrnrx2 :=  cntrx  - rds2
	tpcrnry2 :=  cntry  - rds2
	w = 233
	dif := rds2 - rds1 


	Gdip_FillEllipse(G, pPen1, tpcrnrx1					, tpcrnry1 - ( dif)				, 2*rds1, 2*rds1)     ; 12 		o'clock
	Gdip_FillEllipse(G, pPen2, tpcrnrx1 + (w + dif /2)	, tpcrnry1 - (w + dif /2)		, 2*rds1, 2*rds1)     ; 1.5 	o'clock
	Gdip_FillEllipse(G, pPen3, tpcrnrx1 +  dif			, tpcrnry1 						, 2*rds1, 2*rds1)     ; 3 		o'clock
	Gdip_FillEllipse(G, pPen4, tpcrnrx1 + (w + dif /2)	, tpcrnry1 + (w + dif /2)		, 2*rds1, 2*rds1)     ; 4.5 	o'clock
	Gdip_FillEllipse(G, pPen5, tpcrnrx1					, tpcrnry1 +   dif				, 2*rds1, 2*rds1)     ; 6 		o'clock
	Gdip_FillEllipse(G, pPen6, tpcrnrx1 - (w + dif /2)	, tpcrnry1 + (w + dif /2)		, 2*rds1, 2*rds1)     ; 7.5 	o'clock
	Gdip_FillEllipse(G, pPen7, tpcrnrx1 - (dif)			, tpcrnry1 						, 2*rds1, 2*rds1)     ; 9 		o'clock
	Gdip_FillEllipse(G, pPen8, tpcrnrx1 - (w + dif /2)	, tpcrnry1 - (w + dif /2)		, 2*rds1, 2*rds1)     ; 10.5 	o'clock

	Gdip_FillEllipse(G, pPen9, cntrx - rds3				, cntry	-rds3					, 2*rds3, 2*rds3)

	Gdip_DrawEllipse(G, pPen, tpcrnrx2 					, tpcrnry2						, 2*rds2, 2*rds2)
	Gdip_DrawEllipse(G, pPen, tpcrnrx1					, tpcrnry1 +   dif				, 2*rds1, 2*rds1)
	Gdip_DrawEllipse(G, pPen, tpcrnrx1 +  dif			, tpcrnry1 						, 2*rds1, 2*rds1)
	Gdip_DrawEllipse(G, pPen, tpcrnrx1					, tpcrnry1 - ( dif)				, 2*rds1, 2*rds1)
	Gdip_DrawEllipse(G, pPen, tpcrnrx1 - (dif)			, tpcrnry1 						, 2*rds1, 2*rds1)
	Gdip_DrawEllipse(G, pPen, tpcrnrx1 + (w + dif /2)	, tpcrnry1 + (w + dif /2)		, 2*rds1, 2*rds1)
	Gdip_DrawEllipse(G, pPen, tpcrnrx1 + (w + dif /2)	, tpcrnry1 - (w + dif /2)		, 2*rds1, 2*rds1)
	Gdip_DrawEllipse(G, pPen, tpcrnrx1 - (w + dif /2)	, tpcrnry1 + (w + dif /2)		, 2*rds1, 2*rds1)
	Gdip_DrawEllipse(G, pPen, tpcrnrx1 - (w + dif /2)	, tpcrnry1 - (w + dif /2)		, 2*rds1, 2*rds1)

	UpdateLayeredWindow(hwnd1, hdc, 0, 0, A_ScreenWidth, A_ScreenHeight)   	 	; Draw everything
	sleep, % 1000 / a_index 
	}
settimer, reload, -5000
return

esc::
Gdip_DeleteBrush(pBrush)
SelectObject(hdc, obm)
DeleteObject(hbm)
DeleteDC(hdc)
Gdip_Shutdown(pToken)
exitapp

Last edited by flyingDman on 13 Jul 2019, 13:26, edited 1 time in total.
14.3 & 1.3.7
User avatar
Hellbent
Posts: 2103
Joined: 23 Sep 2017, 13:34

Re: GDIP Art ?

21 Jun 2019, 20:53

Very cool. :thumbup:

Not quite the same, but in the same ballpark.

when you run the script.
-----------------------------------------------------
Press numpad2 to gather all the balls
Move your cursor in a small circle (about 3-4 inches in diameter) Then stop moving
Press Numpad1 and watch.

Right click or esc to exit.

Code: Select all


#SingleInstance,Force
SetBatchLines,-1
CoordMode,Mouse,window
OnExit,GuiClose
global Win:={W:A_ScreenWidth,H:A_ScreenHeight},Planet:={}
;~ Win:=Layered_Window_SetUp(4,0,0,Win.W,Win.H,1,"-Caption -DPIScale +Alwaysontop +E0x20 ")
Win:=Layered_Window_SetUp(4,0,0,Win.W,Win.H,1,"-Caption -DPIScale +Alwaysontop ")
UpdateLayeredWindow(Win.hwnd, Win.hdc, 0, 0, Win.W, Win.H)

Gui,1:Add,Text,x0 y0 w%A_ScreenWidth% h%A_ScreenHeight% gMovWin

cc:=1

Loop 200	{
	;~ color:=Random_Colour(Range_R_Min:=0,Range_R_Max:=0,Range_G_Min:=0,Range_G_Max:=255,Range_B_Min:=0,Range_B_Max:=255)
	color:=Random_Colour(Range_R_Min:=0,Range_R_Max:=255,Range_G_Min:=0,Range_G_Max:=255,Range_B_Min:=0,Range_B_Max:=255)
	W:=Random(5,35)
	;~ Planet.Push(new Ball(Random(0,A_ScreenWidth),Random(0,A_ScreenHeight),W,w,color,Random(7,500)*.001,Random(70,1250)*.1,Random(1,50)*.1))
	;~ Planet.Push(new Ball(Random(0,A_ScreenWidth),Random(0,A_ScreenHeight),W,w,color,Random(7,500)*.001,Random(70,1250)*.1,Random(1,50)*.1))
	Planet.Push(new Ball(Random(0,A_ScreenWidth),Random(0,A_ScreenHeight),W,w,color,Random(0.07,5.0),Random(7.0,125.0),Random(0.1,5.0)))
}
;~ Planet.Push(new Ball(Random(0,A_ScreenWidth),Random(0,A_ScreenHeight),W:=50,w,"ff0000",Random(7,500)*.001,Random(70,1250)*.1,Random(1,50)*.1))
;~ Planet.Push(new Ball(Random(0,A_ScreenWidth),Random(0,A_ScreenHeight),W:=30,w,"0000ff",Random(7,500)*.001,Random(70,1250)*.1,Random(1,50)*.1))
clear:=1
Sun_Brush:=New_Brush("ffaa00","aa")
Sun_Pen:=New_Pen("000000",,2)
SetTimer,Game_Loop,10
count:=0
return
GuiClose:
GuiContextMenu:
*ESC::
	Gdip_DeleteBrush(Sun_Brush)
	Gdip_DeletePen(Sun_Pen)
	loop,% Planet.Length(){
		Gdip_DeleteBrush(Planet[A_Index].Brush)
		Gdip_DeletePen(Planet[A_Index].Pen)	
	}
	Layered_Window_ShutDown(Win)
	ExitApp
Numpad1::
	Clear:=!clear
	return
Numpad2::
	center:=1
	return
;~ Numpad3::
	;~ Reload
	;~ return
MovWin:
	PostMessage,0xa1,2
	return
Game_Loop:
	loop 5
		{
			if(clear)
				Gdip_GraphicsClear(Win.g)
			Mousegetpos,x1,y1
			Gdip_FillEllipse(Win.g, Sun_Brush, x1-75,y1-75,150,150)
			Gdip_DrawEllipse(Win.g, Sun_Pen,x1-75,y1-75,150,150)
			Loop,% Planet.Length()	{
				Planet[A_Index].UpDate(x1,y1)
			}
			if(cc=1&&count++>400){
				value:=Random(1,7)
				Loop,% Planet.Length()	{
					if(value=1)
						color:=Random_Colour(Range_R_Min:=100,Range_R_Max:=255,Range_G_Min:=0,Range_G_Max:=255,Range_B_Min:=100,Range_B_Max:=255)
					else if(value=2)
						color:=Random_Colour(Range_R_Min:=0,Range_R_Max:=255,Range_G_Min:=0,Range_G_Max:=0,Range_B_Min:=0,Range_B_Max:=0)
					else if(value=3)
						color:=Random_Colour(Range_R_Min:=0,Range_R_Max:=0,Range_G_Min:=0,Range_G_Max:=255,Range_B_Min:=0,Range_B_Max:=0)
					else if(value=4)
						color:=Random_Colour(Range_R_Min:=0,Range_R_Max:=0,Range_G_Min:=0,Range_G_Max:=0,Range_B_Min:=0,Range_B_Max:=255)
					else if(value=5)
						color:=Random_Colour(Range_R_Min:=100,Range_R_Max:=255,Range_G_Min:=0,Range_G_Max:=0,Range_B_Min:=100,Range_B_Max:=255)
					else if(value=6)
						color:=Random_Colour(Range_R_Min:=100,Range_R_Max:=255,Range_G_Min:=100,Range_G_Max:=255,Range_B_Min:=0,Range_B_Max:=0)
					else if(value=7)
						color:=Random_Colour(Range_R_Min:=0,Range_R_Max:=0,Range_G_Min:=100,Range_G_Max:=255,Range_B_Min:=100,Range_B_Max:=255)
					Planet[A_Index].Color:=color
				}
				Count:=0
				;~ Planet[1].Color:="FF0000"
			}
			UpdateLayeredWindow(Win.hwnd, Win.hdc)
		}
	if(center=1){
		loop,% Planet.Length()
			Planet[A_Index].Pos.X:=x1,Planet[A_Index].Pos.y:=y1,Planet[A_Index].Vel.X:=0,Planet[A_Index].Vel.Y:=0
		center:=0	
	}
	return
	
	
	
Random(Min,Max){
	Random,Out,Min,Max
	return Out
}

Random_Colour(Range_R_Min:=0,Range_R_Max:=255,Range_G_Min:=0,Range_G_Max:=255,Range_B_Min:=0,Range_B_Max:=255){
	 RGBCOLOR := { 1 : ( Random( Range_R_Min , Range_R_Max ) ) , 2 : Random( Range_G_Min , Range_G_Max ) , 3 : Random( Range_B_Min , Range_B_Max ) }
	FOR COLOR IN RGBCOLOR	{
		SETFORMAT , INTEGER , HEX
		RGBCOLOR[ A_INDEX ] += 0
		TEMP := RGBCOLOR[A_INDEX]
		STRINGREPLACE , TEMP , TEMP , 0x 
		RGBCOLOR[A_INDEX] := TEMP
		SETFORMAT , INTEGER , DECIMAL	
		IF( STRLEN( RGBCOLOR[ A_INDEX ] ) < 2 )
			RGBCOLOR[ A_INDEX ] := "0" RGBCOLOR[ A_INDEX ]
		TEMPCOLOR .= RGBCOLOR[ A_INDEX ]
	}
	RETURN TEMPCOLOR
}
Class Ball
	{
		__New(x,y,w,h,Colour,max_acc,Max_Vel,sx,thline:=1)
			{
				This.Pos:=New HB_Vector(x,y) 	
				This.Acc:=New HB_Vector(0,0)	
				This.Vel:=New HB_Vector(sx,0)	
				This.W:=w,This.H:=h
				This.Max_Vel:=Max_Vel
				This.Max_Acc:=Max_Acc
				This.Color:=Colour
				This.Brush:=New_Brush(Colour,"ff")
				This.Pen:=New_Pen("000000",,thline)
			}
		Draw()
			{
				Gdip_DeleteBrush(This.Brush)

				This.Brush:=New_Brush(This.Color,"ff")
				Gdip_FillEllipse(Win.g, This.Brush, This.Pos.X,This.Pos.Y,This.W,This.H)
				Gdip_DrawEllipse(Win.g, This.pen, This.Pos.X,This.Pos.Y,This.W,This.H)
			}
		Check_Speed()
			{
				(This.vel.X>This.max_Vel)?(This.vel.x:=This.max_Vel)
				(This.vel.x<-This.max_Vel)?(This.vel.x:=-This.max_Vel)
				(This.vel.y>This.max_Vel)?(This.vel.y:=This.max_Vel)
				(This.vel.y<-This.max_Vel)?(This.vel.y:=-This.max_Vel)
			}
		Update(x1,y1)
			{
				This.Acc.X:=x1-This.w//2,This.Acc.Y:=y1-This.h//2 
				This.Acc.Sub(This.Pos)  		
				This.Acc.Setmag(This.Max_Acc)  	
				This.vel.add(This.Acc) 			
				This.pos.add(This.vel)  		
				;~ This.Check_Speed()
				This.Draw()
			}
	}

Class HB_Vector	{
	__New(x:=0,y:=0){
		This.X:=x
		This.Y:=y
	}
	Add(Other_HB_Vector){
		This.X+=Other_HB_Vector.X
		This.Y+=Other_HB_Vector.Y
	}
	Sub(Other_HB_Vector){
		This.X-=Other_HB_Vector.X
		This.Y-=Other_HB_Vector.Y
	}
	mag(){
		return Sqrt(This.X*This.X + This.Y*This.Y)
	}
	magsq(){
		return This.Mag()**2
	}	
	setMag(in1){
		m:=This.Mag()
		This.X := This.X * in1/m
		This.Y := This.Y * in1/m
		return This
	}
	mult(in1,in2:="",in3:="",in4:="",in5:=""){
		if(IsObject(in1)&&in2=""){
			This.X*=In1.X 
			This.Y*=In1.Y 
		}else if(!IsObject(In1)&&In2=""){
			This.X*=In1
			This.Y*=In1
		}else if(!IsObject(In1)&&IsObject(In2)){
			This.X*=In1*In2.X
			This.Y*=In1*In2.Y
		}else if(IsObject(In1)&&IsObject(In2)){
			This.X*=In1.X*In2.X
			This.Y*=In1.Y*In2.Y
		}	
	}
	div(in1,in2:="",in3:="",in4:="",in5:=""){
		if(IsObject(in1)&&in2=""){
			This.X/=In1.X 
			This.Y/=In1.Y 
		}else if(!IsObject(In1)&&In2=""){
			This.X/=In1
			This.Y/=In1
		}else if(!IsObject(In1)&&IsObject(In2)){
			This.X/=In1/In2.X
			This.Y/=In1/In2.Y
		}else if(IsObject(In1)&&IsObject(In2)){
			This.X/=In1.X/In2.X
			This.Y/=In1.Y/In2.Y
		}	
	}
	dist(in1){
		return Sqrt(((This.X-In1.X)**2) + ((This.Y-In1.Y)**2))
	}
	dot(in1){
		return (This.X*in1.X)+(This.Y*In1.Y)
	}
	cross(in1){
		return This.X*In1.Y-This.Y*In1.X
	}
	Norm(){
		m:=This.Mag()
		This.X/=m
		This.Y/=m
	}
}
	
; The stuff below this line is just the GDIP LIB
;-----------------------------------------------------------------------------------------------------------------------------------
;-----------------------------------------------------------------------------------------------------------------------------------
;-----------------------------------------------------------------------------------------------------------------------------------
;-----------------------------------------------------------------------------------------------------------------------------------

;Shit that I (Hellbent) added
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

Layered_Window_SetUp(Smoothing,Window_X,Window_Y,Window_W,Window_H,Window_Name:=1,Window_Options:="")
	{
		Layered:={}
		Layered.W:=Window_W
		Layered.H:=Window_H
		Layered.X:=Window_X
		Layered.Y:=Window_Y
		Layered.Name:=Window_Name
		Layered.Options:=Window_Options
		Layered.Token:=Gdip_Startup()
		Create_Layered_GUI(Layered)
		Layered.hwnd:=winExist()
		Layered.hbm := CreateDIBSection(Window_W,Window_H)
		Layered.hdc := CreateCompatibleDC()
		Layered.obm := SelectObject(Layered.hdc,Layered.hbm)
		Layered.G := Gdip_GraphicsFromHDC(Layered.hdc)
		Gdip_SetSmoothingMode(Layered.G,Smoothing)
		return Layered
	}

Create_Layered_GUI(Layered)
	{
		Gui,% Layered.Name ": +E0x80000 +LastFound " Layered.Options 
		Gui,% Layered.Name ":Show",% "x" Layered.X " y" Layered.Y " w" Layered.W " h" Layered.H " NA"
	}
	
Layered_Window_ShutDown(This)
	{
		SelectObject(This.hdc,This.obm)
		DeleteObject(This.hbm)
		DeleteDC(This.hdc)
		gdip_deleteGraphics(This.g)
		Gdip_Shutdown(This.Token)
	}

Gdip_RotateBitmap(pBitmap, Angle, Dispose=1) { ; returns rotated bitmap. By Learning one.
Gdip_GetImageDimensions(pBitmap, Width, Height)
Gdip_GetRotatedDimensions(Width, Height, Angle, RWidth, RHeight)
Gdip_GetRotatedTranslation(Width, Height, Angle, xTranslation, yTranslation)

pBitmap2 := Gdip_CreateBitmap(RWidth, RHeight)
G2 := Gdip_GraphicsFromImage(pBitmap2), Gdip_SetSmoothingMode(G2, 4), Gdip_SetInterpolationMode(G2, 7)
Gdip_TranslateWorldTransform(G2, xTranslation, yTranslation)
Gdip_RotateWorldTransform(G2, Angle)
Gdip_DrawImage(G2, pBitmap, 0, 0, Width, Height)

Gdip_ResetWorldTransform(G2)
Gdip_DeleteGraphics(G2)
if Dispose
Gdip_DisposeImage(pBitmap)
return pBitmap2
}

New_Brush(colour:="000000",Alpha:="FF")
	{
		static Hellbent_Brush:=[]
		new_colour := "0x" Alpha colour 
		Hellbent_Brush[Hellbent_Brush.Length()+1]:=Gdip_BrushCreateSolid(new_colour)
		return Hellbent_Brush[Hellbent_Brush.Length()]
	}
	
	
New_Pen(colour:="000000",Alpha:="FF",Width:= 5)
	{
		static Hellbent_Pen:=[]
		new_colour := "0x" Alpha colour 
		Hellbent_Pen[Hellbent_Pen.Length()+1]:=Gdip_CreatePen(New_Colour,Width)
		return Hellbent_Pen[Hellbent_Pen.Length()]
	}	
	
Fill_Box(pGraphics,pBrush,x,y,w,h)	
	{
		;~ Gdip_FillRectangle(G, Brush, x, y, w, h)
		Ptr := A_PtrSize ? "UPtr" : "UInt"
	
		return DllCall("gdiplus\GdipFillRectangle"
					, Ptr, pGraphics
					, Ptr, pBrush
					, "float", x
					, "float", y
					, "float", w
					, "float", h)
	}
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&



















; Gdip standard library v1.45 by tic (Tariq Porter) 07/09/11
; Modifed by Rseding91 using fincs 64 bit compatible Gdip library 5/1/2013
; Supports: Basic, _L ANSi, _L Unicode x86 and _L Unicode x64
;
; Updated 2/20/2014 - fixed Gdip_CreateRegion() and Gdip_GetClipRegion() on AHK Unicode x86
; Updated 5/13/2013 - fixed Gdip_SetBitmapToClipboard() on AHK Unicode x64
;
;#####################################################################################
;#####################################################################################
; STATUS ENUMERATION
; Return values for functions specified to have status enumerated return type
;#####################################################################################
;
; Ok =						= 0
; GenericError				= 1
; InvalidParameter			= 2
; OutOfMemory				= 3
; ObjectBusy				= 4
; InsufficientBuffer		= 5
; NotImplemented			= 6
; Win32Error				= 7
; WrongState				= 8
; Aborted					= 9
; FileNotFound				= 10
; ValueOverflow				= 11
; AccessDenied				= 12
; UnknownImageFormat		= 13
; FontFamilyNotFound		= 14
; FontStyleNotFound			= 15
; NotTrueTypeFont			= 16
; UnsupportedGdiplusVersion	= 17
; GdiplusNotInitialized		= 18
; PropertyNotFound			= 19
; PropertyNotSupported		= 20
; ProfileNotFound			= 21
;
;#####################################################################################
;#####################################################################################
; FUNCTIONS
;#####################################################################################
;
; UpdateLayeredWindow(hwnd, hdc, x="", y="", w="", h="", Alpha=255)
; BitBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, Raster="")
; StretchBlt(dDC, dx, dy, dw, dh, sDC, sx, sy, sw, sh, Raster="")
; SetImage(hwnd, hBitmap)
; Gdip_BitmapFromScreen(Screen=0, Raster="")
; CreateRectF(ByRef RectF, x, y, w, h)
; CreateSizeF(ByRef SizeF, w, h)
; CreateDIBSection
;
;#####################################################################################

; Function:     			UpdateLayeredWindow
; Description:  			Updates a layered window with the handle to the DC of a gdi bitmap
; 
; hwnd        				Handle of the layered window to update
; hdc           			Handle to the DC of the GDI bitmap to update the window with
; Layeredx      			x position to place the window
; Layeredy      			y position to place the window
; Layeredw      			Width of the window
; Layeredh      			Height of the window
; Alpha         			Default = 255 : The transparency (0-255) to set the window transparency
;
; return      				If the function succeeds, the return value is nonzero
;
; notes						If x or y omitted, then layered window will use its current coordinates
;							If w or h omitted then current width and height will be used

UpdateLayeredWindow(hwnd, hdc, x="", y="", w="", h="", Alpha=255)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	if ((x != "") && (y != ""))
		VarSetCapacity(pt, 8), NumPut(x, pt, 0, "UInt"), NumPut(y, pt, 4, "UInt")

	if (w = "") ||(h = "")
		WinGetPos,,, w, h, ahk_id %hwnd%
   
	return DllCall("UpdateLayeredWindow"
					, Ptr, hwnd
					, Ptr, 0
					, Ptr, ((x = "") && (y = "")) ? 0 : &pt
					, "int64*", w|h<<32
					, Ptr, hdc
					, "int64*", 0
					, "uint", 0
					, "UInt*", Alpha<<16|1<<24
					, "uint", 2)
}

;#####################################################################################

; Function				BitBlt
; Description			The BitBlt function performs a bit-block transfer of the color data corresponding to a rectangle 
;						of pixels from the specified source device context into a destination device context.
;
; dDC					handle to destination DC
; dx					x-coord of destination upper-left corner
; dy					y-coord of destination upper-left corner
; dw					width of the area to copy
; dh					height of the area to copy
; sDC					handle to source DC
; sx					x-coordinate of source upper-left corner
; sy					y-coordinate of source upper-left corner
; Raster				raster operation code
;
; return				If the function succeeds, the return value is nonzero
;
; notes					If no raster operation is specified, then SRCCOPY is used, which copies the source directly to the destination rectangle
;
; BLACKNESS				= 0x00000042
; NOTSRCERASE			= 0x001100A6
; NOTSRCCOPY			= 0x00330008
; SRCERASE				= 0x00440328
; DSTINVERT				= 0x00550009
; PATINVERT				= 0x005A0049
; SRCINVERT				= 0x00660046
; SRCAND				= 0x008800C6
; MERGEPAINT			= 0x00BB0226
; MERGECOPY				= 0x00C000CA
; SRCCOPY				= 0x00CC0020
; SRCPAINT				= 0x00EE0086
; PATCOPY				= 0x00F00021
; PATPAINT				= 0x00FB0A09
; WHITENESS				= 0x00FF0062
; CAPTUREBLT			= 0x40000000
; NOMIRRORBITMAP		= 0x80000000

BitBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, Raster="")
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	return DllCall("gdi32\BitBlt"
					, Ptr, dDC
					, "int", dx
					, "int", dy
					, "int", dw
					, "int", dh
					, Ptr, sDC
					, "int", sx
					, "int", sy
					, "uint", Raster ? Raster : 0x00CC0020)
}

;#####################################################################################

; Function				StretchBlt
; Description			The StretchBlt function copies a bitmap from a source rectangle into a destination rectangle, 
;						stretching or compressing the bitmap to fit the dimensions of the destination rectangle, if necessary.
;						The system stretches or compresses the bitmap according to the stretching mode currently set in the destination device context.
;
; ddc					handle to destination DC
; dx					x-coord of destination upper-left corner
; dy					y-coord of destination upper-left corner
; dw					width of destination rectangle
; dh					height of destination rectangle
; sdc					handle to source DC
; sx					x-coordinate of source upper-left corner
; sy					y-coordinate of source upper-left corner
; sw					width of source rectangle
; sh					height of source rectangle
; Raster				raster operation code
;
; return				If the function succeeds, the return value is nonzero
;
; notes					If no raster operation is specified, then SRCCOPY is used. It uses the same raster operations as BitBlt		

StretchBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, sw, sh, Raster="")
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	return DllCall("gdi32\StretchBlt"
					, Ptr, ddc
					, "int", dx
					, "int", dy
					, "int", dw
					, "int", dh
					, Ptr, sdc
					, "int", sx
					, "int", sy
					, "int", sw
					, "int", sh
					, "uint", Raster ? Raster : 0x00CC0020)
}

;#####################################################################################

; Function				SetStretchBltMode
; Description			The SetStretchBltMode function sets the bitmap stretching mode in the specified device context
;
; hdc					handle to the DC
; iStretchMode			The stretching mode, describing how the target will be stretched
;
; return				If the function succeeds, the return value is the previous stretching mode. If it fails it will return 0
;
; STRETCH_ANDSCANS 		= 0x01
; STRETCH_ORSCANS 		= 0x02
; STRETCH_DELETESCANS 	= 0x03
; STRETCH_HALFTONE 		= 0x04

SetStretchBltMode(hdc, iStretchMode=4)
{
	return DllCall("gdi32\SetStretchBltMode"
					, A_PtrSize ? "UPtr" : "UInt", hdc
					, "int", iStretchMode)
}

;#####################################################################################

; Function				SetImage
; Description			Associates a new image with a static control
;
; hwnd					handle of the control to update
; hBitmap				a gdi bitmap to associate the static control with
;
; return				If the function succeeds, the return value is nonzero

SetImage(hwnd, hBitmap)
{
	SendMessage, 0x172, 0x0, hBitmap,, ahk_id %hwnd%
	E := ErrorLevel
	DeleteObject(E)
	return E
}

;#####################################################################################

; Function				SetSysColorToControl
; Description			Sets a solid colour to a control
;
; hwnd					handle of the control to update
; SysColor				A system colour to set to the control
;
; return				If the function succeeds, the return value is zero
;
; notes					A control must have the 0xE style set to it so it is recognised as a bitmap
;						By default SysColor=15 is used which is COLOR_3DFACE. This is the standard background for a control
;
; COLOR_3DDKSHADOW				= 21
; COLOR_3DFACE					= 15
; COLOR_3DHIGHLIGHT				= 20
; COLOR_3DHILIGHT				= 20
; COLOR_3DLIGHT					= 22
; COLOR_3DSHADOW				= 16
; COLOR_ACTIVEBORDER			= 10
; COLOR_ACTIVECAPTION			= 2
; COLOR_APPWORKSPACE			= 12
; COLOR_BACKGROUND				= 1
; COLOR_BTNFACE					= 15
; COLOR_BTNHIGHLIGHT			= 20
; COLOR_BTNHILIGHT				= 20
; COLOR_BTNSHADOW				= 16
; COLOR_BTNTEXT					= 18
; COLOR_CAPTIONTEXT				= 9
; COLOR_DESKTOP					= 1
; COLOR_GRADIENTACTIVECAPTION	= 27
; COLOR_GRADIENTINACTIVECAPTION	= 28
; COLOR_GRAYTEXT				= 17
; COLOR_HIGHLIGHT				= 13
; COLOR_HIGHLIGHTTEXT			= 14
; COLOR_HOTLIGHT				= 26
; COLOR_INACTIVEBORDER			= 11
; COLOR_INACTIVECAPTION			= 3
; COLOR_INACTIVECAPTIONTEXT		= 19
; COLOR_INFOBK					= 24
; COLOR_INFOTEXT				= 23
; COLOR_MENU					= 4
; COLOR_MENUHILIGHT				= 29
; COLOR_MENUBAR					= 30
; COLOR_MENUTEXT				= 7
; COLOR_SCROLLBAR				= 0
; COLOR_WINDOW					= 5
; COLOR_WINDOWFRAME				= 6
; COLOR_WINDOWTEXT				= 8

SetSysColorToControl(hwnd, SysColor=15)
{
   WinGetPos,,, w, h, ahk_id %hwnd%
   bc := DllCall("GetSysColor", "Int", SysColor, "UInt")
   pBrushClear := Gdip_BrushCreateSolid(0xff000000 | (bc >> 16 | bc & 0xff00 | (bc & 0xff) << 16))
   pBitmap := Gdip_CreateBitmap(w, h), G := Gdip_GraphicsFromImage(pBitmap)
   Gdip_FillRectangle(G, pBrushClear, 0, 0, w, h)
   hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
   SetImage(hwnd, hBitmap)
   Gdip_DeleteBrush(pBrushClear)
   Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap), DeleteObject(hBitmap)
   return 0
}

;#####################################################################################

; Function				Gdip_BitmapFromScreen
; Description			Gets a gdi+ bitmap from the screen
;
; Screen				0 = All screens
;						Any numerical value = Just that screen
;						x|y|w|h = Take specific coordinates with a width and height
; Raster				raster operation code
;
; return      			If the function succeeds, the return value is a pointer to a gdi+ bitmap
;						-1:		one or more of x,y,w,h not passed properly
;
; notes					If no raster operation is specified, then SRCCOPY is used to the returned bitmap

Gdip_BitmapFromScreen(Screen=0, Raster="")
{
	if (Screen = 0)
	{
		Sysget, x, 76
		Sysget, y, 77	
		Sysget, w, 78
		Sysget, h, 79
	}
	else if (SubStr(Screen, 1, 5) = "hwnd:")
	{
		Screen := SubStr(Screen, 6)
		if !WinExist( "ahk_id " Screen)
			return -2
		WinGetPos,,, w, h, ahk_id %Screen%
		x := y := 0
		hhdc := GetDCEx(Screen, 3)
	}
	else if (Screen&1 != "")
	{
		Sysget, M, Monitor, %Screen%
		x := MLeft, y := MTop, w := MRight-MLeft, h := MBottom-MTop
	}
	else
	{
		StringSplit, S, Screen, |
		x := S1, y := S2, w := S3, h := S4
	}

	if (x = "") || (y = "") || (w = "") || (h = "")
		return -1

	chdc := CreateCompatibleDC(), hbm := CreateDIBSection(w, h, chdc), obm := SelectObject(chdc, hbm), hhdc := hhdc ? hhdc : GetDC()
	BitBlt(chdc, 0, 0, w, h, hhdc, x, y, Raster)
	ReleaseDC(hhdc)
	
	pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
	SelectObject(chdc, obm), DeleteObject(hbm), DeleteDC(hhdc), DeleteDC(chdc)
	return pBitmap
}

;#####################################################################################

; Function				Gdip_BitmapFromHWND
; Description			Uses PrintWindow to get a handle to the specified window and return a bitmap from it
;
; hwnd					handle to the window to get a bitmap from
;
; return				If the function succeeds, the return value is a pointer to a gdi+ bitmap
;
; notes					Window must not be not minimised in order to get a handle to it's client area

Gdip_BitmapFromHWND(hwnd)
{
	WinGetPos,,, Width, Height, ahk_id %hwnd%
	hbm := CreateDIBSection(Width, Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
	PrintWindow(hwnd, hdc)
	pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
	SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
	return pBitmap
}

;#####################################################################################

; Function    			CreateRectF
; Description			Creates a RectF object, containing a the coordinates and dimensions of a rectangle
;
; RectF       			Name to call the RectF object
; x            			x-coordinate of the upper left corner of the rectangle
; y            			y-coordinate of the upper left corner of the rectangle
; w            			Width of the rectangle
; h            			Height of the rectangle
;
; return      			No return value

CreateRectF(ByRef RectF, x, y, w, h)
{
   VarSetCapacity(RectF, 16)
   NumPut(x, RectF, 0, "float"), NumPut(y, RectF, 4, "float"), NumPut(w, RectF, 8, "float"), NumPut(h, RectF, 12, "float")
}

;#####################################################################################

; Function    			CreateRect
; Description			Creates a Rect object, containing a the coordinates and dimensions of a rectangle
;
; RectF       			Name to call the RectF object
; x            			x-coordinate of the upper left corner of the rectangle
; y            			y-coordinate of the upper left corner of the rectangle
; w            			Width of the rectangle
; h            			Height of the rectangle
;
; return      			No return value

CreateRect(ByRef Rect, x, y, w, h)
{
	VarSetCapacity(Rect, 16)
	NumPut(x, Rect, 0, "uint"), NumPut(y, Rect, 4, "uint"), NumPut(w, Rect, 8, "uint"), NumPut(h, Rect, 12, "uint")
}
;#####################################################################################

; Function		    	CreateSizeF
; Description			Creates a SizeF object, containing an 2 values
;
; SizeF         		Name to call the SizeF object
; w            			w-value for the SizeF object
; h            			h-value for the SizeF object
;
; return      			No Return value

CreateSizeF(ByRef SizeF, w, h)
{
   VarSetCapacity(SizeF, 8)
   NumPut(w, SizeF, 0, "float"), NumPut(h, SizeF, 4, "float")     
}
;#####################################################################################

; Function		    	CreatePointF
; Description			Creates a SizeF object, containing an 2 values
;
; SizeF         		Name to call the SizeF object
; w            			w-value for the SizeF object
; h            			h-value for the SizeF object
;
; return      			No Return value

CreatePointF(ByRef PointF, x, y)
{
   VarSetCapacity(PointF, 8)
   NumPut(x, PointF, 0, "float"), NumPut(y, PointF, 4, "float")     
}
;#####################################################################################

; Function				CreateDIBSection
; Description			The CreateDIBSection function creates a DIB (Device Independent Bitmap) that applications can write to directly
;
; w						width of the bitmap to create
; h						height of the bitmap to create
; hdc					a handle to the device context to use the palette from
; bpp					bits per pixel (32 = ARGB)
; ppvBits				A pointer to a variable that receives a pointer to the location of the DIB bit values
;
; return				returns a DIB. A gdi bitmap
;
; notes					ppvBits will receive the location of the pixels in the DIB

CreateDIBSection(w, h, hdc="", bpp=32, ByRef ppvBits=0)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	hdc2 := hdc ? hdc : GetDC()
	VarSetCapacity(bi, 40, 0)
	
	NumPut(w, bi, 4, "uint")
	, NumPut(h, bi, 8, "uint")
	, NumPut(40, bi, 0, "uint")
	, NumPut(1, bi, 12, "ushort")
	, NumPut(0, bi, 16, "uInt")
	, NumPut(bpp, bi, 14, "ushort")
	
	hbm := DllCall("CreateDIBSection"
					, Ptr, hdc2
					, Ptr, &bi
					, "uint", 0
					, A_PtrSize ? "UPtr*" : "uint*", ppvBits
					, Ptr, 0
					, "uint", 0, Ptr)

	if !hdc
		ReleaseDC(hdc2)
	return hbm
}

;#####################################################################################

; Function				PrintWindow
; Description			The PrintWindow function copies a visual window into the specified device context (DC), typically a printer DC
;
; hwnd					A handle to the window that will be copied
; hdc					A handle to the device context
; Flags					Drawing options
;
; return				If the function succeeds, it returns a nonzero value
;
; PW_CLIENTONLY			= 1

PrintWindow(hwnd, hdc, Flags=0)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	return DllCall("PrintWindow", Ptr, hwnd, Ptr, hdc, "uint", Flags)
}

;#####################################################################################

; Function				DestroyIcon
; Description			Destroys an icon and frees any memory the icon occupied
;
; hIcon					Handle to the icon to be destroyed. The icon must not be in use
;
; return				If the function succeeds, the return value is nonzero

DestroyIcon(hIcon)
{
	return DllCall("DestroyIcon", A_PtrSize ? "UPtr" : "UInt", hIcon)
}

;#####################################################################################

PaintDesktop(hdc)
{
	return DllCall("PaintDesktop", A_PtrSize ? "UPtr" : "UInt", hdc)
}

;#####################################################################################

CreateCompatibleBitmap(hdc, w, h)
{
	return DllCall("gdi32\CreateCompatibleBitmap", A_PtrSize ? "UPtr" : "UInt", hdc, "int", w, "int", h)
}

;#####################################################################################

; Function				CreateCompatibleDC
; Description			This function creates a memory device context (DC) compatible with the specified device
;
; hdc					Handle to an existing device context					
;
; return				returns the handle to a device context or 0 on failure
;
; notes					If this handle is 0 (by default), the function creates a memory device context compatible with the application's current screen

CreateCompatibleDC(hdc=0)
{
   return DllCall("CreateCompatibleDC", A_PtrSize ? "UPtr" : "UInt", hdc)
}

;#####################################################################################

; Function				SelectObject
; Description			The SelectObject function selects an object into the specified device context (DC). The new object replaces the previous object of the same type
;
; hdc					Handle to a DC
; hgdiobj				A handle to the object to be selected into the DC
;
; return				If the selected object is not a region and the function succeeds, the return value is a handle to the object being replaced
;
; notes					The specified object must have been created by using one of the following functions
;						Bitmap - CreateBitmap, CreateBitmapIndirect, CreateCompatibleBitmap, CreateDIBitmap, CreateDIBSection (A single bitmap cannot be selected into more than one DC at the same time)
;						Brush - CreateBrushIndirect, CreateDIBPatternBrush, CreateDIBPatternBrushPt, CreateHatchBrush, CreatePatternBrush, CreateSolidBrush
;						Font - CreateFont, CreateFontIndirect
;						Pen - CreatePen, CreatePenIndirect
;						Region - CombineRgn, CreateEllipticRgn, CreateEllipticRgnIndirect, CreatePolygonRgn, CreateRectRgn, CreateRectRgnIndirect
;
; notes					If the selected object is a region and the function succeeds, the return value is one of the following value
;
; SIMPLEREGION			= 2 Region consists of a single rectangle
; COMPLEXREGION			= 3 Region consists of more than one rectangle
; NULLREGION			= 1 Region is empty

SelectObject(hdc, hgdiobj)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	return DllCall("SelectObject", Ptr, hdc, Ptr, hgdiobj)
}

;#####################################################################################

; Function				DeleteObject
; Description			This function deletes a logical pen, brush, font, bitmap, region, or palette, freeing all system resources associated with the object
;						After the object is deleted, the specified handle is no longer valid
;
; hObject				Handle to a logical pen, brush, font, bitmap, region, or palette to delete
;
; return				Nonzero indicates success. Zero indicates that the specified handle is not valid or that the handle is currently selected into a device context

DeleteObject(hObject)
{
   return DllCall("DeleteObject", A_PtrSize ? "UPtr" : "UInt", hObject)
}

;#####################################################################################

; Function				GetDC
; Description			This function retrieves a handle to a display device context (DC) for the client area of the specified window.
;						The display device context can be used in subsequent graphics display interface (GDI) functions to draw in the client area of the window. 
;
; hwnd					Handle to the window whose device context is to be retrieved. If this value is NULL, GetDC retrieves the device context for the entire screen					
;
; return				The handle the device context for the specified window's client area indicates success. NULL indicates failure

GetDC(hwnd=0)
{
	return DllCall("GetDC", A_PtrSize ? "UPtr" : "UInt", hwnd)
}

;#####################################################################################

; DCX_CACHE = 0x2
; DCX_CLIPCHILDREN = 0x8
; DCX_CLIPSIBLINGS = 0x10
; DCX_EXCLUDERGN = 0x40
; DCX_EXCLUDEUPDATE = 0x100
; DCX_INTERSECTRGN = 0x80
; DCX_INTERSECTUPDATE = 0x200
; DCX_LOCKWINDOWUPDATE = 0x400
; DCX_NORECOMPUTE = 0x100000
; DCX_NORESETATTRS = 0x4
; DCX_PARENTCLIP = 0x20
; DCX_VALIDATE = 0x200000
; DCX_WINDOW = 0x1

GetDCEx(hwnd, flags=0, hrgnClip=0)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
    return DllCall("GetDCEx", Ptr, hwnd, Ptr, hrgnClip, "int", flags)
}

;#####################################################################################

; Function				ReleaseDC
; Description			This function releases a device context (DC), freeing it for use by other applications. The effect of ReleaseDC depends on the type of device context
;
; hdc					Handle to the device context to be released
; hwnd					Handle to the window whose device context is to be released
;
; return				1 = released
;						0 = not released
;
; notes					The application must call the ReleaseDC function for each call to the GetWindowDC function and for each call to the GetDC function that retrieves a common device context
;						An application cannot use the ReleaseDC function to release a device context that was created by calling the CreateDC function; instead, it must use the DeleteDC function. 

ReleaseDC(hdc, hwnd=0)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	return DllCall("ReleaseDC", Ptr, hwnd, Ptr, hdc)
}

;#####################################################################################

; Function				DeleteDC
; Description			The DeleteDC function deletes the specified device context (DC)
;
; hdc					A handle to the device context
;
; return				If the function succeeds, the return value is nonzero
;
; notes					An application must not delete a DC whose handle was obtained by calling the GetDC function. Instead, it must call the ReleaseDC function to free the DC

DeleteDC(hdc)
{
   return DllCall("DeleteDC", A_PtrSize ? "UPtr" : "UInt", hdc)
}
;#####################################################################################

; Function				Gdip_LibraryVersion
; Description			Get the current library version
;
; return				the library version
;
; notes					This is useful for non compiled programs to ensure that a person doesn't run an old version when testing your scripts

Gdip_LibraryVersion()
{
	return 1.45
}

;#####################################################################################

; Function				Gdip_LibrarySubVersion
; Description			Get the current library sub version
;
; return				the library sub version
;
; notes					This is the sub-version currently maintained by Rseding91
Gdip_LibrarySubVersion()
{
	return 1.47
}

;#####################################################################################

; Function:    			Gdip_BitmapFromBRA
; Description: 			Gets a pointer to a gdi+ bitmap from a BRA file
;
; BRAFromMemIn			The variable for a BRA file read to memory
; File					The name of the file, or its number that you would like (This depends on alternate parameter)
; Alternate				Changes whether the File parameter is the file name or its number
;
; return      			If the function succeeds, the return value is a pointer to a gdi+ bitmap
;						-1 = The BRA variable is empty
;						-2 = The BRA has an incorrect header
;						-3 = The BRA has information missing
;						-4 = Could not find file inside the BRA

Gdip_BitmapFromBRA(ByRef BRAFromMemIn, File, Alternate=0)
{
	Static FName = "ObjRelease"
	
	if !BRAFromMemIn
		return -1
	Loop, Parse, BRAFromMemIn, `n
	{
		if (A_Index = 1)
		{
			StringSplit, Header, A_LoopField, |
			if (Header0 != 4 || Header2 != "BRA!")
				return -2
		}
		else if (A_Index = 2)
		{
			StringSplit, Info, A_LoopField, |
			if (Info0 != 3)
				return -3
		}
		else
			break
	}
	if !Alternate
		StringReplace, File, File, \, \\, All
	RegExMatch(BRAFromMemIn, "mi`n)^" (Alternate ? File "\|.+?\|(\d+)\|(\d+)" : "\d+\|" File "\|(\d+)\|(\d+)") "$", FileInfo)
	if !FileInfo
		return -4
	
	hData := DllCall("GlobalAlloc", "uint", 2, Ptr, FileInfo2, Ptr)
	pData := DllCall("GlobalLock", Ptr, hData, Ptr)
	DllCall("RtlMoveMemory", Ptr, pData, Ptr, &BRAFromMemIn+Info2+FileInfo1, Ptr, FileInfo2)
	DllCall("GlobalUnlock", Ptr, hData)
	DllCall("ole32\CreateStreamOnHGlobal", Ptr, hData, "int", 1, A_PtrSize ? "UPtr*" : "UInt*", pStream)
	DllCall("gdiplus\GdipCreateBitmapFromStream", Ptr, pStream, A_PtrSize ? "UPtr*" : "UInt*", pBitmap)
	If (A_PtrSize)
		%FName%(pStream)
	Else
		DllCall(NumGet(NumGet(1*pStream)+8), "uint", pStream)
	return pBitmap
}

;#####################################################################################

; Function				Gdip_DrawRectangle
; Description			This function uses a pen to draw the outline of a rectangle into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; x						x-coordinate of the top left of the rectangle
; y						y-coordinate of the top left of the rectangle
; w						width of the rectanlge
; h						height of the rectangle
;
; return				status enumeration. 0 = success
;
; notes					as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width

Gdip_DrawRectangle(pGraphics, pPen, x, y, w, h)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	return DllCall("gdiplus\GdipDrawRectangle", Ptr, pGraphics, Ptr, pPen, "float", x, "float", y, "float", w, "float", h)
}

;#####################################################################################

; Function				Gdip_DrawRoundedRectangle
; Description			This function uses a pen to draw the outline of a rounded rectangle into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; x						x-coordinate of the top left of the rounded rectangle
; y						y-coordinate of the top left of the rounded rectangle
; w						width of the rectanlge
; h						height of the rectangle
; r						radius of the rounded corners
;
; return				status enumeration. 0 = success
;
; notes					as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width

Gdip_DrawRoundedRectangle(pGraphics, pPen, x, y, w, h, r)
{
	Gdip_SetClipRect(pGraphics, x-r, y-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x+w-r, y-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x-r, y+h-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x+w-r, y+h-r, 2*r, 2*r, 4)
	E := Gdip_DrawRectangle(pGraphics, pPen, x, y, w, h)
	Gdip_ResetClip(pGraphics)
	Gdip_SetClipRect(pGraphics, x-(2*r), y+r, w+(4*r), h-(2*r), 4)
	Gdip_SetClipRect(pGraphics, x+r, y-(2*r), w-(2*r), h+(4*r), 4)
	Gdip_DrawEllipse(pGraphics, pPen, x, y, 2*r, 2*r)
	Gdip_DrawEllipse(pGraphics, pPen, x+w-(2*r), y, 2*r, 2*r)
	Gdip_DrawEllipse(pGraphics, pPen, x, y+h-(2*r), 2*r, 2*r)
	Gdip_DrawEllipse(pGraphics, pPen, x+w-(2*r), y+h-(2*r), 2*r, 2*r)
	Gdip_ResetClip(pGraphics)
	return E
}

;#####################################################################################

; Function				Gdip_DrawEllipse
; Description			This function uses a pen to draw the outline of an ellipse into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; x						x-coordinate of the top left of the rectangle the ellipse will be drawn into
; y						y-coordinate of the top left of the rectangle the ellipse will be drawn into
; w						width of the ellipse
; h						height of the ellipse
;
; return				status enumeration. 0 = success
;
; notes					as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width

Gdip_DrawEllipse(pGraphics, pPen, x, y, w, h)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	return DllCall("gdiplus\GdipDrawEllipse", Ptr, pGraphics, Ptr, pPen, "float", x, "float", y, "float", w, "float", h)
}

;#####################################################################################

; Function				Gdip_DrawBezier
; Description			This function uses a pen to draw the outline of a bezier (a weighted curve) into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; x1					x-coordinate of the start of the bezier
; y1					y-coordinate of the start of the bezier
; x2					x-coordinate of the first arc of the bezier
; y2					y-coordinate of the first arc of the bezier
; x3					x-coordinate of the second arc of the bezier
; y3					y-coordinate of the second arc of the bezier
; x4					x-coordinate of the end of the bezier
; y4					y-coordinate of the end of the bezier
;
; return				status enumeration. 0 = success
;
; notes					as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width

Gdip_DrawBezier(pGraphics, pPen, x1, y1, x2, y2, x3, y3, x4, y4)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	return DllCall("gdiplus\GdipDrawBezier"
					, Ptr, pgraphics
					, Ptr, pPen
					, "float", x1
					, "float", y1
					, "float", x2
					, "float", y2
					, "float", x3
					, "float", y3
					, "float", x4
					, "float", y4)
}

;#####################################################################################

; Function				Gdip_DrawArc
; Description			This function uses a pen to draw the outline of an arc into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; x						x-coordinate of the start of the arc
; y						y-coordinate of the start of the arc
; w						width of the arc
; h						height of the arc
; StartAngle			specifies the angle between the x-axis and the starting point of the arc
; SweepAngle			specifies the angle between the starting and ending points of the arc
;
; return				status enumeration. 0 = success
;
; notes					as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width

Gdip_DrawArc(pGraphics, pPen, x, y, w, h, StartAngle, SweepAngle)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	return DllCall("gdiplus\GdipDrawArc"
					, Ptr, pGraphics
					, Ptr, pPen
					, "float", x
					, "float", y
					, "float", w
					, "float", h
					, "float", StartAngle
					, "float", SweepAngle)
}

;#####################################################################################

; Function				Gdip_DrawPie
; Description			This function uses a pen to draw the outline of a pie into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; x						x-coordinate of the start of the pie
; y						y-coordinate of the start of the pie
; w						width of the pie
; h						height of the pie
; StartAngle			specifies the angle between the x-axis and the starting point of the pie
; SweepAngle			specifies the angle between the starting and ending points of the pie
;
; return				status enumeration. 0 = success
;
; notes					as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width

Gdip_DrawPie(pGraphics, pPen, x, y, w, h, StartAngle, SweepAngle)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	return DllCall("gdiplus\GdipDrawPie", Ptr, pGraphics, Ptr, pPen, "float", x, "float", y, "float", w, "float", h, "float", StartAngle, "float", SweepAngle)
}

;#####################################################################################

; Function				Gdip_DrawLine
; Description			This function uses a pen to draw a line into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; x1					x-coordinate of the start of the line
; y1					y-coordinate of the start of the line
; x2					x-coordinate of the end of the line
; y2					y-coordinate of the end of the line
;
; return				status enumeration. 0 = success		

Gdip_DrawLine(pGraphics, pPen, x1, y1, x2, y2)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	return DllCall("gdiplus\GdipDrawLine"
					, Ptr, pGraphics
					, Ptr, pPen
					, "float", x1
					, "float", y1
					, "float", x2
					, "float", y2)
}

;#####################################################################################

; Function				Gdip_DrawLines
; Description			This function uses a pen to draw a series of joined lines into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; Points				the coordinates of all the points passed as x1,y1|x2,y2|x3,y3.....
;
; return				status enumeration. 0 = success				

Gdip_DrawLines(pGraphics, pPen, Points)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	StringSplit, Points, Points, |
	VarSetCapacity(PointF, 8*Points0)   
	Loop, %Points0%
	{
		StringSplit, Coord, Points%A_Index%, `,
		NumPut(Coord1, PointF, 8*(A_Index-1), "float"), NumPut(Coord2, PointF, (8*(A_Index-1))+4, "float")
	}
	return DllCall("gdiplus\GdipDrawLines", Ptr, pGraphics, Ptr, pPen, Ptr, &PointF, "int", Points0)
}

;#####################################################################################

; Function				Gdip_FillRectangle
; Description			This function uses a brush to fill a rectangle in the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBrush				Pointer to a brush
; x						x-coordinate of the top left of the rectangle
; y						y-coordinate of the top left of the rectangle
; w						width of the rectanlge
; h						height of the rectangle
;
; return				status enumeration. 0 = success

Gdip_FillRectangle(pGraphics, pBrush, x, y, w, h)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	return DllCall("gdiplus\GdipFillRectangle"
					, Ptr, pGraphics
					, Ptr, pBrush
					, "float", x
					, "float", y
					, "float", w
					, "float", h)
}

;#####################################################################################

; Function				Gdip_FillRoundedRectangle
; Description			This function uses a brush to fill a rounded rectangle in the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBrush				Pointer to a brush
; x						x-coordinate of the top left of the rounded rectangle
; y						y-coordinate of the top left of the rounded rectangle
; w						width of the rectanlge
; h						height of the rectangle
; r						radius of the rounded corners
;
; return				status enumeration. 0 = success

Gdip_FillRoundedRectangle(pGraphics, pBrush, x, y, w, h, r)
{
	Region := Gdip_GetClipRegion(pGraphics)
	Gdip_SetClipRect(pGraphics, x-r, y-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x+w-r, y-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x-r, y+h-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x+w-r, y+h-r, 2*r, 2*r, 4)
	E := Gdip_FillRectangle(pGraphics, pBrush, x, y, w, h)
	Gdip_SetClipRegion(pGraphics, Region, 0)
	Gdip_SetClipRect(pGraphics, x-(2*r), y+r, w+(4*r), h-(2*r), 4)
	Gdip_SetClipRect(pGraphics, x+r, y-(2*r), w-(2*r), h+(4*r), 4)
	Gdip_FillEllipse(pGraphics, pBrush, x, y, 2*r, 2*r)
	Gdip_FillEllipse(pGraphics, pBrush, x+w-(2*r), y, 2*r, 2*r)
	Gdip_FillEllipse(pGraphics, pBrush, x, y+h-(2*r), 2*r, 2*r)
	Gdip_FillEllipse(pGraphics, pBrush, x+w-(2*r), y+h-(2*r), 2*r, 2*r)
	Gdip_SetClipRegion(pGraphics, Region, 0)
	Gdip_DeleteRegion(Region)
	return E
}

;#####################################################################################

; Function				Gdip_FillPolygon
; Description			This function uses a brush to fill a polygon in the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBrush				Pointer to a brush
; Points				the coordinates of all the points passed as x1,y1|x2,y2|x3,y3.....
;
; return				status enumeration. 0 = success
;
; notes					Alternate will fill the polygon as a whole, wheras winding will fill each new "segment"
; Alternate 			= 0
; Winding 				= 1

Gdip_FillPolygon(pGraphics, pBrush, Points, FillMode=0)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	StringSplit, Points, Points, |
	VarSetCapacity(PointF, 8*Points0)   
	Loop, %Points0%
	{
		StringSplit, Coord, Points%A_Index%, `,
		NumPut(Coord1, PointF, 8*(A_Index-1), "float"), NumPut(Coord2, PointF, (8*(A_Index-1))+4, "float")
	}   
	return DllCall("gdiplus\GdipFillPolygon", Ptr, pGraphics, Ptr, pBrush, Ptr, &PointF, "int", Points0, "int", FillMode)
}

;#####################################################################################

; Function				Gdip_FillPie
; Description			This function uses a brush to fill a pie in the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBrush				Pointer to a brush
; x						x-coordinate of the top left of the pie
; y						y-coordinate of the top left of the pie
; w						width of the pie
; h						height of the pie
; StartAngle			specifies the angle between the x-axis and the starting point of the pie
; SweepAngle			specifies the angle between the starting and ending points of the pie
;
; return				status enumeration. 0 = success

Gdip_FillPie(pGraphics, pBrush, x, y, w, h, StartAngle, SweepAngle)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	return DllCall("gdiplus\GdipFillPie"
					, Ptr, pGraphics
					, Ptr, pBrush
					, "float", x
					, "float", y
					, "float", w
					, "float", h
					, "float", StartAngle
					, "float", SweepAngle)
}

;#####################################################################################

; Function				Gdip_FillEllipse
; Description			This function uses a brush to fill an ellipse in the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBrush				Pointer to a brush
; x						x-coordinate of the top left of the ellipse
; y						y-coordinate of the top left of the ellipse
; w						width of the ellipse
; h						height of the ellipse
;
; return				status enumeration. 0 = success

Gdip_FillEllipse(pGraphics, pBrush, x, y, w, h)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	return DllCall("gdiplus\GdipFillEllipse", Ptr, pGraphics, Ptr, pBrush, "float", x, "float", y, "float", w, "float", h)
}

;#####################################################################################

; Function				Gdip_FillRegion
; Description			This function uses a brush to fill a region in the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBrush				Pointer to a brush
; Region				Pointer to a Region
;
; return				status enumeration. 0 = success
;
; notes					You can create a region Gdip_CreateRegion() and then add to this

Gdip_FillRegion(pGraphics, pBrush, Region)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	return DllCall("gdiplus\GdipFillRegion", Ptr, pGraphics, Ptr, pBrush, Ptr, Region)
}

;#####################################################################################

; Function				Gdip_FillPath
; Description			This function uses a brush to fill a path in the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBrush				Pointer to a brush
; Region				Pointer to a Path
;
; return				status enumeration. 0 = success

Gdip_FillPath(pGraphics, pBrush, Path)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	return DllCall("gdiplus\GdipFillPath", Ptr, pGraphics, Ptr, pBrush, Ptr, Path)
}

;#####################################################################################

; Function				Gdip_DrawImagePointsRect
; Description			This function draws a bitmap into the Graphics of another bitmap and skews it
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBitmap				Pointer to a bitmap to be drawn
; Points				Points passed as x1,y1|x2,y2|x3,y3 (3 points: top left, top right, bottom left) describing the drawing of the bitmap
; sx					x-coordinate of source upper-left corner
; sy					y-coordinate of source upper-left corner
; sw					width of source rectangle
; sh					height of source rectangle
; Matrix				a matrix used to alter image attributes when drawing
;
; return				status enumeration. 0 = success
;
; notes					if sx,sy,sw,sh are missed then the entire source bitmap will be used
;						Matrix can be omitted to just draw with no alteration to ARGB
;						Matrix may be passed as a digit from 0 - 1 to change just transparency
;						Matrix can be passed as a matrix with any delimiter

Gdip_DrawImagePointsRect(pGraphics, pBitmap, Points, sx="", sy="", sw="", sh="", Matrix=1)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	StringSplit, Points, Points, |
	VarSetCapacity(PointF, 8*Points0)   
	Loop, %Points0%
	{
		StringSplit, Coord, Points%A_Index%, `,
		NumPut(Coord1, PointF, 8*(A_Index-1), "float"), NumPut(Coord2, PointF, (8*(A_Index-1))+4, "float")
	}

	if (Matrix&1 = "")
		ImageAttr := Gdip_SetImageAttributesColorMatrix(Matrix)
	else if (Matrix != 1)
		ImageAttr := Gdip_SetImageAttributesColorMatrix("1|0|0|0|0|0|1|0|0|0|0|0|1|0|0|0|0|0|" Matrix "|0|0|0|0|0|1")
		
	if (sx = "" && sy = "" && sw = "" && sh = "")
	{
		sx := 0, sy := 0
		sw := Gdip_GetImageWidth(pBitmap)
		sh := Gdip_GetImageHeight(pBitmap)
	}

	E := DllCall("gdiplus\GdipDrawImagePointsRect"
				, Ptr, pGraphics
				, Ptr, pBitmap
				, Ptr, &PointF
				, "int", Points0
				, "float", sx
				, "float", sy
				, "float", sw
				, "float", sh
				, "int", 2
				, Ptr, ImageAttr
				, Ptr, 0
				, Ptr, 0)
	if ImageAttr
		Gdip_DisposeImageAttributes(ImageAttr)
	return E
}

;#####################################################################################

; Function				Gdip_DrawImage
; Description			This function draws a bitmap into the Graphics of another bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pBitmap				Pointer to a bitmap to be drawn
; dx					x-coord of destination upper-left corner
; dy					y-coord of destination upper-left corner
; dw					width of destination image
; dh					height of destination image
; sx					x-coordinate of source upper-left corner
; sy					y-coordinate of source upper-left corner
; sw					width of source image
; sh					height of source image
; Matrix				a matrix used to alter image attributes when drawing
;
; return				status enumeration. 0 = success
;
; notes					if sx,sy,sw,sh are missed then the entire source bitmap will be used
;						Gdip_DrawImage performs faster
;						Matrix can be omitted to just draw with no alteration to ARGB
;						Matrix may be passed as a digit from 0 - 1 to change just transparency
;						Matrix can be passed as a matrix with any delimiter. For example:
;						MatrixBright=
;						(
;						1.5		|0		|0		|0		|0
;						0		|1.5	|0		|0		|0
;						0		|0		|1.5	|0		|0
;						0		|0		|0		|1		|0
;						0.05	|0.05	|0.05	|0		|1
;						)
;
; notes					MatrixBright = 1.5|0|0|0|0|0|1.5|0|0|0|0|0|1.5|0|0|0|0|0|1|0|0.05|0.05|0.05|0|1
;						MatrixGreyScale = 0.299|0.299|0.299|0|0|0.587|0.587|0.587|0|0|0.114|0.114|0.114|0|0|0|0|0|1|0|0|0|0|0|1
;						MatrixNegative = -1|0|0|0|0|0|-1|0|0|0|0|0|-1|0|0|0|0|0|1|0|0|0|0|0|1

Gdip_DrawImage(pGraphics, pBitmap, dx="", dy="", dw="", dh="", sx="", sy="", sw="", sh="", Matrix=1)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	if (Matrix&1 = "")
		ImageAttr := Gdip_SetImageAttributesColorMatrix(Matrix)
	else if (Matrix != 1)
		ImageAttr := Gdip_SetImageAttributesColorMatrix("1|0|0|0|0|0|1|0|0|0|0|0|1|0|0|0|0|0|" Matrix "|0|0|0|0|0|1")

	if (sx = "" && sy = "" && sw = "" && sh = "")
	{
		if (dx = "" && dy = "" && dw = "" && dh = "")
		{
			sx := dx := 0, sy := dy := 0
			sw := dw := Gdip_GetImageWidth(pBitmap)
			sh := dh := Gdip_GetImageHeight(pBitmap)
		}
		else
		{
			sx := sy := 0
			sw := Gdip_GetImageWidth(pBitmap)
			sh := Gdip_GetImageHeight(pBitmap)
		}
	}

	E := DllCall("gdiplus\GdipDrawImageRectRect"
				, Ptr, pGraphics
				, Ptr, pBitmap
				, "float", dx
				, "float", dy
				, "float", dw
				, "float", dh
				, "float", sx
				, "float", sy
				, "float", sw
				, "float", sh
				, "int", 2
				, Ptr, ImageAttr
				, Ptr, 0
				, Ptr, 0)
	if ImageAttr
		Gdip_DisposeImageAttributes(ImageAttr)
	return E
}

;#####################################################################################

; Function				Gdip_SetImageAttributesColorMatrix
; Description			This function creates an image matrix ready for drawing
;
; Matrix				a matrix used to alter image attributes when drawing
;						passed with any delimeter
;
; return				returns an image matrix on sucess or 0 if it fails
;
; notes					MatrixBright = 1.5|0|0|0|0|0|1.5|0|0|0|0|0|1.5|0|0|0|0|0|1|0|0.05|0.05|0.05|0|1
;						MatrixGreyScale = 0.299|0.299|0.299|0|0|0.587|0.587|0.587|0|0|0.114|0.114|0.114|0|0|0|0|0|1|0|0|0|0|0|1
;						MatrixNegative = -1|0|0|0|0|0|-1|0|0|0|0|0|-1|0|0|0|0|0|1|0|0|0|0|0|1

Gdip_SetImageAttributesColorMatrix(Matrix)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	VarSetCapacity(ColourMatrix, 100, 0)
	Matrix := RegExReplace(RegExReplace(Matrix, "^[^\d-\.]+([\d\.])", "$1", "", 1), "[^\d-\.]+", "|")
	StringSplit, Matrix, Matrix, |
	Loop, 25
	{
		Matrix := (Matrix%A_Index% != "") ? Matrix%A_Index% : Mod(A_Index-1, 6) ? 0 : 1
		NumPut(Matrix, ColourMatrix, (A_Index-1)*4, "float")
	}
	DllCall("gdiplus\GdipCreateImageAttributes", A_PtrSize ? "UPtr*" : "uint*", ImageAttr)
	DllCall("gdiplus\GdipSetImageAttributesColorMatrix", Ptr, ImageAttr, "int", 1, "int", 1, Ptr, &ColourMatrix, Ptr, 0, "int", 0)
	return ImageAttr
}

;#####################################################################################

; Function				Gdip_GraphicsFromImage
; Description			This function gets the graphics for a bitmap used for drawing functions
;
; pBitmap				Pointer to a bitmap to get the pointer to its graphics
;
; return				returns a pointer to the graphics of a bitmap
;
; notes					a bitmap can be drawn into the graphics of another bitmap

Gdip_GraphicsFromImage(pBitmap)
{
	DllCall("gdiplus\GdipGetImageGraphicsContext", A_PtrSize ? "UPtr" : "UInt", pBitmap, A_PtrSize ? "UPtr*" : "UInt*", pGraphics)
	return pGraphics
}

;#####################################################################################

; Function				Gdip_GraphicsFromHDC
; Description			This function gets the graphics from the handle to a device context
;
; hdc					This is the handle to the device context
;
; return				returns a pointer to the graphics of a bitmap
;
; notes					You can draw a bitmap into the graphics of another bitmap

Gdip_GraphicsFromHDC(hdc)
{
    DllCall("gdiplus\GdipCreateFromHDC", A_PtrSize ? "UPtr" : "UInt", hdc, A_PtrSize ? "UPtr*" : "UInt*", pGraphics)
    return pGraphics
}

;#####################################################################################

; Function				Gdip_GetDC
; Description			This function gets the device context of the passed Graphics
;
; hdc					This is the handle to the device context
;
; return				returns the device context for the graphics of a bitmap

Gdip_GetDC(pGraphics)
{
	DllCall("gdiplus\GdipGetDC", A_PtrSize ? "UPtr" : "UInt", pGraphics, A_PtrSize ? "UPtr*" : "UInt*", hdc)
	return hdc
}

;#####################################################################################

; Function				Gdip_ReleaseDC
; Description			This function releases a device context from use for further use
;
; pGraphics				Pointer to the graphics of a bitmap
; hdc					This is the handle to the device context
;
; return				status enumeration. 0 = success

Gdip_ReleaseDC(pGraphics, hdc)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	return DllCall("gdiplus\GdipReleaseDC", Ptr, pGraphics, Ptr, hdc)
}

;#####################################################################################

; Function				Gdip_GraphicsClear
; Description			Clears the graphics of a bitmap ready for further drawing
;
; pGraphics				Pointer to the graphics of a bitmap
; ARGB					The colour to clear the graphics to
;
; return				status enumeration. 0 = success
;
; notes					By default this will make the background invisible
;						Using clipping regions you can clear a particular area on the graphics rather than clearing the entire graphics

Gdip_GraphicsClear(pGraphics, ARGB=0x00ffffff)
{
    return DllCall("gdiplus\GdipGraphicsClear", A_PtrSize ? "UPtr" : "UInt", pGraphics, "int", ARGB)
}

;#####################################################################################

; Function				Gdip_BlurBitmap
; Description			Gives a pointer to a blurred bitmap from a pointer to a bitmap
;
; pBitmap				Pointer to a bitmap to be blurred
; Blur					The Amount to blur a bitmap by from 1 (least blur) to 100 (most blur)
;
; return				If the function succeeds, the return value is a pointer to the new blurred bitmap
;						-1 = The blur parameter is outside the range 1-100
;
; notes					This function will not dispose of the original bitmap

Gdip_BlurBitmap(pBitmap, Blur)
{
	if (Blur > 100) || (Blur < 1)
		return -1	
	
	sWidth := Gdip_GetImageWidth(pBitmap), sHeight := Gdip_GetImageHeight(pBitmap)
	dWidth := sWidth//Blur, dHeight := sHeight//Blur

	pBitmap1 := Gdip_CreateBitmap(dWidth, dHeight)
	G1 := Gdip_GraphicsFromImage(pBitmap1)
	Gdip_SetInterpolationMode(G1, 7)
	Gdip_DrawImage(G1, pBitmap, 0, 0, dWidth, dHeight, 0, 0, sWidth, sHeight)

	Gdip_DeleteGraphics(G1)

	pBitmap2 := Gdip_CreateBitmap(sWidth, sHeight)
	G2 := Gdip_GraphicsFromImage(pBitmap2)
	Gdip_SetInterpolationMode(G2, 7)
	Gdip_DrawImage(G2, pBitmap1, 0, 0, sWidth, sHeight, 0, 0, dWidth, dHeight)

	Gdip_DeleteGraphics(G2)
	Gdip_DisposeImage(pBitmap1)
	return pBitmap2
}

;#####################################################################################

; Function:     		Gdip_SaveBitmapToFile
; Description:  		Saves a bitmap to a file in any supported format onto disk
;   
; pBitmap				Pointer to a bitmap
; sOutput      			The name of the file that the bitmap will be saved to. Supported extensions are: .BMP,.DIB,.RLE,.JPG,.JPEG,.JPE,.JFIF,.GIF,.TIF,.TIFF,.PNG
; Quality      			If saving as jpg (.JPG,.JPEG,.JPE,.JFIF) then quality can be 1-100 with default at maximum quality
;
; return      			If the function succeeds, the return value is zero, otherwise:
;						-1 = Extension supplied is not a supported file format
;						-2 = Could not get a list of encoders on system
;						-3 = Could not find matching encoder for specified file format
;						-4 = Could not get WideChar name of output file
;						-5 = Could not save file to disk
;
; notes					This function will use the extension supplied from the sOutput parameter to determine the output format

Gdip_SaveBitmapToFile(pBitmap, sOutput, Quality=75)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	SplitPath, sOutput,,, Extension
	if Extension not in BMP,DIB,RLE,JPG,JPEG,JPE,JFIF,GIF,TIF,TIFF,PNG
		return -1
	Extension := "." Extension

	DllCall("gdiplus\GdipGetImageEncodersSize", "uint*", nCount, "uint*", nSize)
	VarSetCapacity(ci, nSize)
	DllCall("gdiplus\GdipGetImageEncoders", "uint", nCount, "uint", nSize, Ptr, &ci)
	if !(nCount && nSize)
		return -2
	
	If (A_IsUnicode){
		StrGet_Name := "StrGet"
		Loop, %nCount%
		{
			sString := %StrGet_Name%(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
			if !InStr(sString, "*" Extension)
				continue
			
			pCodec := &ci+idx
			break
		}
	} else {
		Loop, %nCount%
		{
			Location := NumGet(ci, 76*(A_Index-1)+44)
			nSize := DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "uint", 0, "int",  0, "uint", 0, "uint", 0)
			VarSetCapacity(sString, nSize)
			DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "str", sString, "int", nSize, "uint", 0, "uint", 0)
			if !InStr(sString, "*" Extension)
				continue
			
			pCodec := &ci+76*(A_Index-1)
			break
		}
	}
	
	if !pCodec
		return -3

	if (Quality != 75)
	{
		Quality := (Quality < 0) ? 0 : (Quality > 100) ? 100 : Quality
		if Extension in .JPG,.JPEG,.JPE,.JFIF
		{
			DllCall("gdiplus\GdipGetEncoderParameterListSize", Ptr, pBitmap, Ptr, pCodec, "uint*", nSize)
			VarSetCapacity(EncoderParameters, nSize, 0)
			DllCall("gdiplus\GdipGetEncoderParameterList", Ptr, pBitmap, Ptr, pCodec, "uint", nSize, Ptr, &EncoderParameters)
			Loop, % NumGet(EncoderParameters, "UInt")      ;%
			{
				elem := (24+(A_PtrSize ? A_PtrSize : 4))*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
				if (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6)
				{
					p := elem+&EncoderParameters-pad-4
					NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20, "UInt")), "UInt")
					break
				}
			}      
		}
	}

	if (!A_IsUnicode)
	{
		nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sOutput, "int", -1, Ptr, 0, "int", 0)
		VarSetCapacity(wOutput, nSize*2)
		DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sOutput, "int", -1, Ptr, &wOutput, "int", nSize)
		VarSetCapacity(wOutput, -1)
		if !VarSetCapacity(wOutput)
			return -4
		E := DllCall("gdiplus\GdipSaveImageToFile", Ptr, pBitmap, Ptr, &wOutput, Ptr, pCodec, "uint", p ? p : 0)
	}
	else
		E := DllCall("gdiplus\GdipSaveImageToFile", Ptr, pBitmap, Ptr, &sOutput, Ptr, pCodec, "uint", p ? p : 0)
	return E ? -5 : 0
}

;#####################################################################################

; Function				Gdip_GetPixel
; Description			Gets the ARGB of a pixel in a bitmap
;
; pBitmap				Pointer to a bitmap
; x						x-coordinate of the pixel
; y						y-coordinate of the pixel
;
; return				Returns the ARGB value of the pixel

Gdip_GetPixel(pBitmap, x, y)
{
	DllCall("gdiplus\GdipBitmapGetPixel", A_PtrSize ? "UPtr" : "UInt", pBitmap, "int", x, "int", y, "uint*", ARGB)
	return ARGB
}

;#####################################################################################

; Function				Gdip_SetPixel
; Description			Sets the ARGB of a pixel in a bitmap
;
; pBitmap				Pointer to a bitmap
; x						x-coordinate of the pixel
; y						y-coordinate of the pixel
;
; return				status enumeration. 0 = success

Gdip_SetPixel(pBitmap, x, y, ARGB)
{
   return DllCall("gdiplus\GdipBitmapSetPixel", A_PtrSize ? "UPtr" : "UInt", pBitmap, "int", x, "int", y, "int", ARGB)
}

;#####################################################################################

; Function				Gdip_GetImageWidth
; Description			Gives the width of a bitmap
;
; pBitmap				Pointer to a bitmap
;
; return				Returns the width in pixels of the supplied bitmap

Gdip_GetImageWidth(pBitmap)
{
   DllCall("gdiplus\GdipGetImageWidth", A_PtrSize ? "UPtr" : "UInt", pBitmap, "uint*", Width)
   return Width
}

;#####################################################################################

; Function				Gdip_GetImageHeight
; Description			Gives the height of a bitmap
;
; pBitmap				Pointer to a bitmap
;
; return				Returns the height in pixels of the supplied bitmap

Gdip_GetImageHeight(pBitmap)
{
   DllCall("gdiplus\GdipGetImageHeight", A_PtrSize ? "UPtr" : "UInt", pBitmap, "uint*", Height)
   return Height
}

;#####################################################################################

; Function				Gdip_GetDimensions
; Description			Gives the width and height of a bitmap
;
; pBitmap				Pointer to a bitmap
; Width					ByRef variable. This variable will be set to the width of the bitmap
; Height				ByRef variable. This variable will be set to the height of the bitmap
;
; return				No return value
;						Gdip_GetDimensions(pBitmap, ThisWidth, ThisHeight) will set ThisWidth to the width and ThisHeight to the height

Gdip_GetImageDimensions(pBitmap, ByRef Width, ByRef Height)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	DllCall("gdiplus\GdipGetImageWidth", Ptr, pBitmap, "uint*", Width)
	DllCall("gdiplus\GdipGetImageHeight", Ptr, pBitmap, "uint*", Height)
}

;#####################################################################################

Gdip_GetDimensions(pBitmap, ByRef Width, ByRef Height)
{
	Gdip_GetImageDimensions(pBitmap, Width, Height)
}

;#####################################################################################

Gdip_GetImagePixelFormat(pBitmap)
{
	DllCall("gdiplus\GdipGetImagePixelFormat", A_PtrSize ? "UPtr" : "UInt", pBitmap, A_PtrSize ? "UPtr*" : "UInt*", Format)
	return Format
}

;#####################################################################################

; Function				Gdip_GetDpiX
; Description			Gives the horizontal dots per inch of the graphics of a bitmap
;
; pBitmap				Pointer to a bitmap
; Width					ByRef variable. This variable will be set to the width of the bitmap
; Height				ByRef variable. This variable will be set to the height of the bitmap
;
; return				No return value
;						Gdip_GetDimensions(pBitmap, ThisWidth, ThisHeight) will set ThisWidth to the width and ThisHeight to the height

Gdip_GetDpiX(pGraphics)
{
	DllCall("gdiplus\GdipGetDpiX", A_PtrSize ? "UPtr" : "uint", pGraphics, "float*", dpix)
	return Round(dpix)
}

;#####################################################################################

Gdip_GetDpiY(pGraphics)
{
	DllCall("gdiplus\GdipGetDpiY", A_PtrSize ? "UPtr" : "uint", pGraphics, "float*", dpiy)
	return Round(dpiy)
}

;#####################################################################################

Gdip_GetImageHorizontalResolution(pBitmap)
{
	DllCall("gdiplus\GdipGetImageHorizontalResolution", A_PtrSize ? "UPtr" : "uint", pBitmap, "float*", dpix)
	return Round(dpix)
}

;#####################################################################################

Gdip_GetImageVerticalResolution(pBitmap)
{
	DllCall("gdiplus\GdipGetImageVerticalResolution", A_PtrSize ? "UPtr" : "uint", pBitmap, "float*", dpiy)
	return Round(dpiy)
}

;#####################################################################################

Gdip_BitmapSetResolution(pBitmap, dpix, dpiy)
{
	return DllCall("gdiplus\GdipBitmapSetResolution", A_PtrSize ? "UPtr" : "uint", pBitmap, "float", dpix, "float", dpiy)
}

;#####################################################################################

Gdip_CreateBitmapFromFile(sFile, IconNumber=1, IconSize="")
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	, PtrA := A_PtrSize ? "UPtr*" : "UInt*"
	
	SplitPath, sFile,,, ext
	if ext in exe,dll
	{
		Sizes := IconSize ? IconSize : 256 "|" 128 "|" 64 "|" 48 "|" 32 "|" 16
		BufSize := 16 + (2*(A_PtrSize ? A_PtrSize : 4))
		
		VarSetCapacity(buf, BufSize, 0)
		Loop, Parse, Sizes, |
		{
			DllCall("PrivateExtractIcons", "str", sFile, "int", IconNumber-1, "int", A_LoopField, "int", A_LoopField, PtrA, hIcon, PtrA, 0, "uint", 1, "uint", 0)
			
			if !hIcon
				continue

			if !DllCall("GetIconInfo", Ptr, hIcon, Ptr, &buf)
			{
				DestroyIcon(hIcon)
				continue
			}
			
			hbmMask  := NumGet(buf, 12 + ((A_PtrSize ? A_PtrSize : 4) - 4))
			hbmColor := NumGet(buf, 12 + ((A_PtrSize ? A_PtrSize : 4) - 4) + (A_PtrSize ? A_PtrSize : 4))
			if !(hbmColor && DllCall("GetObject", Ptr, hbmColor, "int", BufSize, Ptr, &buf))
			{
				DestroyIcon(hIcon)
				continue
			}
			break
		}
		if !hIcon
			return -1

		Width := NumGet(buf, 4, "int"), Height := NumGet(buf, 8, "int")
		hbm := CreateDIBSection(Width, -Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
		if !DllCall("DrawIconEx", Ptr, hdc, "int", 0, "int", 0, Ptr, hIcon, "uint", Width, "uint", Height, "uint", 0, Ptr, 0, "uint", 3)
		{
			DestroyIcon(hIcon)
			return -2
		}
		
		VarSetCapacity(dib, 104)
		DllCall("GetObject", Ptr, hbm, "int", A_PtrSize = 8 ? 104 : 84, Ptr, &dib) ; sizeof(DIBSECTION) = 76+2*(A_PtrSize=8?4:0)+2*A_PtrSize
		Stride := NumGet(dib, 12, "Int"), Bits := NumGet(dib, 20 + (A_PtrSize = 8 ? 4 : 0)) ; padding
		DllCall("gdiplus\GdipCreateBitmapFromScan0", "int", Width, "int", Height, "int", Stride, "int", 0x26200A, Ptr, Bits, PtrA, pBitmapOld)
		pBitmap := Gdip_CreateBitmap(Width, Height)
		G := Gdip_GraphicsFromImage(pBitmap)
		, Gdip_DrawImage(G, pBitmapOld, 0, 0, Width, Height, 0, 0, Width, Height)
		SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
		Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmapOld)
		DestroyIcon(hIcon)
	}
	else
	{
		if (!A_IsUnicode)
		{
			VarSetCapacity(wFile, 1024)
			DllCall("kernel32\MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sFile, "int", -1, Ptr, &wFile, "int", 512)
			DllCall("gdiplus\GdipCreateBitmapFromFile", Ptr, &wFile, PtrA, pBitmap)
		}
		else
			DllCall("gdiplus\GdipCreateBitmapFromFile", Ptr, &sFile, PtrA, pBitmap)
	}
	
	return pBitmap
}

;#####################################################################################

Gdip_CreateBitmapFromHBITMAP(hBitmap, Palette=0)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", Ptr, hBitmap, Ptr, Palette, A_PtrSize ? "UPtr*" : "uint*", pBitmap)
	return pBitmap
}

;#####################################################################################

Gdip_CreateHBITMAPFromBitmap(pBitmap, Background=0xffffffff)
{
	DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", A_PtrSize ? "UPtr" : "UInt", pBitmap, A_PtrSize ? "UPtr*" : "uint*", hbm, "int", Background)
	return hbm
}

;#####################################################################################

Gdip_CreateBitmapFromHICON(hIcon)
{
	DllCall("gdiplus\GdipCreateBitmapFromHICON", A_PtrSize ? "UPtr" : "UInt", hIcon, A_PtrSize ? "UPtr*" : "uint*", pBitmap)
	return pBitmap
}

;#####################################################################################

Gdip_CreateHICONFromBitmap(pBitmap)
{
	DllCall("gdiplus\GdipCreateHICONFromBitmap", A_PtrSize ? "UPtr" : "UInt", pBitmap, A_PtrSize ? "UPtr*" : "uint*", hIcon)
	return hIcon
}

;#####################################################################################

Gdip_CreateBitmap(Width, Height, Format=0x26200A)
{
    DllCall("gdiplus\GdipCreateBitmapFromScan0", "int", Width, "int", Height, "int", 0, "int", Format, A_PtrSize ? "UPtr" : "UInt", 0, A_PtrSize ? "UPtr*" : "uint*", pBitmap)
    Return pBitmap
}

;#####################################################################################

Gdip_CreateBitmapFromClipboard()
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	if !DllCall("OpenClipboard", Ptr, 0)
		return -1
	if !DllCall("IsClipboardFormatAvailable", "uint", 8)
		return -2
	if !hBitmap := DllCall("GetClipboardData", "uint", 2, Ptr)
		return -3
	if !pBitmap := Gdip_CreateBitmapFromHBITMAP(hBitmap)
		return -4
	if !DllCall("CloseClipboard")
		return -5
	DeleteObject(hBitmap)
	return pBitmap
}

;#####################################################################################

Gdip_SetBitmapToClipboard(pBitmap)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	off1 := A_PtrSize = 8 ? 52 : 44, off2 := A_PtrSize = 8 ? 32 : 24
	hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
	DllCall("GetObject", Ptr, hBitmap, "int", VarSetCapacity(oi, A_PtrSize = 8 ? 104 : 84, 0), Ptr, &oi)
	hdib := DllCall("GlobalAlloc", "uint", 2, Ptr, 40+NumGet(oi, off1, "UInt"), Ptr)
	pdib := DllCall("GlobalLock", Ptr, hdib, Ptr)
	DllCall("RtlMoveMemory", Ptr, pdib, Ptr, &oi+off2, Ptr, 40)
	DllCall("RtlMoveMemory", Ptr, pdib+40, Ptr, NumGet(oi, off2 - (A_PtrSize ? A_PtrSize : 4), Ptr), Ptr, NumGet(oi, off1, "UInt"))
	DllCall("GlobalUnlock", Ptr, hdib)
	DllCall("DeleteObject", Ptr, hBitmap)
	DllCall("OpenClipboard", Ptr, 0)
	DllCall("EmptyClipboard")
	DllCall("SetClipboardData", "uint", 8, Ptr, hdib)
	DllCall("CloseClipboard")
}

;#####################################################################################

Gdip_CloneBitmapArea(pBitmap, x, y, w, h, Format=0x26200A)
{
	DllCall("gdiplus\GdipCloneBitmapArea"
					, "float", x
					, "float", y
					, "float", w
					, "float", h
					, "int", Format
					, A_PtrSize ? "UPtr" : "UInt", pBitmap
					, A_PtrSize ? "UPtr*" : "UInt*", pBitmapDest)
	return pBitmapDest
}

;#####################################################################################
; Create resources
;#####################################################################################

Gdip_CreatePen(ARGB, w)
{
   DllCall("gdiplus\GdipCreatePen1", "UInt", ARGB, "float", w, "int", 2, A_PtrSize ? "UPtr*" : "UInt*", pPen)
   return pPen
}

;#####################################################################################

Gdip_CreatePenFromBrush(pBrush, w)
{
	DllCall("gdiplus\GdipCreatePen2", A_PtrSize ? "UPtr" : "UInt", pBrush, "float", w, "int", 2, A_PtrSize ? "UPtr*" : "UInt*", pPen)
	return pPen
}

;#####################################################################################

Gdip_BrushCreateSolid(ARGB=0xff000000)
{
	DllCall("gdiplus\GdipCreateSolidFill", "UInt", ARGB, A_PtrSize ? "UPtr*" : "UInt*", pBrush)
	return pBrush
}

;#####################################################################################

; HatchStyleHorizontal = 0
; HatchStyleVertical = 1
; HatchStyleForwardDiagonal = 2
; HatchStyleBackwardDiagonal = 3
; HatchStyleCross = 4
; HatchStyleDiagonalCross = 5
; HatchStyle05Percent = 6
; HatchStyle10Percent = 7
; HatchStyle20Percent = 8
; HatchStyle25Percent = 9
; HatchStyle30Percent = 10
; HatchStyle40Percent = 11
; HatchStyle50Percent = 12
; HatchStyle60Percent = 13
; HatchStyle70Percent = 14
; HatchStyle75Percent = 15
; HatchStyle80Percent = 16
; HatchStyle90Percent = 17
; HatchStyleLightDownwardDiagonal = 18
; HatchStyleLightUpwardDiagonal = 19
; HatchStyleDarkDownwardDiagonal = 20
; HatchStyleDarkUpwardDiagonal = 21
; HatchStyleWideDownwardDiagonal = 22
; HatchStyleWideUpwardDiagonal = 23
; HatchStyleLightVertical = 24
; HatchStyleLightHorizontal = 25
; HatchStyleNarrowVertical = 26
; HatchStyleNarrowHorizontal = 27
; HatchStyleDarkVertical = 28
; HatchStyleDarkHorizontal = 29
; HatchStyleDashedDownwardDiagonal = 30
; HatchStyleDashedUpwardDiagonal = 31
; HatchStyleDashedHorizontal = 32
; HatchStyleDashedVertical = 33
; HatchStyleSmallConfetti = 34
; HatchStyleLargeConfetti = 35
; HatchStyleZigZag = 36
; HatchStyleWave = 37
; HatchStyleDiagonalBrick = 38
; HatchStyleHorizontalBrick = 39
; HatchStyleWeave = 40
; HatchStylePlaid = 41
; HatchStyleDivot = 42
; HatchStyleDottedGrid = 43
; HatchStyleDottedDiamond = 44
; HatchStyleShingle = 45
; HatchStyleTrellis = 46
; HatchStyleSphere = 47
; HatchStyleSmallGrid = 48
; HatchStyleSmallCheckerBoard = 49
; HatchStyleLargeCheckerBoard = 50
; HatchStyleOutlinedDiamond = 51
; HatchStyleSolidDiamond = 52
; HatchStyleTotal = 53
Gdip_BrushCreateHatch(ARGBfront, ARGBback, HatchStyle=0)
{
	DllCall("gdiplus\GdipCreateHatchBrush", "int", HatchStyle, "UInt", ARGBfront, "UInt", ARGBback, A_PtrSize ? "UPtr*" : "UInt*", pBrush)
	return pBrush
}

;#####################################################################################

Gdip_CreateTextureBrush(pBitmap, WrapMode=1, x=0, y=0, w="", h="")
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	, PtrA := A_PtrSize ? "UPtr*" : "UInt*"
	
	if !(w && h)
		DllCall("gdiplus\GdipCreateTexture", Ptr, pBitmap, "int", WrapMode, PtrA, pBrush)
	else
		DllCall("gdiplus\GdipCreateTexture2", Ptr, pBitmap, "int", WrapMode, "float", x, "float", y, "float", w, "float", h, PtrA, pBrush)
	return pBrush
}

;#####################################################################################

; WrapModeTile = 0
; WrapModeTileFlipX = 1
; WrapModeTileFlipY = 2
; WrapModeTileFlipXY = 3
; WrapModeClamp = 4
Gdip_CreateLineBrush(x1, y1, x2, y2, ARGB1, ARGB2, WrapMode=1)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	CreatePointF(PointF1, x1, y1), CreatePointF(PointF2, x2, y2)
	DllCall("gdiplus\GdipCreateLineBrush", Ptr, &PointF1, Ptr, &PointF2, "Uint", ARGB1, "Uint", ARGB2, "int", WrapMode, A_PtrSize ? "UPtr*" : "UInt*", LGpBrush)
	return LGpBrush
}

;#####################################################################################

; LinearGradientModeHorizontal = 0
; LinearGradientModeVertical = 1
; LinearGradientModeForwardDiagonal = 2
; LinearGradientModeBackwardDiagonal = 3
Gdip_CreateLineBrushFromRect(x, y, w, h, ARGB1, ARGB2, LinearGradientMode=1, WrapMode=1)
{
	CreateRectF(RectF, x, y, w, h)
	DllCall("gdiplus\GdipCreateLineBrushFromRect", A_PtrSize ? "UPtr" : "UInt", &RectF, "int", ARGB1, "int", ARGB2, "int", LinearGradientMode, "int", WrapMode, A_PtrSize ? "UPtr*" : "UInt*", LGpBrush)
	return LGpBrush
}

;#####################################################################################

Gdip_CloneBrush(pBrush)
{
	DllCall("gdiplus\GdipCloneBrush", A_PtrSize ? "UPtr" : "UInt", pBrush, A_PtrSize ? "UPtr*" : "UInt*", pBrushClone)
	return pBrushClone
}

;#####################################################################################
; Delete resources
;#####################################################################################

Gdip_DeletePen(pPen)
{
   return DllCall("gdiplus\GdipDeletePen", A_PtrSize ? "UPtr" : "UInt", pPen)
}

;#####################################################################################

Gdip_DeleteBrush(pBrush)
{
   return DllCall("gdiplus\GdipDeleteBrush", A_PtrSize ? "UPtr" : "UInt", pBrush)
}

;#####################################################################################

Gdip_DisposeImage(pBitmap)
{
   return DllCall("gdiplus\GdipDisposeImage", A_PtrSize ? "UPtr" : "UInt", pBitmap)
}

;#####################################################################################

Gdip_DeleteGraphics(pGraphics)
{
   return DllCall("gdiplus\GdipDeleteGraphics", A_PtrSize ? "UPtr" : "UInt", pGraphics)
}

;#####################################################################################

Gdip_DisposeImageAttributes(ImageAttr)
{
	return DllCall("gdiplus\GdipDisposeImageAttributes", A_PtrSize ? "UPtr" : "UInt", ImageAttr)
}

;#####################################################################################

Gdip_DeleteFont(hFont)
{
   return DllCall("gdiplus\GdipDeleteFont", A_PtrSize ? "UPtr" : "UInt", hFont)
}

;#####################################################################################

Gdip_DeleteStringFormat(hFormat)
{
   return DllCall("gdiplus\GdipDeleteStringFormat", A_PtrSize ? "UPtr" : "UInt", hFormat)
}

;#####################################################################################

Gdip_DeleteFontFamily(hFamily)
{
   return DllCall("gdiplus\GdipDeleteFontFamily", A_PtrSize ? "UPtr" : "UInt", hFamily)
}

;#####################################################################################

Gdip_DeleteMatrix(Matrix)
{
   return DllCall("gdiplus\GdipDeleteMatrix", A_PtrSize ? "UPtr" : "UInt", Matrix)
}

;#####################################################################################
; Text functions
;#####################################################################################

Gdip_TextToGraphics(pGraphics, Text, Options, Font="Arial", Width="", Height="", Measure=0)
{
	IWidth := Width, IHeight:= Height
	
	RegExMatch(Options, "i)X([\-\d\.]+)(p*)", xpos)
	RegExMatch(Options, "i)Y([\-\d\.]+)(p*)", ypos)
	RegExMatch(Options, "i)W([\-\d\.]+)(p*)", Width)
	RegExMatch(Options, "i)H([\-\d\.]+)(p*)", Height)
	RegExMatch(Options, "i)C(?!(entre|enter))([a-f\d]+)", Colour)
	RegExMatch(Options, "i)Top|Up|Bottom|Down|vCentre|vCenter", vPos)
	RegExMatch(Options, "i)NoWrap", NoWrap)
	RegExMatch(Options, "i)R(\d)", Rendering)
	RegExMatch(Options, "i)S(\d+)(p*)", Size)

	if !Gdip_DeleteBrush(Gdip_CloneBrush(Colour2))
		PassBrush := 1, pBrush := Colour2
	
	if !(IWidth && IHeight) && (xpos2 || ypos2 || Width2 || Height2 || Size2)
		return -1

	Style := 0, Styles := "Regular|Bold|Italic|BoldItalic|Underline|Strikeout"
	Loop, Parse, Styles, |
	{
		if RegExMatch(Options, "\b" A_loopField)
		Style |= (A_LoopField != "StrikeOut") ? (A_Index-1) : 8
	}
  
	Align := 0, Alignments := "Near|Left|Centre|Center|Far|Right"
	Loop, Parse, Alignments, |
	{
		if RegExMatch(Options, "\b" A_loopField)
			Align |= A_Index//2.1      ; 0|0|1|1|2|2
	}

	xpos := (xpos1 != "") ? xpos2 ? IWidth*(xpos1/100) : xpos1 : 0
	ypos := (ypos1 != "") ? ypos2 ? IHeight*(ypos1/100) : ypos1 : 0
	Width := Width1 ? Width2 ? IWidth*(Width1/100) : Width1 : IWidth
	Height := Height1 ? Height2 ? IHeight*(Height1/100) : Height1 : IHeight
	if !PassBrush
		Colour := "0x" (Colour2 ? Colour2 : "ff000000")
	Rendering := ((Rendering1 >= 0) && (Rendering1 <= 5)) ? Rendering1 : 4
	Size := (Size1 > 0) ? Size2 ? IHeight*(Size1/100) : Size1 : 12

	hFamily := Gdip_FontFamilyCreate(Font)
	hFont := Gdip_FontCreate(hFamily, Size, Style)
	FormatStyle := NoWrap ? 0x4000 | 0x1000 : 0x4000
	hFormat := Gdip_StringFormatCreate(FormatStyle)
	pBrush := PassBrush ? pBrush : Gdip_BrushCreateSolid(Colour)
	if !(hFamily && hFont && hFormat && pBrush && pGraphics)
		return !pGraphics ? -2 : !hFamily ? -3 : !hFont ? -4 : !hFormat ? -5 : !pBrush ? -6 : 0
   
	CreateRectF(RC, xpos, ypos, Width, Height)
	Gdip_SetStringFormatAlign(hFormat, Align)
	Gdip_SetTextRenderingHint(pGraphics, Rendering)
	ReturnRC := Gdip_MeasureString(pGraphics, Text, hFont, hFormat, RC)

	if vPos
	{
		StringSplit, ReturnRC, ReturnRC, |
		
		if (vPos = "vCentre") || (vPos = "vCenter")
			ypos += (Height-ReturnRC4)//2
		else if (vPos = "Top") || (vPos = "Up")
			ypos := 0
		else if (vPos = "Bottom") || (vPos = "Down")
			ypos := Height-ReturnRC4
		
		CreateRectF(RC, xpos, ypos, Width, ReturnRC4)
		ReturnRC := Gdip_MeasureString(pGraphics, Text, hFont, hFormat, RC)
	}

	if !Measure
		E := Gdip_DrawString(pGraphics, Text, hFont, hFormat, pBrush, RC)

	if !PassBrush
		Gdip_DeleteBrush(pBrush)
	Gdip_DeleteStringFormat(hFormat)   
	Gdip_DeleteFont(hFont)
	Gdip_DeleteFontFamily(hFamily)
	return E ? E : ReturnRC
}

;#####################################################################################

Gdip_DrawString(pGraphics, sString, hFont, hFormat, pBrush, ByRef RectF)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	if (!A_IsUnicode)
	{
		nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sString, "int", -1, Ptr, 0, "int", 0)
		VarSetCapacity(wString, nSize*2)
		DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sString, "int", -1, Ptr, &wString, "int", nSize)
	}
	
	return DllCall("gdiplus\GdipDrawString"
					, Ptr, pGraphics
					, Ptr, A_IsUnicode ? &sString : &wString
					, "int", -1
					, Ptr, hFont
					, Ptr, &RectF
					, Ptr, hFormat
					, Ptr, pBrush)
}

;#####################################################################################

Gdip_MeasureString(pGraphics, sString, hFont, hFormat, ByRef RectF)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	VarSetCapacity(RC, 16)
	if !A_IsUnicode
	{
		nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sString, "int", -1, "uint", 0, "int", 0)
		VarSetCapacity(wString, nSize*2)   
		DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sString, "int", -1, Ptr, &wString, "int", nSize)
	}
	
	DllCall("gdiplus\GdipMeasureString"
					, Ptr, pGraphics
					, Ptr, A_IsUnicode ? &sString : &wString
					, "int", -1
					, Ptr, hFont
					, Ptr, &RectF
					, Ptr, hFormat
					, Ptr, &RC
					, "uint*", Chars
					, "uint*", Lines)
	
	return &RC ? NumGet(RC, 0, "float") "|" NumGet(RC, 4, "float") "|" NumGet(RC, 8, "float") "|" NumGet(RC, 12, "float") "|" Chars "|" Lines : 0
}

; Near = 0
; Center = 1
; Far = 2
Gdip_SetStringFormatAlign(hFormat, Align)
{
   return DllCall("gdiplus\GdipSetStringFormatAlign", A_PtrSize ? "UPtr" : "UInt", hFormat, "int", Align)
}

; StringFormatFlagsDirectionRightToLeft    = 0x00000001
; StringFormatFlagsDirectionVertical       = 0x00000002
; StringFormatFlagsNoFitBlackBox           = 0x00000004
; StringFormatFlagsDisplayFormatControl    = 0x00000020
; StringFormatFlagsNoFontFallback          = 0x00000400
; StringFormatFlagsMeasureTrailingSpaces   = 0x00000800
; StringFormatFlagsNoWrap                  = 0x00001000
; StringFormatFlagsLineLimit               = 0x00002000
; StringFormatFlagsNoClip                  = 0x00004000 
Gdip_StringFormatCreate(Format=0, Lang=0)
{
   DllCall("gdiplus\GdipCreateStringFormat", "int", Format, "int", Lang, A_PtrSize ? "UPtr*" : "UInt*", hFormat)
   return hFormat
}

; Regular = 0
; Bold = 1
; Italic = 2
; BoldItalic = 3
; Underline = 4
; Strikeout = 8
Gdip_FontCreate(hFamily, Size, Style=0)
{
   DllCall("gdiplus\GdipCreateFont", A_PtrSize ? "UPtr" : "UInt", hFamily, "float", Size, "int", Style, "int", 0, A_PtrSize ? "UPtr*" : "UInt*", hFont)
   return hFont
}

Gdip_FontFamilyCreate(Font)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	if (!A_IsUnicode)
	{
		nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &Font, "int", -1, "uint", 0, "int", 0)
		VarSetCapacity(wFont, nSize*2)
		DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &Font, "int", -1, Ptr, &wFont, "int", nSize)
	}
	
	DllCall("gdiplus\GdipCreateFontFamilyFromName"
					, Ptr, A_IsUnicode ? &Font : &wFont
					, "uint", 0
					, A_PtrSize ? "UPtr*" : "UInt*", hFamily)
	
	return hFamily
}

;#####################################################################################
; Matrix functions
;#####################################################################################

Gdip_CreateAffineMatrix(m11, m12, m21, m22, x, y)
{
   DllCall("gdiplus\GdipCreateMatrix2", "float", m11, "float", m12, "float", m21, "float", m22, "float", x, "float", y, A_PtrSize ? "UPtr*" : "UInt*", Matrix)
   return Matrix
}

Gdip_CreateMatrix()
{
   DllCall("gdiplus\GdipCreateMatrix", A_PtrSize ? "UPtr*" : "UInt*", Matrix)
   return Matrix
}

;#####################################################################################
; GraphicsPath functions
;#####################################################################################

; Alternate = 0
; Winding = 1
Gdip_CreatePath(BrushMode=0)
{
	DllCall("gdiplus\GdipCreatePath", "int", BrushMode, A_PtrSize ? "UPtr*" : "UInt*", Path)
	return Path
}

Gdip_AddPathEllipse(Path, x, y, w, h)
{
	return DllCall("gdiplus\GdipAddPathEllipse", A_PtrSize ? "UPtr" : "UInt", Path, "float", x, "float", y, "float", w, "float", h)
}

Gdip_AddPathPolygon(Path, Points)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	StringSplit, Points, Points, |
	VarSetCapacity(PointF, 8*Points0)   
	Loop, %Points0%
	{
		StringSplit, Coord, Points%A_Index%, `,
		NumPut(Coord1, PointF, 8*(A_Index-1), "float"), NumPut(Coord2, PointF, (8*(A_Index-1))+4, "float")
	}   

	return DllCall("gdiplus\GdipAddPathPolygon", Ptr, Path, Ptr, &PointF, "int", Points0)
}

Gdip_DeletePath(Path)
{
	return DllCall("gdiplus\GdipDeletePath", A_PtrSize ? "UPtr" : "UInt", Path)
}

;#####################################################################################
; Quality functions
;#####################################################################################

; SystemDefault = 0
; SingleBitPerPixelGridFit = 1
; SingleBitPerPixel = 2
; AntiAliasGridFit = 3
; AntiAlias = 4
Gdip_SetTextRenderingHint(pGraphics, RenderingHint)
{
	return DllCall("gdiplus\GdipSetTextRenderingHint", A_PtrSize ? "UPtr" : "UInt", pGraphics, "int", RenderingHint)
}

; Default = 0
; LowQuality = 1
; HighQuality = 2
; Bilinear = 3
; Bicubic = 4
; NearestNeighbor = 5
; HighQualityBilinear = 6
; HighQualityBicubic = 7
Gdip_SetInterpolationMode(pGraphics, InterpolationMode)
{
   return DllCall("gdiplus\GdipSetInterpolationMode", A_PtrSize ? "UPtr" : "UInt", pGraphics, "int", InterpolationMode)
}

; Default = 0
; HighSpeed = 1
; HighQuality = 2
; None = 3
; AntiAlias = 4
Gdip_SetSmoothingMode(pGraphics, SmoothingMode)
{
   return DllCall("gdiplus\GdipSetSmoothingMode", A_PtrSize ? "UPtr" : "UInt", pGraphics, "int", SmoothingMode)
}

; CompositingModeSourceOver = 0 (blended)
; CompositingModeSourceCopy = 1 (overwrite)
Gdip_SetCompositingMode(pGraphics, CompositingMode=0)
{
   return DllCall("gdiplus\GdipSetCompositingMode", A_PtrSize ? "UPtr" : "UInt", pGraphics, "int", CompositingMode)
}

;#####################################################################################
; Extra functions
;#####################################################################################

Gdip_Startup()
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	if !DllCall("GetModuleHandle", "str", "gdiplus", Ptr)
		DllCall("LoadLibrary", "str", "gdiplus")
	VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
	DllCall("gdiplus\GdiplusStartup", A_PtrSize ? "UPtr*" : "uint*", pToken, Ptr, &si, Ptr, 0)
	return pToken
}

Gdip_Shutdown(pToken)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	DllCall("gdiplus\GdiplusShutdown", Ptr, pToken)
	if hModule := DllCall("GetModuleHandle", "str", "gdiplus", Ptr)
		DllCall("FreeLibrary", Ptr, hModule)
	return 0
}

; Prepend = 0; The new operation is applied before the old operation.
; Append = 1; The new operation is applied after the old operation.
Gdip_RotateWorldTransform(pGraphics, Angle, MatrixOrder=0)
{
	return DllCall("gdiplus\GdipRotateWorldTransform", A_PtrSize ? "UPtr" : "UInt", pGraphics, "float", Angle, "int", MatrixOrder)
}

Gdip_ScaleWorldTransform(pGraphics, x, y, MatrixOrder=0)
{
	return DllCall("gdiplus\GdipScaleWorldTransform", A_PtrSize ? "UPtr" : "UInt", pGraphics, "float", x, "float", y, "int", MatrixOrder)
}

Gdip_TranslateWorldTransform(pGraphics, x, y, MatrixOrder=0)
{
	return DllCall("gdiplus\GdipTranslateWorldTransform", A_PtrSize ? "UPtr" : "UInt", pGraphics, "float", x, "float", y, "int", MatrixOrder)
}

Gdip_ResetWorldTransform(pGraphics)
{
	return DllCall("gdiplus\GdipResetWorldTransform", A_PtrSize ? "UPtr" : "UInt", pGraphics)
}

Gdip_GetRotatedTranslation(Width, Height, Angle, ByRef xTranslation, ByRef yTranslation)
{
	pi := 3.14159, TAngle := Angle*(pi/180)	

	Bound := (Angle >= 0) ? Mod(Angle, 360) : 360-Mod(-Angle, -360)
	if ((Bound >= 0) && (Bound <= 90))
		xTranslation := Height*Sin(TAngle), yTranslation := 0
	else if ((Bound > 90) && (Bound <= 180))
		xTranslation := (Height*Sin(TAngle))-(Width*Cos(TAngle)), yTranslation := -Height*Cos(TAngle)
	else if ((Bound > 180) && (Bound <= 270))
		xTranslation := -(Width*Cos(TAngle)), yTranslation := -(Height*Cos(TAngle))-(Width*Sin(TAngle))
	else if ((Bound > 270) && (Bound <= 360))
		xTranslation := 0, yTranslation := -Width*Sin(TAngle)
}

Gdip_GetRotatedDimensions(Width, Height, Angle, ByRef RWidth, ByRef RHeight)
{
	pi := 3.14159, TAngle := Angle*(pi/180)
	if !(Width && Height)
		return -1
	RWidth := Ceil(Abs(Width*Cos(TAngle))+Abs(Height*Sin(TAngle)))
	RHeight := Ceil(Abs(Width*Sin(TAngle))+Abs(Height*Cos(Tangle)))
}

; RotateNoneFlipNone   = 0
; Rotate90FlipNone     = 1
; Rotate180FlipNone    = 2
; Rotate270FlipNone    = 3
; RotateNoneFlipX      = 4
; Rotate90FlipX        = 5
; Rotate180FlipX       = 6
; Rotate270FlipX       = 7
; RotateNoneFlipY      = Rotate180FlipX
; Rotate90FlipY        = Rotate270FlipX
; Rotate180FlipY       = RotateNoneFlipX
; Rotate270FlipY       = Rotate90FlipX
; RotateNoneFlipXY     = Rotate180FlipNone
; Rotate90FlipXY       = Rotate270FlipNone
; Rotate180FlipXY      = RotateNoneFlipNone
; Rotate270FlipXY      = Rotate90FlipNone 

Gdip_ImageRotateFlip(pBitmap, RotateFlipType=1)
{
	return DllCall("gdiplus\GdipImageRotateFlip", A_PtrSize ? "UPtr" : "UInt", pBitmap, "int", RotateFlipType)
}

; Replace = 0
; Intersect = 1
; Union = 2
; Xor = 3
; Exclude = 4
; Complement = 5
Gdip_SetClipRect(pGraphics, x, y, w, h, CombineMode=0)
{
   return DllCall("gdiplus\GdipSetClipRect",  A_PtrSize ? "UPtr" : "UInt", pGraphics, "float", x, "float", y, "float", w, "float", h, "int", CombineMode)
}

Gdip_SetClipPath(pGraphics, Path, CombineMode=0)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	return DllCall("gdiplus\GdipSetClipPath", Ptr, pGraphics, Ptr, Path, "int", CombineMode)
}

Gdip_ResetClip(pGraphics)
{
   return DllCall("gdiplus\GdipResetClip", A_PtrSize ? "UPtr" : "UInt", pGraphics)
}

Gdip_GetClipRegion(pGraphics)
{
	Region := Gdip_CreateRegion()
	DllCall("gdiplus\GdipGetClip", A_PtrSize ? "UPtr" : "UInt", pGraphics, "UInt*", Region)
	return Region
}

Gdip_SetClipRegion(pGraphics, Region, CombineMode=0)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	return DllCall("gdiplus\GdipSetClipRegion", Ptr, pGraphics, Ptr, Region, "int", CombineMode)
}

Gdip_CreateRegion()
{
	DllCall("gdiplus\GdipCreateRegion", "UInt*", Region)
	return Region
}

Gdip_DeleteRegion(Region)
{
	return DllCall("gdiplus\GdipDeleteRegion", A_PtrSize ? "UPtr" : "UInt", Region)
}

;#####################################################################################
; BitmapLockBits
;#####################################################################################

Gdip_LockBits(pBitmap, x, y, w, h, ByRef Stride, ByRef Scan0, ByRef BitmapData, LockMode = 3, PixelFormat = 0x26200a)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	CreateRect(Rect, x, y, w, h)
	VarSetCapacity(BitmapData, 16+2*(A_PtrSize ? A_PtrSize : 4), 0)
	E := DllCall("Gdiplus\GdipBitmapLockBits", Ptr, pBitmap, Ptr, &Rect, "uint", LockMode, "int", PixelFormat, Ptr, &BitmapData)
	Stride := NumGet(BitmapData, 8, "Int")
	Scan0 := NumGet(BitmapData, 16, Ptr)
	return E
}

;#####################################################################################

Gdip_UnlockBits(pBitmap, ByRef BitmapData)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	return DllCall("Gdiplus\GdipBitmapUnlockBits", Ptr, pBitmap, Ptr, &BitmapData)
}

;#####################################################################################

Gdip_SetLockBitPixel(ARGB, Scan0, x, y, Stride)
{
	Numput(ARGB, Scan0+0, (x*4)+(y*Stride), "UInt")
}

;#####################################################################################

Gdip_GetLockBitPixel(Scan0, x, y, Stride)
{
	return NumGet(Scan0+0, (x*4)+(y*Stride), "UInt")
}

;#####################################################################################

Gdip_PixelateBitmap(pBitmap, ByRef pBitmapOut, BlockSize)
{
	static PixelateBitmap
	
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	
	if (!PixelateBitmap)
	{
		if A_PtrSize != 8 ; x86 machine code
		MCode_PixelateBitmap =
		(LTrim Join
		558BEC83EC3C8B4514538B5D1C99F7FB56578BC88955EC894DD885C90F8E830200008B451099F7FB8365DC008365E000894DC88955F08945E833FF897DD4
		397DE80F8E160100008BCB0FAFCB894DCC33C08945F88945FC89451C8945143BD87E608B45088D50028BC82BCA8BF02BF2418945F48B45E02955F4894DC4
		8D0CB80FAFCB03CA895DD08BD1895DE40FB64416030145140FB60201451C8B45C40FB604100145FC8B45F40FB604020145F883C204FF4DE475D6034D18FF
		4DD075C98B4DCC8B451499F7F98945148B451C99F7F989451C8B45FC99F7F98945FC8B45F899F7F98945F885DB7E648B450C8D50028BC82BCA83C103894D
		C48BC82BCA41894DF48B4DD48945E48B45E02955E48D0C880FAFCB03CA895DD08BD18BF38A45148B7DC48804178A451C8B7DF488028A45FC8804178A45F8
		8B7DE488043A83C2044E75DA034D18FF4DD075CE8B4DCC8B7DD447897DD43B7DE80F8CF2FEFFFF837DF0000F842C01000033C08945F88945FC89451C8945
		148945E43BD87E65837DF0007E578B4DDC034DE48B75E80FAF4D180FAFF38B45088D500203CA8D0CB18BF08BF88945F48B45F02BF22BFA2955F48945CC0F
		B6440E030145140FB60101451C0FB6440F010145FC8B45F40FB604010145F883C104FF4DCC75D8FF45E4395DE47C9B8B4DF00FAFCB85C9740B8B451499F7
		F9894514EB048365140033F63BCE740B8B451C99F7F989451CEB0389751C3BCE740B8B45FC99F7F98945FCEB038975FC3BCE740B8B45F899F7F98945F8EB
		038975F88975E43BDE7E5A837DF0007E4C8B4DDC034DE48B75E80FAF4D180FAFF38B450C8D500203CA8D0CB18BF08BF82BF22BFA2BC28B55F08955CC8A55
		1488540E038A551C88118A55FC88540F018A55F888140183C104FF4DCC75DFFF45E4395DE47CA68B45180145E0015DDCFF4DC80F8594FDFFFF8B451099F7
		FB8955F08945E885C00F8E450100008B45EC0FAFC38365DC008945D48B45E88945CC33C08945F88945FC89451C8945148945103945EC7E6085DB7E518B4D
		D88B45080FAFCB034D108D50020FAF4D18034DDC8BF08BF88945F403CA2BF22BFA2955F4895DC80FB6440E030145140FB60101451C0FB6440F010145FC8B
		45F40FB604080145F883C104FF4DC875D8FF45108B45103B45EC7CA08B4DD485C9740B8B451499F7F9894514EB048365140033F63BCE740B8B451C99F7F9
		89451CEB0389751C3BCE740B8B45FC99F7F98945FCEB038975FC3BCE740B8B45F899F7F98945F8EB038975F88975103975EC7E5585DB7E468B4DD88B450C
		0FAFCB034D108D50020FAF4D18034DDC8BF08BF803CA2BF22BFA2BC2895DC88A551488540E038A551C88118A55FC88540F018A55F888140183C104FF4DC8
		75DFFF45108B45103B45EC7CAB8BC3C1E0020145DCFF4DCC0F85CEFEFFFF8B4DEC33C08945F88945FC89451C8945148945103BC87E6C3945F07E5C8B4DD8
		8B75E80FAFCB034D100FAFF30FAF4D188B45088D500203CA8D0CB18BF08BF88945F48B45F02BF22BFA2955F48945C80FB6440E030145140FB60101451C0F
		B6440F010145FC8B45F40FB604010145F883C104FF4DC875D833C0FF45108B4DEC394D107C940FAF4DF03BC874068B451499F7F933F68945143BCE740B8B
		451C99F7F989451CEB0389751C3BCE740B8B45FC99F7F98945FCEB038975FC3BCE740B8B45F899F7F98945F8EB038975F88975083975EC7E63EB0233F639
		75F07E4F8B4DD88B75E80FAFCB034D080FAFF30FAF4D188B450C8D500203CA8D0CB18BF08BF82BF22BFA2BC28B55F08955108A551488540E038A551C8811
		8A55FC88540F018A55F888140883C104FF4D1075DFFF45088B45083B45EC7C9F5F5E33C05BC9C21800
		)
		else ; x64 machine code
		MCode_PixelateBitmap =
		(LTrim Join
		4489442418488954241048894C24085355565741544155415641574883EC28418BC1448B8C24980000004C8BDA99488BD941F7F9448BD0448BFA8954240C
		448994248800000085C00F8E9D020000418BC04533E4458BF299448924244C8954241041F7F933C9898C24980000008BEA89542404448BE889442408EB05
		4C8B5C24784585ED0F8E1A010000458BF1418BFD48897C2418450FAFF14533D233F633ED4533E44533ED4585C97E5B4C63BC2490000000418D040A410FAF
		C148984C8D441802498BD9498BD04D8BD90FB642010FB64AFF4403E80FB60203E90FB64AFE4883C2044403E003F149FFCB75DE4D03C748FFCB75D0488B7C
		24188B8C24980000004C8B5C2478418BC59941F7FE448BE8418BC49941F7FE448BE08BC59941F7FE8BE88BC69941F7FE8BF04585C97E4048639C24900000
		004103CA4D8BC1410FAFC94863C94A8D541902488BCA498BC144886901448821408869FF408871FE4883C10448FFC875E84803D349FFC875DA8B8C249800
		0000488B5C24704C8B5C24784183C20448FFCF48897C24180F850AFFFFFF8B6C2404448B2424448B6C24084C8B74241085ED0F840A01000033FF33DB4533
		DB4533D24533C04585C97E53488B74247085ED7E42438D0C04418BC50FAF8C2490000000410FAFC18D04814863C8488D5431028BCD0FB642014403D00FB6
		024883C2044403D80FB642FB03D80FB642FA03F848FFC975DE41FFC0453BC17CB28BCD410FAFC985C9740A418BC299F7F98BF0EB0233F685C9740B418BC3
		99F7F9448BD8EB034533DB85C9740A8BC399F7F9448BD0EB034533D285C9740A8BC799F7F9448BC0EB034533C033D24585C97E4D4C8B74247885ED7E3841
		8D0C14418BC50FAF8C2490000000410FAFC18D04814863C84A8D4431028BCD40887001448818448850FF448840FE4883C00448FFC975E8FFC2413BD17CBD
		4C8B7424108B8C2498000000038C2490000000488B5C24704503E149FFCE44892424898C24980000004C897424100F859EFDFFFF448B7C240C448B842480
		000000418BC09941F7F98BE8448BEA89942498000000896C240C85C00F8E3B010000448BAC2488000000418BCF448BF5410FAFC9898C248000000033FF33
		ED33F64533DB4533D24533C04585FF7E524585C97E40418BC5410FAFC14103C00FAF84249000000003C74898488D541802498BD90FB642014403D00FB602
		4883C2044403D80FB642FB03F00FB642FA03E848FFCB75DE488B5C247041FFC0453BC77CAE85C9740B418BC299F7F9448BE0EB034533E485C9740A418BC3
		99F7F98BD8EB0233DB85C9740A8BC699F7F9448BD8EB034533DB85C9740A8BC599F7F9448BD0EB034533D24533C04585FF7E4E488B4C24784585C97E3541
		8BC5410FAFC14103C00FAF84249000000003C74898488D540802498BC144886201881A44885AFF448852FE4883C20448FFC875E941FFC0453BC77CBE8B8C
		2480000000488B5C2470418BC1C1E00203F849FFCE0F85ECFEFFFF448BAC24980000008B6C240C448BA4248800000033FF33DB4533DB4533D24533C04585
		FF7E5A488B7424704585ED7E48418BCC8BC5410FAFC94103C80FAF8C2490000000410FAFC18D04814863C8488D543102418BCD0FB642014403D00FB60248
		83C2044403D80FB642FB03D80FB642FA03F848FFC975DE41FFC0453BC77CAB418BCF410FAFCD85C9740A418BC299F7F98BF0EB0233F685C9740B418BC399
		F7F9448BD8EB034533DB85C9740A8BC399F7F9448BD0EB034533D285C9740A8BC799F7F9448BC0EB034533C033D24585FF7E4E4585ED7E42418BCC8BC541
		0FAFC903CA0FAF8C2490000000410FAFC18D04814863C8488B442478488D440102418BCD40887001448818448850FF448840FE4883C00448FFC975E8FFC2
		413BD77CB233C04883C428415F415E415D415C5F5E5D5BC3
		)
		
		VarSetCapacity(PixelateBitmap, StrLen(MCode_PixelateBitmap)//2)
		Loop % StrLen(MCode_PixelateBitmap)//2		;%
			NumPut("0x" SubStr(MCode_PixelateBitmap, (2*A_Index)-1, 2), PixelateBitmap, A_Index-1, "UChar")
		DllCall("VirtualProtect", Ptr, &PixelateBitmap, Ptr, VarSetCapacity(PixelateBitmap), "uint", 0x40, A_PtrSize ? "UPtr*" : "UInt*", 0)
	}

	Gdip_GetImageDimensions(pBitmap, Width, Height)
	
	if (Width != Gdip_GetImageWidth(pBitmapOut) || Height != Gdip_GetImageHeight(pBitmapOut))
		return -1
	if (BlockSize > Width || BlockSize > Height)
		return -2

	E1 := Gdip_LockBits(pBitmap, 0, 0, Width, Height, Stride1, Scan01, BitmapData1)
	E2 := Gdip_LockBits(pBitmapOut, 0, 0, Width, Height, Stride2, Scan02, BitmapData2)
	if (E1 || E2)
		return -3

	E := DllCall(&PixelateBitmap, Ptr, Scan01, Ptr, Scan02, "int", Width, "int", Height, "int", Stride1, "int", BlockSize)
	
	Gdip_UnlockBits(pBitmap, BitmapData1), Gdip_UnlockBits(pBitmapOut, BitmapData2)
	return 0
}

;#####################################################################################

Gdip_ToARGB(A, R, G, B)
{
	return (A << 24) | (R << 16) | (G << 8) | B
}

;#####################################################################################

Gdip_FromARGB(ARGB, ByRef A, ByRef R, ByRef G, ByRef B)
{
	A := (0xff000000 & ARGB) >> 24
	R := (0x00ff0000 & ARGB) >> 16
	G := (0x0000ff00 & ARGB) >> 8
	B := 0x000000ff & ARGB
}

;#####################################################################################

Gdip_AFromARGB(ARGB)
{
	return (0xff000000 & ARGB) >> 24
}

;#####################################################################################

Gdip_RFromARGB(ARGB)
{
	return (0x00ff0000 & ARGB) >> 16
}

;#####################################################################################

Gdip_GFromARGB(ARGB)
{
	return (0x0000ff00 & ARGB) >> 8
}

;#####################################################################################

Gdip_BFromARGB(ARGB)
{
	return 0x000000ff & ARGB
}

;#####################################################################################

StrGetB(Address, Length=-1, Encoding=0)
{
	; Flexible parameter handling:
	if Length is not integer
	Encoding := Length,  Length := -1

	; Check for obvious errors.
	if (Address+0 < 1024)
		return

	; Ensure 'Encoding' contains a numeric identifier.
	if Encoding = UTF-16
		Encoding = 1200
	else if Encoding = UTF-8
		Encoding = 65001
	else if SubStr(Encoding,1,2)="CP"
		Encoding := SubStr(Encoding,3)

	if !Encoding ; "" or 0
	{
		; No conversion necessary, but we might not want the whole string.
		if (Length == -1)
			Length := DllCall("lstrlen", "uint", Address)
		VarSetCapacity(String, Length)
		DllCall("lstrcpyn", "str", String, "uint", Address, "int", Length + 1)
	}
	else if Encoding = 1200 ; UTF-16
	{
		char_count := DllCall("WideCharToMultiByte", "uint", 0, "uint", 0x400, "uint", Address, "int", Length, "uint", 0, "uint", 0, "uint", 0, "uint", 0)
		VarSetCapacity(String, char_count)
		DllCall("WideCharToMultiByte", "uint", 0, "uint", 0x400, "uint", Address, "int", Length, "str", String, "int", char_count, "uint", 0, "uint", 0)
	}
	else if Encoding is integer
	{
		; Convert from target encoding to UTF-16 then to the active code page.
		char_count := DllCall("MultiByteToWideChar", "uint", Encoding, "uint", 0, "uint", Address, "int", Length, "uint", 0, "int", 0)
		VarSetCapacity(String, char_count * 2)
		char_count := DllCall("MultiByteToWideChar", "uint", Encoding, "uint", 0, "uint", Address, "int", Length, "uint", &String, "int", char_count * 2)
		String := StrGetB(&String, char_count, 1200)
	}
	
	return String
}
test gif 1.gif
test gif 1.gif (1.63 MiB) Viewed 4367 times
Attachments
test gif 1.gif
test gif 1.gif (830.6 KiB) Viewed 4367 times
Last edited by Hellbent on 25 Nov 2019, 12:24, edited 2 times in total.
User avatar
flyingDman
Posts: 2791
Joined: 29 Sep 2013, 19:01

Re: GDIP Art ?

21 Jun 2019, 21:04

Nice!!!, mesmerizing ....
14.3 & 1.3.7
User avatar
Hellbent
Posts: 2103
Joined: 23 Sep 2017, 13:34

Re: GDIP Art ?

21 Jun 2019, 21:14

flyingDman wrote:
21 Jun 2019, 21:04
Nice!!!, mesmerizing ....
Likewise
red_sun
Posts: 19
Joined: 12 Jul 2019, 05:22

Re: GDIP Art ?

13 Jul 2019, 10:46

but in the same ballpark
:thumbup:

Amazing ( but it gobbles up 27% cpu………………..)

I think I gonna adapt it to get a new frequency analyser interface for the chilltrack player of noname .

Thanks for sharing
robodesign
Posts: 934
Joined: 30 Sep 2017, 03:59
Location: Romania
Contact:

Re: GDIP Art ?

16 Jul 2019, 08:07

@flyingDman can I reuse your code? I'd like to implement it as a welcome image in my image viewer. ^_^

Best regards, Marius.
-------------------------
KeyPress OSD v4: GitHub or forum. (presentation video)
Quick Picto Viewer: GitHub or forum.
AHK GDI+ expanded / compilation library (on GitHub)
My home page.
User avatar
flyingDman
Posts: 2791
Joined: 29 Sep 2013, 19:01

Re: GDIP Art ?

16 Jul 2019, 09:38

@robodesign Be my guest...
14.3 & 1.3.7
User avatar
Onimuru
Posts: 107
Joined: 08 Sep 2018, 18:35
Contact:

Re: GDIP Art ?

21 Jul 2019, 16:04

Man, that is cool! Thanks for sharing. Here's something I made:

Code: Select all

#KeyHistory 0
#NoEnv
#Persistent
#SingleInstance Force

ListLines, Off
Process, Priority, , R
SetBatchLines, -1
SetControlDelay, -1

;Eclipse properties that define the position and proportions of everything else in this script:
{
	vRadius := 150, vDiameter := vRadius*2
	vCx := A_ScreenWidth - vRadius*2.5, vCy := 0
	vSx1 := A_ScreenWidth - vRadius*2.5, vSx2 := vSx1 - vDiameter, vSy1 := vSy2 := vRadius - 40
}

vFocus := WinExist("A")

;Create the Control Gui:
{
	Gui, gControl: New, -Caption +AlwaysOnTop +ToolWindow +OwnDialogs +LastFound +HwndgControl
	WinSet, Transparent, 127.5
	Gui, gControl: Color, 0xFFFFFF
	Gui, gControl: Show, % "x" . vCx - 210 . A_Space . "y" . vRadius*1.5 - 40 . A_Space . "w140 h80 NA", gControl
	;===== Reset ============================================================
	Gui, gControl: Add, Button, x5 y5 w20 h20 gResetSectors, &R
	;===== Sector count ============================================================
	Gui, gControl: Add, Edit, x30 y5 w45 h20 Center Number Limit5
	Gui, gControl: Add, UpDown, Left Range0-500 gCreateSectors vvSectors 0x80
	;===== Multiple ============================================================
	Gui, gControl: Add, Edit, x80 y5 w55 h20 Center Number Limit5 v_vMultiplier1
	Gui, gControl: Add, UpDown, Left Range-1-1 gOffsetEdit v_vMultiplier2 -2
	;===== Color setting ============================================================
	Gui, gControl: Add, DropDownList, x5 y30 w105 h20 r4 gColorSetting vvColorSetting, Solid|Distance Alpha|Distance Color|Oscillate Color
	;===== Cycle ============================================================
	Gui, gControl: Add, Button , x115 y30 w20 h20 gCycle, &C
	;===== Pen width ============================================================
	Gui, gControl: Add, Edit, x5 y55 w30 h20 Left Number +HwndgDefault1
	Gui, gControl: Add, UpDown, Left Wrap Range1-3 +HwndgDefault2 gPenWidth
	Gui, gControl: Add, Edit, x5 y105 w30 h20 Left Number
	Gui, gControl: Add, UpDown, Left Wrap Range1-3 gPenWidth
	;===== AntiAlias ============================================================
	Gui, gControl: Add, Checkbox, x40 y55 w18 h20 Checked +HwndgDefault3 gAntiAlias
	Gui, gControl: Add, Checkbox, x40 y105 w18 h20 Checked gAntiAlias
	;===== NSFW ============================================================
	Gui, gControl: Add, Button, x58 y55 w52 h20 +HwndgDefault4 gNSFW, &NSFW
	Gui, gControl: Add, Button, x58 y105 w52 h20 gNSFW, NSFW
	;===== Help ============================================================
	Gui, gControl: Add, Button, x115 y55 w20 h20 +HwndgDefault5 gHelp, &H
	Gui, gControl: Add, Button, x115 y105 w20 h20 gHelp, &H
	;===== Sine wave ============================================================
	Gui, gControl: Add, Edit, w20 h20 Center Disabled Hidden +HwndgExtended1 v_vFrequency1
	Gui, gControl: Add, Slider, x5 y55 w108 h20 AltSubmit Hidden Buddy2_vFrequency1 Range0-60 Thick10 TickInterval10 +HwndgExtended2 gOffsetEdit v_vFrequency2
	Gui, gControl: Add, Edit, w20 h20 Center Disabled Hidden +HwndgExtended3 v_vPhase1
	Gui, gControl: Add, Slider, x5 y80 w108 h20 AltSubmit Hidden Buddy2_vPhase1 Range0-12 Thick10 TickInterval2 +HwndgExtended4 gOffsetEdit v_vPhase2
}

;Create Canvas1 (a layered window (+E0x80000) that can be drawn on with Gdip):
{
	pToken := Gdip_Startup()
	hbm1 := CreateDIBSection(vRadius*2.5, vRadius*2.5 + 5), hdc1 := CreateCompatibleDC(), obm1 := SelectObject(hdc1, hbm1)
	G1 := Gdip_GraphicsFromHDC(hdc1), Gdip_SetSmoothingMode(G1, 4), Gdip_SetInterpolationMode(G1, 7)

	Gui, gCanvas1: New, -Caption +AlwaysOnTop +ToolWindow +OwnDialogs +HwndgCanvas1 +E0x80000 +E0x20
	Gui, gCanvas1: Show, NA
}

;Click the Reset button to pass on information that would otherwise have to be defined and set everything to default:
ControlClick, Button1, , , , , NA

;Store the PID of this process for use in FreeMemory:
vPID := DllCall("GetCurrentProcessId")

;Hack to register 0-9 and Enter on Edit1 and Edit2:
OnMessage(0x101, "WM_KEYUP")
OnExit, Exit

Return

/*
	===== Hotkeys ================================================================================
*/

~$^s::
	Critical
	SetTitleMatchMode, 2

	If (WinActive(A_ScriptName)) {
		Sleep, 200
		Reload
	}
	Return

$Space::
	KeyWait, Space, T0.5
	If (!ErrorLevel) {
		Send, {Space}
		Return
	}

	GoSub, NSFW
	Return

*$Escape::
	KeyWait, Escape, T1
	If (!ErrorLevel) {
		Send, {Esc}
		Return
	}

	GoSub, Exit
	Return

/*
	===== Lables ================================================================================
*/

;Code by heresy (https://autohotkey.com/board/topic/30042-run-ahk-scripts-with-less-half-or-even-less-memory-usage/) to free memory:
FreeMemory:
	H := DllCall("OpenProcess", "UInt", 0x001F0FFF, "Int", 0, "Int", vPID)

    DllCall("SetProcessWorkingSetSize", "UInt", H, "Int", -1, "Int", -1)
    DllCall("CloseHandle", "Int", H)
	Return

ResetSectors:
	;Toggle vCycle off if its on:
	If (vCycle)
		GoSub, Cycle

	;Trigger the FreeMemory label:
	vFreeMemory := 200

	;Set all the controls (with the exception of vAntiAlias and vHelp) to their default values:
	Loop, 6
		GuiControl, , % "Edit" . A_Index, % (A_Index = 1 ? (vSectors := 200) : A_Index = 2 ? (vMultiplier := 2.0) : A_Index <= 4 ? (vPenWidth := 1) : A_Index = 5 ? (vFrequency := 2.0) : (vPhase := 0.0))
	Loop, 2
		GuiControl, , % "msctls_trackbar32" . A_Index, % (A_Index = 1 ? 20 : 0)
	GuiControl, Choose, ComboBox1, 1
	Gui, gControl: Submit, NoHide

	;Transform the Gui back to default if necessary:
	If ((vGuiMode2 := vGuiMode2 ? vGuiMode2 : "Default") != (vGuiMode1 := vColorSetting := "Default"))
		TransformGui()

	If (vFocus) {
		WinActivate, ahk_id %vFocus%

		VarSetCapacity(vFocus, 0)
	}

	;Draw the eclipse and clear the graphics:
	GoSub, UpdateCanvas
	Return

OffsetEdit:
	If (A_GuiControl = "_vMultiplier2") {
		;Offset vMultiplier and reset _vMultiplier2 (the internal UpDown2 variable) back to 0:
		GuiControl, , _vMultiplier1, % (vMultiplier := Round(_vMultiplier2 <= 0 ? (_vMultiplier1 - 0.1) < 0.1 ? 0 : _vMultiplier1 > 500 ? 499.9 : (_vMultiplier1 - 0.1) : (_vMultiplier1 + 0.1) > 499.9 ? 500.0 : (_vMultiplier1 + 0.1), 1))
		GuiControl, , _vMultiplier2, % (_vMultiplier2 := 0)

		GoTo, ColorSetting
	}
	;Offset vFrequency and vPhase:
	GuiControl, , _vFrequency1, % (vFrequency := Round(_vFrequency2/10, 1))
	GuiControl, , _vPhase1, % (vPhase := Round(_vPhase2/2, 1))
ColorSetting:
	Gui, gControl: Submit, NoHide
	;Transform the Gui if necessary:
	If (vGuiMode2 != (vGuiMode1 := ((vColorSetting := RegExReplace(vColorSetting, A_Space, "_")) = "Oscillate_Color" ? "Extended" : "Default")))
		TransformGui()
	;Track the current Gui mode:
	vGuiMode2 := vGuiMode1

	;vCycle has CreateSectors on a timer so stop here:
	If (vCycle)
		Return
CreateSectors:
	Critical

	;Increment vMultiplier and _vMultiplier1 (the internal Edit2 variable) if vCycle is on:
	If (vCycle)
		ControlSetText, Edit2, % (vMultiplier := _vMultiplier1 := Round(vMultiplier + (vMultiplier >= 500 ? -500 : 0.05), 2)), ahk_id %gControl%

	Loop, % vSectors {
		;Calculate the xy coordinates of the start and end of the line that needs to be drawn:
		{
			a := -360/vSectors*3.1415926535897932384626433832795/180
			i := A_Index - 1

			v := a*Format("{:0.6f}", i)
			x1 := vRadius*Cos(v)
			y1 := vRadius*Sin(v)

			v := a*i*Mod(vMultiplier, vSectors)
			x2 := vRadius*Cos(v)
			y2 := vRadius*Sin(v)
		}

		;Calculate the color of the line that needs to be drawn:
		{
			If (vColorSetting = "Distance_Alpha") {
				;Calculate the distance between the xy coordinates and translate that into a range of 0-255:
				v := Abs(Floor(Sqrt((x2 - x1)**2 + (y2 - y1)**2)/vDiameter*255) - 255)		;Best theorem.
				c := Format("{:#X}{:02X}{2:02X}{2:02X}", v, 255)
			}
			Else If (vColorSetting = "Distance_Color") {
				;Calculate the distance between the xy coordinates and translate that into a range of 0-240 with an offset to have red (160) at the center:
				v := (v := Floor(Sqrt((x2 - x1)**2 + (y2 - y1)**2)/vDiameter*240) + 160) + (v > 240 ? -240 : 0)
				c := Format("{:#X}{:06X}", 255, DllCall("shlwapi\ColorHLSToRGB", UInt, v, UInt, 120, UInt, 240))
			}
			Else If (vColorSetting = "Oscillate_Color") {
				;Calculate values for R, G and B on out of sync sine waves and translate that to a range of 0-255:
				v := [Sin((f := 3.1415926535897932384626433832795*vFrequency/vSectors*i + vPhase))*127.5 + 127.5, Sin(f + 2.094395)*127.5 + 127.5, Sin(f + 4.188790)*127.5 + 127.5]
				c := Format("{:#X}{:02X}{:02X}{:02X}", 255, v[1], v[2], v[3])

				;Draw a visualization (not accurate because the values stay possitive but it looks better as a complete sine wave (-1 to 1)) of the outcome of the R, G and B sine waves and increase the pen width by 25% for an overlap to avoid ridges at high sector count:
				Gdip_DrawLine(G1, (pPen := Gdip_CreatePen(c, (w := vDiameter/vSectors)*1.25)), (x := i*w + (w/2)), (Abs((v := Sin(f - vPhase))) < 0.000001 ? 1 : 0) + vRadius*0.25, x, v*20 + vRadius*0.25), Gdip_DeletePen(pPen)
			}
			Else
				c := Format("{:#X}{:02X}{2:02X}{2:02X}", 255, 255)
		}

		;Draw the line:
		Gdip_DrawLine(G1, (pPen := Gdip_CreatePen(c, vPenWidth)), x1 + vRadius, y1 + vRadius*1.5, x2 + vRadius, y2 + vRadius*1.5), Gdip_DeletePen(pPen)
	}

	UpdateCanvas:
		;Draw the outline eclipse and clean up:
		pPen := Gdip_CreatePen("0x80FFFFFF", 1)
		If (vGuiMode1 = "Extended")
			Gdip_DrawLine(G1, pPen, 0, vRadius*0.25, vDiameter, vRadius*0.25)
		Gdip_DrawEllipse(G1, pPen, 0, vRadius*0.5, vDiameter, vDiameter)
		UpdateLayeredWindow(gCanvas1, hdc1, vCx, vCy, vRadius*2.5, vRadius*2.5 + 5, 255)
		Gdip_DeletePen(pPen)
		Gdip_GraphicsClear(G1)

		If (!(vFreeMemory := (vFreeMemory < 200 ? ++vFreeMemory : 0)))
			GoSub, FreeMemory

	Return

Cycle:
	;Toggle vCycle:
	SetTimer, CreateSectors, % ((vCycle := !vCycle) ? 50 : "Off")
	Return

PenWidth:
	;Can't assign the same variable to two controls and moving an Edit with a buddy screws up the buddy control so need to ensure they match here. Changing one, changes the other:
	ControlGetText, vPenWidth, % (vGuiMode1 != "Extended" ? "Edit3" : "Edit4"), ahk_id %gControl%
	GuiControl, , % (vGuiMode1 != "Extended" ? "Edit4" : "Edit3"), % vPenWidth
	If (!vCycle)
		Gosub, CreateSectors
	Return

AntiAlias:
	Gdip_SetSmoothingMode(G1, ((vAntiAlias := !vAntiAlias) ? 3 : 4))		;3 = None, 4= AntiAlias.
	GuiControl, , % (vGuiMode1 != "Extended" ? "Button4" : "Button3"), % (vAntiAlias ? 0 : 1)
	If (!vCycle)
		Gosub, CreateSectors
	Return

NSFW:
	Gui, gControl: Show, NA
	Gui, gCanvas1: Show, NA
	If (vHelp)
		Gui, gCanvas2: Show, NA
	If (vNSFW := !vNSFW) {
		If (vCycle)
			Gosub, Cycle
		Gui, gControl: Hide
		Gui, gCanvas1: Hide
		If (vHelp)
			Gui, gCanvas2: Hide
	}
	Return

Help:
	;Toggle unless an update (vHelp = "Help") is queued because vGuiMode2 != vGuiMode1:
	If (vHelp := (vHelp = "Help" ? True : !vHelp)) {
		hbm2 := CreateDIBSection(A_ScreenWidth, A_ScreenHeight), hdc2 := CreateCompatibleDC(), obm2 := SelectObject(hdc2, hbm2)
		G2 := Gdip_GraphicsFromHDC(hdc2), Gdip_SetSmoothingMode(G2, 4)
		Gui, gCanvas2: New, -Caption +AlwaysOnTop +ToolWindow +OwnDialogs +HwndgCanvas2 +E0x80000 +E0x20
		Gui, gCanvas2: Show, NA

		Gdip_TextToGraphics(G2, "Reset ⮞", "x"vCx - 276 "y"vRadius*1.5 - 35 "cFFFF0000 r4 s15 Bold", "Arial"), Gdip_TextToGraphics(G2, "Line count ⮟", "x"vCx - 265 "y"vRadius*1.5 - 60 "cFFFFFFFF r4 s15 Bold", "Arial"), Gdip_TextToGraphics(G2, "⮟ Multiplier", "x"vCx - 120 "y"vRadius*1.5 - 60 "cFFFFFFFF r4 s15 Bold", "Arial"), Gdip_TextToGraphics(G2, "⮜ Cycle", "x"vCx - 68 "y"vRadius*1.5 - 9 "cFFFFFFFF r4 s15 Bold", "Arial"), Gdip_TextToGraphics(G2, "Color mode ⮞", "x"vCx - 320 "y"vRadius*1.5 - 9 "cFFFFFFFF r4 s15 Bold", "Arial")
		If (vGuiMode1 != "Extended")
			Gdip_TextToGraphics(G2, "Line width ⮞", "x"vCx - 310 "y"vRadius*1.5 + 16 "cFFFFFFFF r4 s15 Bold", "Arial"), Gdip_TextToGraphics(G2, "AntiAlias ⮝", "x"vCx - 244 "y"vRadius*1.5 + 45 "cFFFFFFFF r4 s15 Bold", "Arial"), Gdip_TextToGraphics(G2, "⮝ Hide gui", "x"vCx - 130 "y"vRadius*1.5 + 45 "cFFFF0000 r4 s15 Bold", "Arial"), Gdip_TextToGraphics(G2, "(Hold spacebar)", "x"vCx - 125 "y"vRadius*1.5 + 60 "cFFFF0000 r4 s15 Bold", "Arial"), Gdip_TextToGraphics(G2, "⮜ Help", "x"vCx - 68 "y"vRadius*1.5 + 17 "cFFFFFFFF r4 s15 Bold", "Arial")
		Else
			Gdip_TextToGraphics(G2, "Frequency ⮞", "x"vCx - 312 "y"vRadius*1.5 + 15 "cFFFFFFFF r4 s15 Bold", "Arial"), Gdip_TextToGraphics(G2, "Phase ⮞", "x"vCx - 279 "y"vRadius*1.5 + 40 "cFFFFFFFF r4 s15 Bold", "Arial"), Gdip_TextToGraphics(G2, "Line width ⮞", "x"vCx - 310 "y"vRadius*1.5 + 68 "cFFFFFFFF r4 s15 Bold", "Arial"), Gdip_TextToGraphics(G2, "AntiAlias ⮝", "x"vCx - 244 "y"vRadius*1.5 + 95 "cFFFFFFFF r4 s15 Bold", "Arial"), Gdip_TextToGraphics(G2, "⮝ Hide gui", "x"vCx - 130 "y"vRadius*1.5 + 95 "cFFFF0000 r4 s15 Bold", "Arial"), Gdip_TextToGraphics(G2, "(Hold spacebar)", "x"vCx - 125 "y"vRadius*1.5 + 110 "cFFFF0000 r4 s15 Bold", "Arial"), Gdip_TextToGraphics(G2, "⮜ Help", "x"vCx - 68 "y"vRadius*1.5 + 68 "cFFFFFFFF r4 s15 Bold", "Arial")
		UpdateLayeredWindow(gCanvas2, hdc2, 0, 0, A_ScreenWidth, A_ScreenHeight)
	}
	Else {
		SelectObject(hdc2, obm2), DeleteObject(hbm2), DeleteDC(hdc2), Gdip_DeleteGraphics(G2)
		Gui, gCanvas2: Destroy
	}

	GoSub, FreeMemory
	Return

Exit:
	Critical

	;Delete Gdip assets:
	SelectObject(hdc1, obm1), DeleteObject(hbm1), DeleteDC(hdc1), Gdip_DeleteGraphics(G1)
	If (vHelp)
		SelectObject(hdc2, obm2), DeleteObject(hbm2), DeleteDC(hdc2), Gdip_DeleteGraphics(G2)
	Gdip_Shutdown(pToken)

	ExitApp
	Return

/*
	===== Functions ================================================================================
*/

WM_KEYUP(wParam, lParam) {
	Global
	Local v

	ControlGetFocus, v, ahk_id %gControl%

	If (v ~= "(Edit1|Edit2)" &&  wParam ~= "(13|48|49|50|51|52|53|54|55|56|57|96|97|98|99|100|101|102|103|104|105)") {
		Gui, gControl: Submit, NoHide

		GuiControl, , Edit1, % (vSectors > 2000 ? 2000 : vSectors)
		GuiControl, , Edit2, % (vMultiplier := Format("{:0.1f}", (_vMultiplier1 > 500 ? 500 : _vMultiplier1)))

		vColorSetting := RegExReplace(vColorSetting, A_Space, "_")

		If (wParam = 13)
			If (!vCycle)
				GoSub, CreateSectors
	}
}

TransformGui() {
	Global

	Loop, 5 {
		Control, % (vGuiMode1 != "Extended" ? "Show" : "Hide"), , , % "ahk_id" gDefault%A_Index%
		If (A_Index < 5)
			Control, % (vGuiMode1 != "Extended" ? "Hide" : "Show"), , , % "ahk_id" gExtended%A_Index%
	}
	Gui, gControl: Show, % (vGuiMode1 != "Extended" ? "h80" : "h130") . A_Space . "NA"

	;Switch Help to the new mode if necessary:
	If (vHelp)
		GoSub, % (vHelp := "Help")
}

/*
	===== Gdip Functions ============================================================		;https://github.com/mmikeww/AHKv2-Gdip
*/

Gdip_Startup()
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	pToken := 0

	if !DllCall("GetModuleHandle", "str", "gdiplus", Ptr)
		DllCall("LoadLibrary", "str", "gdiplus")
	VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
	DllCall("gdiplus\GdiplusStartup", A_PtrSize ? "UPtr*" : "uint*", pToken, Ptr, &si, Ptr, 0)
	return pToken
}

Gdip_Shutdown(pToken)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"

	DllCall("gdiplus\GdiplusShutdown", Ptr, pToken)
	if hModule := DllCall("GetModuleHandle", "str", "gdiplus", Ptr)
		DllCall("FreeLibrary", Ptr, hModule)
	return 0
}

GetDC(hwnd:=0)
{
	return DllCall("GetDC", A_PtrSize ? "UPtr" : "UInt", hwnd)
}

ReleaseDC(hdc, hwnd:=0)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"

	return DllCall("ReleaseDC", Ptr, hwnd, Ptr, hdc)
}

CreateDIBSection(w, h, hdc:="", bpp:=32, ByRef ppvBits:=0)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"

	hdc2 := hdc ? hdc : GetDC()
	VarSetCapacity(bi, 40, 0)

	NumPut(w, bi, 4, "uint")
	, NumPut(h, bi, 8, "uint")
	, NumPut(40, bi, 0, "uint")
	, NumPut(1, bi, 12, "ushort")
	, NumPut(0, bi, 16, "uInt")
	, NumPut(bpp, bi, 14, "ushort")

	hbm := DllCall("CreateDIBSection"
					, Ptr, hdc2
					, Ptr, &bi
					, "uint", 0
					, A_PtrSize ? "UPtr*" : "uint*", ppvBits
					, Ptr, 0
					, "uint", 0, Ptr)

	if !hdc
		ReleaseDC(hdc2)
	return hbm
}

CreateCompatibleDC(hdc:=0)
{
	return DllCall("CreateCompatibleDC", A_PtrSize ? "UPtr" : "UInt", hdc)
}

SelectObject(hdc, hgdiobj)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"

	return DllCall("SelectObject", Ptr, hdc, Ptr, hgdiobj)
}

Gdip_GraphicsFromHDC(hdc)
{
	pGraphics := ""

	DllCall("gdiplus\GdipCreateFromHDC", A_PtrSize ? "UPtr" : "UInt", hdc, A_PtrSize ? "UPtr*" : "UInt*", pGraphics)
	return pGraphics
}

Gdip_SetSmoothingMode(pGraphics, SmoothingMode)
{
	return DllCall("gdiplus\GdipSetSmoothingMode", A_PtrSize ? "UPtr" : "UInt", pGraphics, "int", SmoothingMode)
}

Gdip_SetInterpolationMode(pGraphics, InterpolationMode)
{
	return DllCall("gdiplus\GdipSetInterpolationMode", A_PtrSize ? "UPtr" : "UInt", pGraphics, "int", InterpolationMode)
}

Gdip_CreatePen(ARGB, w)
{
	DllCall("gdiplus\GdipCreatePen1", "UInt", ARGB, "float", w, "int", 2, A_PtrSize ? "UPtr*" : "UInt*", pPen)
	return pPen
}

Gdip_DrawEllipse(pGraphics, pPen, x, y, w, h)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"

	return DllCall("gdiplus\GdipDrawEllipse", Ptr, pGraphics, Ptr, pPen, "float", x, "float", y, "float", w, "float", h)
}

Gdip_DeletePen(pPen)
{
	return DllCall("gdiplus\GdipDeletePen", A_PtrSize ? "UPtr" : "UInt", pPen)
}

CreateRectF(ByRef RectF, x, y, w, h)
{
	VarSetCapacity(RectF, 16)
	NumPut(x, RectF, 0, "float"), NumPut(y, RectF, 4, "float"), NumPut(w, RectF, 8, "float"), NumPut(h, RectF, 12, "float")
}

CreateRect(ByRef Rect, x, y, w, h)
{
	VarSetCapacity(Rect, 16)
	NumPut(x, Rect, 0, "uint"), NumPut(y, Rect, 4, "uint"), NumPut(w, Rect, 8, "uint"), NumPut(h, Rect, 12, "uint")
}

UpdateLayeredWindow(hwnd, hdc, x:="", y:="", w:="", h:="", Alpha:=255)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"

	if ((x != "") && (y != ""))
		VarSetCapacity(pt, 8), NumPut(x, pt, 0, "UInt"), NumPut(y, pt, 4, "UInt")

	if (w = "") || (h = "")
	{
		CreateRect( winRect, 0, 0, 0, 0 ) ;is 16 on both 32 and 64
		DllCall( "GetWindowRect", Ptr, hwnd, Ptr, &winRect )
		w := NumGet(winRect, 8, "UInt")  - NumGet(winRect, 0, "UInt")
		h := NumGet(winRect, 12, "UInt") - NumGet(winRect, 4, "UInt")
	}

	return DllCall("UpdateLayeredWindow"
	, Ptr, hwnd
	, Ptr, 0
	, Ptr, ((x = "") && (y = "")) ? 0 : &pt
	, "int64*", w|h<<32
	, Ptr, hdc
	, "int64*", 0
	, "uint", 0
	, "UInt*", Alpha<<16|1<<24
	, "uint", 2)
}

Gdip_GraphicsClear(pGraphics, ARGB:=0x00ffffff)
{
	return DllCall("gdiplus\GdipGraphicsClear", A_PtrSize ? "UPtr" : "UInt", pGraphics, "int", ARGB)
}

Gdip_DrawLine(pGraphics, pPen, x1, y1, x2, y2)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"

	return DllCall("gdiplus\GdipDrawLine"
					, Ptr, pGraphics
					, Ptr, pPen
					, "float", x1
					, "float", y1
					, "float", x2
					, "float", y2)
}

Gdip_DeleteBrush(pBrush)
{
	return DllCall("gdiplus\GdipDeleteBrush", A_PtrSize ? "UPtr" : "UInt", pBrush)
}

Gdip_CloneBrush(pBrush)
{
	DllCall("gdiplus\GdipCloneBrush", A_PtrSize ? "UPtr" : "UInt", pBrush, A_PtrSize ? "UPtr*" : "UInt*", pBrushClone)
	return pBrushClone
}

Gdip_StringFormatCreate(Format:=0, Lang:=0)
{
	DllCall("gdiplus\GdipCreateStringFormat", "int", Format, "int", Lang, A_PtrSize ? "UPtr*" : "UInt*", hFormat)
	return hFormat
}

Gdip_FontCreate(hFamily, Size, Style:=0)
{
	DllCall("gdiplus\GdipCreateFont", A_PtrSize ? "UPtr" : "UInt", hFamily, "float", Size, "int", Style, "int", 0, A_PtrSize ? "UPtr*" : "UInt*", hFont)
	return hFont
}

Gdip_FontFamilvCyreate(Font)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"

	if (!A_IsUnicode)
	{
		nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &Font, "int", -1, "uint", 0, "int", 0)
		VarSetCapacity(wFont, nSize*2)
		DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &Font, "int", -1, Ptr, &wFont, "int", nSize)
	}

	DllCall("gdiplus\GdipCreateFontFamilyFromName"
					, Ptr, A_IsUnicode ? &Font : &wFont
					, "uint", 0
					, A_PtrSize ? "UPtr*" : "UInt*", hFamily)

	return hFamily
}

Gdip_BrushCreateSolid(ARGB:=0xff000000)
{
	pBrush := ""

	DllCall("gdiplus\GdipCreateSolidFill", "UInt", ARGB, A_PtrSize ? "UPtr*" : "UInt*", pBrush)
	return pBrush
}

Gdip_SetStringFormatAlign(hFormat, Align)
{
	return DllCall("gdiplus\GdipSetStringFormatAlign", A_PtrSize ? "UPtr" : "UInt", hFormat, "int", Align)
}

Gdip_SetTextRenderingHint(pGraphics, RenderingHint)
{
	return DllCall("gdiplus\GdipSetTextRenderingHint", A_PtrSize ? "UPtr" : "UInt", pGraphics, "int", RenderingHint)
}

Gdip_MeasureString(pGraphics, sString, hFont, hFormat, ByRef RectF)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"

	VarSetCapacity(RC, 16)
	if !A_IsUnicode
	{
		nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sString, "int", -1, "uint", 0, "int", 0)
		VarSetCapacity(wString, nSize*2)
		DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sString, "int", -1, Ptr, &wString, "int", nSize)
	}

	DllCall("gdiplus\GdipMeasureString"
					, Ptr, pGraphics
					, Ptr, A_IsUnicode ? &sString : &wString
					, "int", -1
					, Ptr, hFont
					, Ptr, &RectF
					, Ptr, hFormat
					, Ptr, &RC
					, "uint*", Chars
					, "uint*", Lines)

	return &RC ? NumGet(RC, 0, "float") "|" NumGet(RC, 4, "float") "|" NumGet(RC, 8, "float") "|" NumGet(RC, 12, "float") "|" Chars "|" Lines : 0
}

Gdip_DrawString(pGraphics, sString, hFont, hFormat, pBrush, ByRef RectF)
{
	Ptr := A_PtrSize ? "UPtr" : "UInt"

	if (!A_IsUnicode)
	{
		nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sString, "int", -1, Ptr, 0, "int", 0)
		VarSetCapacity(wString, nSize*2)
		DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sString, "int", -1, Ptr, &wString, "int", nSize)
	}

	return DllCall("gdiplus\GdipDrawString"
					, Ptr, pGraphics
					, Ptr, A_IsUnicode ? &sString : &wString
					, "int", -1
					, Ptr, hFont
					, Ptr, &RectF
					, Ptr, hFormat
					, Ptr, pBrush)
}

Gdip_DeleteStringFormat(hFormat)
{
	return DllCall("gdiplus\GdipDeleteStringFormat", A_PtrSize ? "UPtr" : "UInt", hFormat)
}

Gdip_DeleteFont(hFont)
{
	return DllCall("gdiplus\GdipDeleteFont", A_PtrSize ? "UPtr" : "UInt", hFont)
}

Gdip_DeleteFontFamily(hFamily)
{
	return DllCall("gdiplus\GdipDeleteFontFamily", A_PtrSize ? "UPtr" : "UInt", hFamily)
}

Gdip_TextToGraphics(pGraphics, Text, Options, Font:="Arial", Width:="", Height:="", Measure:=0)
{
	IWidth := Width, IHeight:= Height

	pattern_opts := (A_AhkVersion < "2") ? "iO)" : "i)"
	RegExMatch(Options, pattern_opts "X([\-\d\.]+)(p*)", xpos)
	RegExMatch(Options, pattern_opts "Y([\-\d\.]+)(p*)", ypos)
	RegExMatch(Options, pattern_opts "W([\-\d\.]+)(p*)", Width)
	RegExMatch(Options, pattern_opts "H([\-\d\.]+)(p*)", Height)
	RegExMatch(Options, pattern_opts "C(?!(entre|enter))([a-f\d]+)", Colour)
	RegExMatch(Options, pattern_opts "Top|Up|Bottom|Down|vCentre|vCenter", vPos)
	RegExMatch(Options, pattern_opts "NoWrap", NoWrap)
	RegExMatch(Options, pattern_opts "R(\d)", Rendering)
	RegExMatch(Options, pattern_opts "S(\d+)(p*)", Size)

	if Colour && !Gdip_DeleteBrush(Gdip_CloneBrush(Colour[2]))
		PassBrush := 1, pBrush := Colour[2]

	if !(IWidth && IHeight) && ((xpos && xpos[2]) || (ypos && ypos[2]) || (Width && Width[2]) || (Height && Height[2]) || (Size && Size[2]))
		return -1

	Style := 0, Styles := "Regular|Bold|Italic|BoldItalic|Underline|Strikeout"
	For eachStyle, valStyle in StrSplit( Styles, "|" )
	{
		if RegExMatch(Options, "\b" valStyle)
			Style |= (valStyle != "StrikeOut") ? (A_Index-1) : 8
	}

	Align := 0, Alignments := "Near|Left|Centre|Center|Far|Right"
	For eachAlignment, valAlignment in StrSplit( Alignments, "|" )
	{
		if RegExMatch(Options, "\b" valAlignment)
			Align |= A_Index//2.1	; 0|0|1|1|2|2
	}

	xpos := (xpos && (xpos[1] != "")) ? xpos[2] ? IWidth*(xpos[1]/100) : xpos[1] : 0
	ypos := (ypos && (ypos[1] != "")) ? ypos[2] ? IHeight*(ypos[1]/100) : ypos[1] : 0
	Width := (Width && Width[1]) ? Width[2] ? IWidth*(Width[1]/100) : Width[1] : IWidth
	Height := (Height && Height[1]) ? Height[2] ? IHeight*(Height[1]/100) : Height[1] : IHeight
	if !PassBrush
		Colour := "0x" (Colour && Colour[2] ? Colour[2] : "ff000000")
	Rendering := (Rendering && (Rendering[1] >= 0) && (Rendering[1] <= 5)) ? Rendering[1] : 4
	Size := (Size && (Size[1] > 0)) ? Size[2] ? IHeight*(Size[1]/100) : Size[1] : 12

	hFamily := Gdip_FontFamilvCyreate(Font)
	hFont := Gdip_FontCreate(hFamily, Size, Style)
	FormatStyle := NoWrap ? 0x4000 | 0x1000 : 0x4000
	hFormat := Gdip_StringFormatCreate(FormatStyle)
	pBrush := PassBrush ? pBrush : Gdip_BrushCreateSolid(Colour)
	if !(hFamily && hFont && hFormat && pBrush && pGraphics)
		return !pGraphics ? -2 : !hFamily ? -3 : !hFont ? -4 : !hFormat ? -5 : !pBrush ? -6 : 0

	CreateRectF(RC, xpos, ypos, Width, Height)
	Gdip_SetStringFormatAlign(hFormat, Align)
	Gdip_SetTextRenderingHint(pGraphics, Rendering)
	ReturnRC := Gdip_MeasureString(pGraphics, Text, hFont, hFormat, RC)

	if vPos
	{
		ReturnRC := StrSplit(ReturnRC, "|")

		if (vPos[0] = "vCentre") || (vPos[0] = "vCenter")
			ypos += (Height-ReturnRC[4])//2
		else if (vPos[0] = "Top") || (vPos[0] = "Up")
			ypos := 0
		else if (vPos[0] = "Bottom") || (vPos[0] = "Down")
			ypos := Height-ReturnRC[4]

		CreateRectF(RC, xpos, ypos, Width, ReturnRC[4])
		ReturnRC := Gdip_MeasureString(pGraphics, Text, hFont, hFormat, RC)
	}

	if !Measure
		_E := Gdip_DrawString(pGraphics, Text, hFont, hFormat, pBrush, RC)

	if !PassBrush
		Gdip_DeleteBrush(pBrush)
	Gdip_DeleteStringFormat(hFormat)
	Gdip_DeleteFont(hFont)
	Gdip_DeleteFontFamily(hFamily)
	return _E ? _E : ReturnRC
}

DeleteObject(hObject)
{
	return DllCall("DeleteObject", A_PtrSize ? "UPtr" : "UInt", hObject)
}

DeleteDC(hdc)
{
	return DllCall("DeleteDC", A_PtrSize ? "UPtr" : "UInt", hdc)
}

Gdip_DeleteGraphics(pGraphics)
{
	return DllCall("gdiplus\GdipDeleteGraphics", A_PtrSize ? "UPtr" : "UInt", pGraphics)
}
Last edited by Onimuru on 22 Jul 2019, 03:13, edited 1 time in total.
User avatar
flyingDman
Posts: 2791
Joined: 29 Sep 2013, 19:01

Re: GDIP Art ?

21 Jul 2019, 20:33

Could you look at your variables V1 V2 ? their are some characters that are translated to "?". Thank you.
14.3 & 1.3.7
DebuffedInRl
Posts: 12
Joined: 19 Jul 2019, 02:02

Re: GDIP Art ?

22 Jul 2019, 02:37

I just found these whilst browsing forum and tried them out...there pretty awesome to be honest...
User avatar
Onimuru
Posts: 107
Joined: 08 Sep 2018, 18:35
Contact:

Re: GDIP Art ?

22 Jul 2019, 03:14

Thanks for pointing that out, I edited the code.
User avatar
Onimuru
Posts: 107
Joined: 08 Sep 2018, 18:35
Contact:

Re: GDIP Art ?

02 Aug 2019, 12:35

Here's something else I made based on https://i.imgur.com/CUgIRMB.gif

Code: Select all

#KeyHistory 0
#NoEnv
#Persistent
#SingleInstance Force

ListLines, Off
Process, Priority, , R
SetBatchLines, -1
SetControlDelay, -1

Global vRadius := 150, vDiameter := vRadius*2
	, vSectors := 8
	, vClockwise := 1  ;1 || -1
	;, vCx := A_ScreenWidth - vRadius*1.5, vCy := vRadius*1.5
	, vCanvas := new LayeredWindow("gCanvas", "-Caption +AlwaysOnTop +ToolWindow +OwnDialogs +E0x20", A_ScreenWidth - vRadius*2.5, 0, vRadius*2.5, vRadius*2.5 + 5)
	, Balls := {}

SetTimer, Update, 25

Loop, % vSectors {
	a := (vClockwise*(180/vSectors)*0.01745329251994329576923690768489)*(A_Index - 1)

	Balls.Push(new Ball(vRadius*Cos(a), vRadius, vRadius*Sin(a), vRadius*1.5, vRadius/10, a*57.295779513082320876798154814105))

	Sleep, 325  ;If you add more sectors (+ 2 Balls) or adjust the timer, you have to find the correct delay between new balls for those settings. I couldn't figure out how to calculate it...
}

OnExit, Exit

Exit

/*
	===== Labels ================================================================================
*/

Update:
	Gdip_DrawEllipse(vCanvas.G, vCanvas.pPen, vRadius - vRadius/20, vRadius*1.5 - vRadius/20, vRadius/10, vRadius/10)
	Gdip_DrawEllipse(vCanvas.G, vCanvas.pPen, 0, vRadius*0.5, vDiameter, vDiameter)

	For i, v in Balls
		v.UpDate()

	UpdateLayeredWindow(vCanvas.Hwnd, vCanvas.hdc), Gdip_GraphicsClear(vCanvas.G)

	Return

/*
	===== Functions ================================================================================
*/

Class LayeredWindow {
	__New(_name, _options, _x, _y, _w, _h, _smoothing := 4, _interpolation := 7) {
		this.Layered := {"Name": _name
			, "Options": _options
			, "X": _x
			, "Y": _y
			, "W": _w
			, "H": _h}

		this.Layered.pToken := Gdip_Startup()
		this.Layered.hbm := CreateDIBSection(_w, _h), this.Layered.hdc := CreateCompatibleDC(), this.Layered.obm := SelectObject(this.Layered.hdc, this.Layered.hbm)
		this.Layered.G := Gdip_GraphicsFromHDC(this.Layered.hdc), Gdip_SetSmoothingMode(this.Layered.G, _smoothing), Gdip_SetInterpolationMode(this.Layered.G, _interpolation)

		this.CreateGUI(), this.Layered.Hwnd := WinExist()

		this.Layered.pPen := Gdip_CreatePen("0x80FFFFFF", 1)

		Return (this.Layered)
	}

	CreateGUI() {
		Gui, % this.Layered.Name . ": New", % this.Layered.Options . " +LastFound +E0x80000"
		Gui, % this.Layered.Name . ": Show", % " x" . this.Layered.X . " y" . this.Layered.Y . " w" . this.Layered.W " h" . this.Layered.H " NA"
	}

	ShutDown() {
		Gdip_DeletePen(this.Layered.pPen)

		SelectObject(this.Layered.hdc, this.obm), DeleteObject(this.Layered.hbm), DeleteDC(this.Layered.hdc), Gdip_DeleteGraphics(this.Layered.G)
		Gdip_Shutdown(this.Layered.pToken)
	}
}

Class Ball {
	__New(_x1, _x2, _y1, _y2, _s, _a) {
		C := Format("{:02X}{:02X}{:02X}", Round((C := HSV_Convert2RGB(Abs(_a)/360))[1]*255), Round(C[2]*255), Round(C[3]*255))

		this.Cx := this.Ox := _x1 + _x2, this.Cy := this.Oy := _y1 + _y2, this.Dx := (-_x1*2)/vDiameter, this.Dy := (-_y1*2)/vDiameter
			, this.S := _s, this.P := [], this.B := [Gdip_BrushCreateSolid("0xFF" . C), Gdip_BrushCreateSolid("0xCC" . C), Gdip_BrushCreateSolid("0x99" . C), Gdip_BrushCreateSolid("0x66" . C), Gdip_BrushCreateSolid("0x33" . C)]
			, this.M := -5
			, this.E := (Abs(this.A := _a) < 180)
	}

	Update() {
		D := Sqrt((this.Cx - this.Ox)**2 + (this.Cy - this.Oy)**2)
		If (D >= (vRadius - 10) - 1) {
			this.M *= -1

			If (this.E)  ;This becomes an unnessary check quickly, only used to spawn the opporsite ball at the correct time.
				Balls.Push(new Ball(-(this.Ox - vRadius), vRadius, -(this.Oy - vRadius*1.5), vRadius*1.5, vRadius/10, this.A + 180*vClockwise)), this.E := 0
		}

		Else If (D <= 1)
			this.M *= -1

		this.P.RemoveAt(5)
		this.P.InsertAt(1, [this.Cx += this.Dx*this.M, this.Cy += this.Dy*this.M])

		this.Draw()
	}

	Draw() {
		For i, v in this.P {
			s := this.S - this.S*i/10

			Gdip_FillEllipse(vCanvas.G, this.B[i], v[1] - s/2, v[2] - s/2, s, s)
		}
	}
}

HSV_Convert2RGB(h := 0, s := 1, v := 1) {  ;Credit: jeeswg (https://www.autohotkey.com/boards/viewtopic.php?t=44375)
	If (s = 0)
		Return [r, g, b]

	h := (h = 1 ? 0.0 : h) * 6.0, i := Floor(h)

	f := h - i, p := v*(1.0 - s), q := v*(1.0 - s*f), t := v*(1.0 - s*(1.0 - f))

	If (i = 0)
		r := v, g := t, b := p

	Else If (i =1 )
		r := q, g := v, b := p

	Else If (i = 2)
		r := p, g := v, b := t

	Else If (i = 3)
		r := p, g := q, b := v

	Else If (i = 4)
		r := t, g := p, b := v

	Else
		r := v, g := p, b := q

	Return [r, g, b]
}

/*
	===== Hotkeys ================================================================================
*/

~$Esc::
	KeyWait, Esc, T0.5
	If (!ErrorLevel)
		Return
Exit:
	For i, v in Balls
		For i, v in v.B
			Gdip_DeleteBrush(v)

	vCanvas.ShutDown()
	ExitApp
	Return

~$^s::
	Critical
	SetTitleMatchMode, 2

	If (WinActive(A_ScriptName)) {
		Sleep, 200
		Reload
	}
	Return
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: GDIP Art ?

05 Aug 2019, 01:52

[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
Onimuru
Posts: 107
Joined: 08 Sep 2018, 18:35
Contact:

Re: GDIP Art ?

09 Aug 2019, 08:27

This was a lot of fun:

Code: Select all

#KeyHistory 0
#NoEnv
#Persistent
#SingleInstance Force

#Include, %A_ScriptDir%\..\..\..\lib\GDIp.ahk

ListLines, Off
Process, Priority, , R
SetBatchLines, -1
SetControlDelay, -1

vCanvas := 150
Global vCanvas := new Canvas("gCanvas", "-Caption +AlwaysOnTop +ToolWindow +OwnDialogs +E0x20", A_ScreenWidth - vCanvas*2.5 + 5, vCanvas*.5 + 5, vCanvas*2 + 10, vCanvas*2 + 10)
	, vSolarSystem := {"x": 5
		, "y": 5
		, "h": vCanvas.width/2
		, "k": vCanvas.height/2

		, "ratio": 1
		, "depth": 0

		, "date": 0
		, "planets": []

		, "speedratio": 1}

vSolarSystem.planets.Push(new Planet("Sun", Min(vCanvas.width, vCanvas.height)/10, 0, 0, 0, vSolarSystem))  ;(_name, _diameter, _orbitangle, _orbitradius, _orbitrevolution (days), _parent)
Loop, % Random(1, 6) {
	vSolarSystem.planets.Push(new Planet(A_Index, Random(10, vSolarSystem.planets[1].diameter[1]*1.35), Random(0, 360), Random(vSolarSystem.planets[1].diameter[1], Min(vCanvas.width/2, vCanvas.height/2)), Random(250, 2500), vSolarSystem.planets[1]))
	Loop, % Random(-2, 3)
		vSolarSystem.planets.Push(new Planet(Round(vSolarSystem.planets[vSolarSystem.planets.Length() - (A_Index - 1)].name + A_Index/10, 1), Random(5, vSolarSystem.planets[vSolarSystem.planets.Length() - (A_Index - 1)].diameter[1]*.5), Random(0, 360), Random(vSolarSystem.planets[vSolarSystem.planets.Length() - (A_Index - 1)].diameter[1]*1.25, vSolarSystem.planets[vSolarSystem.planets.Length() - (A_Index - 1)].diameter[1]*1.75), Random(35, 800), vSolarSystem.planets[vSolarSystem.planets.Length() - (A_Index - 1)]))
}

DllCall("QueryPerformanceFrequency", "Int64*", QPF)
DllCall("QueryPerformanceCounter", "Int64*", QPC_before)

SetTimer, Update, -1

OnExit, Exit

Exit

/*
	===== Hotkeys ================================================================================
*/

~$^s::
	Critical
	SetTitleMatchMode, 2

	If (WinActive(A_ScriptName)) {
		Sleep, 200
		Reload
	}
	Return

~$Left::
	vSolarSystem.speedratio /= 2

	KeyWait, Left
	Return

~$Right::
	vSolarSystem.speedratio *= 2

	KeyWait, Right
	Return

~$Space::
	KeyWait, Space, T0.5
	If (ErrorLevel) {
		Gui, gCanvas: Show, NA
		If (NSFW := !NSFW)
			Gui, gCanvas: Hide
	}

	KeyWait, Space
	Return

~$Esc::
	KeyWait, Esc, T0.5
	If (ErrorLevel)
		Gosub, Exit

	Return

/*
	===== Labels ================================================================================
*/

Update:
	DllCall("QueryPerformanceCounter", "Int64*", QPC_now)
	QPC_delta := (QPC_now - QPC_before)/QPF*1000

;	If (vCanvas.follow) {
;		MouseGetPos, x, y
;		Gui, gCanvas: Show, % "x" . x - vCanvas.width/2 . " y" . y - vCanvas.height/2 . " NA"
;	}

	If (QPC_delta > 50) {  ;1000/20 (~20 FPS)
		QPC_before := QPC_now - Mod(QPC_delta, 50)
			, p := [0]

		Gdip_TextToGraphics(vCanvas.G, Round(vSolarSystem.date += 1*vSolarSystem.speedratio) . " days`n`nRevolutions:", "cFFFFFFFF Bold r4 s12", "Arial")
		For i, v in vSolarSystem.planets {
			v.Update(vSolarSystem.date)

			If (v.parent.name == "Sun")
				Gdip_TextToGraphics(vCanvas.G, v.name . ": " Round(vSolarSystem.date/v.orbit.revolution, 2), "y" . 13*(++p[1] + 2) . " cFFFFFFFF Bold r4 s12", "Arial")
		}

		If (vSolarSystem.speedratio != 1)
			Gdip_TextToGraphics(vCanvas.G, Round(vSolarSystem.speedratio, 1) . "x", "x" . vCanvas.width - 35 . " cFFFFFFFF Bold r4 s12", "Arial")

		Loop, % (p[1] := vSolarSystem.planets.Clone()).Length() {
			p[3] := A_ScreenWidth*1.5 + 1  ;Should be greater than any potential orbit.radius*parent.ratio (min 0.5, max 1.5).

			For i, v in p[1]  ;Finds the planet with the lowest depth ("furthest" away).
				If (p[3] > v.depth)
					p[3] := v.depth, p[2] := i

;			If (vDebug)
;				p[0] .= (A_Index > 1 ? "|" : "") . p[1][p[2]].name

			p[1].RemoveAt(p[2]).Draw(vSolarSystem.date)  ;Draw the "furthest" planet and remove it from the temp array so that "closer" planets will be drawn over it.
		}

		For i, v in vSolarSystem.planets
			Gdip_DrawLine(vCanvas.G, vCanvas.pPen[1], v.h, v.k, v.parent.h, v.parent.k)

;		If (vDebug) {
;			If (GetKeyState("q", "P")) {
;				p[0] := StrSplit(p[0], "|")
;				For i, v in p[0]
;					p[0] .= (i > 1 ? "|" : "") . v
;
;				ToolTip, % p[0]
;			}
;
;			Else
;				ToolTip
;		}

		UpdateLayeredWindow(vCanvas.hwnd, vCanvas.hdc), Gdip_GraphicsClear(vCanvas.G)
	}

	SetTimer, Update, -1

	Return

Exit:
	SetTimer, Update, Delete

	vCanvas.ShutDown()

	ExitApp
	Return

/*
	===== Functions ================================================================================
*/

Angle_Radians(_degrees){
	Return (_degrees*0.01745329251994329576923690768489)
}

Between(_number, _low, _high) {
	Return (_number >= _low && _number <= _high)
}

Random(_min := 0, _max := 100) {
	Random, r, _min, _max

	Return (r)
}

Random_Color() {
	Loop, 6
		c .= StrSplit("0123456789ABCDEF")[Random(1, 16)]

    return (c)
}

Class Canvas {
	__New(_name, _options, _x, _y, _width, _height, _smoothing := 4, _interpolation := 7, _hide := 0) {
		this.x := _x, this.y := _y
		this.width := _width, this.height := _height

		this.pToken := Gdip_Startup()
		this.hbm := CreateDIBSection(_width, _height), this.hdc := CreateCompatibleDC(), this.obm := SelectObject(this.hdc, this.hbm)
		this.G := Gdip_GraphicsFromHDC(this.hdc), Gdip_SetSmoothingMode(this.G, _smoothing), Gdip_SetInterpolationMode(this.G, _interpolation)

		this.pBrush := [], 	this.pPen := [Gdip_CreatePen("0x80FFFFFF", 1)]

		Gui, % _name ": New", % _options . " +LastFound +E0x80000"
		Gui, % _name ": Show", % " x" . _x . " y" . _y . " w" . _width . " h" . _height . (_hide ? " Hide" : " NA")
		this.hwnd := WinExist()

		Return (this)
	}

	NewBrush(_alpha := "FF", _colour := "000000") {
		this.pBrush.Push(Gdip_BrushCreateSolid("0x" . _alpha . _colour))

		Return (this.pBrush[this.pBrush.Length()])
	}

	NewLineBrush(_x, _y, _width, _height, _alpha1 := "FF", _colour1 := "000000", _alpha2 := "FF", _colour2 := "000000", _lineargradientmode := 1, _wrapmode := 1) {
		this.pBrush.Push(Gdip_CreateLineBrushFromRect(_x, _y, _width, _height, "0x" . _alpha1 . _colour1, "0x" . _alpha2 . _colour2, _lineargradientmode, _wrapmode))

		Return (this.pBrush[this.pBrush.Length()])
	}

	NewPen(_alpha := "FF", _colour := "000000", _width := 1) {
		this.pPen.Push(Gdip_CreatePen("0x" . _alpha . _colour, _width))

		Return (this.pPen[this.pPen.Length()])
	}

	ShutDown() {
		For i, v in this.pPen
			Gdip_DeletePen(v)
		For i, v in this.pBrush
			Gdip_DeleteBrush(v)

		SelectObject(this.hdc, this.obm), DeleteObject(this.hbm), DeleteDC(this.hdc), Gdip_DeleteGraphics(this.G)
		Gdip_Shutdown(this.pToken)
	}
}

Class Planet {
	__New(_name, _diameter, _orbitangle, _orbitradius, _orbitrevolution, _parent) {
		a := Angle_Radians((_orbitangle >= 0) ? Mod(_orbitangle, 360) : 360 - Mod(-_orbitangle, -360))

		this.name := _name

		this.diameter := [_diameter]

		this.orbit := {"x": _orbitradius*Cos(a)
			, "y": _orbitradius*Sin(a)
			, "radius": _orbitradius
			, "revolution": _orbitrevolution}

		this.parent := _parent

		this.pBrush := (_name == "Sun" ? vCanvas.NewBrush("FF", {1: "FFFF00", 2: "00FFFF", 3: "FFFFFF"}[Random(1, 3)]) : vCanvas.NewLineBrush(_diameter/2, _diameter/2, _diameter, _diameter, "FF", Random_Color(), "FF", Random_Color(), ((Between(_orbitangle, 67.5, 112.5) || Between(_orbitangle, 247.5, 292.5)) ? 1 : (Between(_orbitangle, 202.5, 247.5) || Between(_orbitangle, 22.5, 67.5)) ? 2 : (Between(_orbitangle, 112.5, 157.5) || Between(_orbitangle, 292.5, 337.5)) ? 3 : 0)))  ;Horizontal (67.5 -> 112.5 || 247.5 -> 292.5), ForwardDiagonal (202.5 -> 247.5 || 22.5 -> 67.5), Backward Diagonal (112.5 -> 157.5 || 292.5 -> 337.5), Vertical (157.5 -> 202.5 || 337.5 -> 22.5)

		Return (this)
	}

	Update(_date) {
		a := Angle_Radians((_date/this.orbit.revolution)*360)

		this.ratio := (this.diameter[2] := (this.diameter[1] + this.diameter[1]*Sin(a)/2)*this.parent.ratio)/this.diameter[1]
		this.depth := this.parent.depth + (this.ratio - 1)*this.orbit.radius*2

		this.h := this.parent.h + this.orbit.x*Cos(a)*this.parent.ratio, this.k := this.parent.k + this.orbit.y*Sin(a + 1.5707963267948966192313216916398)*this.parent.ratio
	}

	Draw(_date) {
		Gdip_FillEllipse(vCanvas.G, this.pBrush, this.h - this.diameter[2]/2, this.k - this.diameter[2]/2, this.diameter[2], this.diameter[2])
		If (this.parent.name != "Sun")
			Gdip_TextToGraphics(vCanvas.G, this.name, "x" . this.h + this.diameter[2]/2 . " y" . this.k - this.diameter[2]/2 . " cFFFFFFFF Bold r4 s10", "Arial")
		Else
			Gdip_TextToGraphics(vCanvas.G, this.name . "`n" . Round(Mod((_date/this.orbit.revolution)*360, 360)), "x" . this.h + this.diameter[2]/2 . " y" . this.k - this.diameter[2]/2 . " cFFFFFFFF Bold r4 s12", "Arial")
	}
}
There is no support for collision or physics in general lol, I just wanted to create a simulated z-axis for something else. Even so, I think it's pretty neat :)
User avatar
Hellbent
Posts: 2103
Joined: 23 Sep 2017, 13:34

Re: GDIP Art ?

09 Nov 2019, 03:49

.


Maurer Rose

https://en.wikipedia.org/wiki/Maurer_rose

Insipired By: https://www.youtube.com/watch?v=4uU9lZ-HSqA


All necessary Gdip functions included.

Code: Select all

#SingleInstance,Force
SetBatchLines,-1
CoordMode,Mouse,Client
global Main:={},Petals:=2,Sweep:=11
Gdip_StartUp()
DllCall("gdiplus\GdipCreatePen1", "UInt", "0xffA50D05", "float", 3, "int", 2, A_PtrSize ? "UPtr*" : "UInt*", PetalPen)
DllCall("gdiplus\GdipCreatePen1", "UInt", "0xff000000", "float", 1, "int", 2, A_PtrSize ? "UPtr*" : "UInt*", SweepPen)
DllCall("gdiplus\GdipCreateSolidFill", "UInt", "0xff087864", A_PtrSize ? "UPtr*" : "UInt*", BBrush)
CreateWindow()
SetTimer,Update,10
return
GuiClose:
	ExitApp
Update:
	MouseGetPos,nx,ny
	if((nx!=ox||ny!=oy)&&WinActive("Ahk_Id " Main.HWND)){
		DllCall("gdiplus\GdipGraphicsClear", A_PtrSize ? "UPtr" : "UInt", Main.G, "int", ARGB)
		ox:=nx,oy:=ny,SweepList:="",PetalList:="",Sweep:=nx//5+Ran(),Petals:=(ny>300)?(7):(ny>250)?(6):(ny>200)?(5):(ny>150)?(4):(ny>100)?(3):(2)
		Loop,360
			SweepList.=Calculate(A_Index*Sweep), PetalList.=Calculate(A_Index*3.14159/180)
		Gdip_FillRectangle( Main.G,BBrush,-1,-1,380+2,280+2),Gdip_DrawLines(Main.G,SweepPen,SweepList)
		Gdip_DrawLines(Main.G,PetalPen,PetalList),BitBlt(Main.hdc1,10,10,380,280,Main.hdc2,0,0)
	}
	return
Ran(){
	Random,out,1,9
	return out
}
Calculate(InputValue){
	r:=135*Sin(Petals*InputValue)
	x:=r*cos(InputValue)+190
	y:=r*sin(InputValue)+140
	return x "," y "|"
}
CreateWindow(){
	Gui,1:+AlwaysOnTop +HwndWindowHwnd -DPIScale
	Gui,1:Color,1C2125
	Main.HWND:=WindowHwnd,Main.hdc1:=GetDC(Main.HWND),Main.hdc2:=CreateCompatibleDC()
	Main.hbm:=CreateDIBSection(380,280),Main.obm:=SelectObject(Main.hdc2,Main.hbm)
	Main.G:=Gdip_GraphicsFromHDC(Main.hdc2),Gdip_SetSmoothingMode(Main.G,4)
	Gui,1:Show,h300 w400,Maurer_rose	
}
;-------------------------------------------------------------------------------------------------------------------------
;-------------------------------------------------Gdip functions----------------------------------------------------------
;-------------------------------------------------------------------------------------------------------------------------
;-------------------------------------------------------------------------------------------------------------------------
Gdip_Startup(){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	if !DllCall("GetModuleHandle", "str", "gdiplus", Ptr)
		DllCall("LoadLibrary", "str", "gdiplus")
	VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
	DllCall("gdiplus\GdiplusStartup", A_PtrSize ? "UPtr*" : "uint*", pToken, Ptr, &si, Ptr, 0)
	return pToken
}
Gdip_FillRectangle(pGraphics, pBrush, x, y, w, h){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	return DllCall("gdiplus\GdipFillRectangle", Ptr, pGraphics, Ptr, pBrush, "float", x, "float", y, "float", w, "float", h)
}
Gdip_DrawLines(pGraphics, pPen, Points){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	StringSplit, Points, Points, |
	VarSetCapacity(PointF, 8*Points0)
	Loop, %Points0%
	{
		StringSplit, Coord, Points%A_Index%, `,
		NumPut(Coord1, PointF, 8*(A_Index-1), "float"), NumPut(Coord2, PointF, (8*(A_Index-1))+4, "float")
	}
	return DllCall("gdiplus\GdipDrawLines", Ptr, pGraphics, Ptr, pPen, Ptr, &PointF, "int", Points0)
}
BitBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, Raster=""){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	return DllCall("gdi32\BitBlt", Ptr, dDC, "int", dx, "int", dy, "int", dw, "int", dh, Ptr, sDC, "int", sx, "int", sy, "uint", Raster ? Raster : 0x00CC0020)
}
GetDC(hwnd=0){
	return DllCall("GetDC", A_PtrSize ? "UPtr" : "UInt", hwnd)
}
CreateCompatibleDC(hdc=0){
   return DllCall("CreateCompatibleDC", A_PtrSize ? "UPtr" : "UInt", hdc)
}
CreateDIBSection(w, h, hdc="", bpp=32, ByRef ppvBits=0){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	hdc2 := hdc ? hdc : GetDC()
	VarSetCapacity(bi, 40, 0)
	NumPut(w, bi, 4, "uint"), NumPut(h, bi, 8, "uint"), NumPut(40, bi, 0, "uint"), NumPut(1, bi, 12, "ushort"), NumPut(0, bi, 16, "uInt"), NumPut(bpp, bi, 14, "ushort")
	hbm := DllCall("CreateDIBSection", Ptr, hdc2, Ptr, &bi, "uint", 0, A_PtrSize ? "UPtr*" : "uint*", ppvBits, Ptr, 0, "uint", 0, Ptr)
	if !hdc
		ReleaseDC(hdc2)
	return hbm
}
SelectObject(hdc, hgdiobj){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	return DllCall("SelectObject", Ptr, hdc, Ptr, hgdiobj)
}
Gdip_GraphicsFromHDC(hdc){
    DllCall("gdiplus\GdipCreateFromHDC", A_PtrSize ? "UPtr" : "UInt", hdc, A_PtrSize ? "UPtr*" : "UInt*", pGraphics)
    return pGraphics
}
Gdip_SetSmoothingMode(pGraphics, SmoothingMode){
   return DllCall("gdiplus\GdipSetSmoothingMode", A_PtrSize ? "UPtr" : "UInt", pGraphics, "int", SmoothingMode)
}
ReleaseDC(hdc, hwnd=0){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	return DllCall("ReleaseDC", Ptr, hwnd, Ptr, hdc)
}

.
test gif 1.gif
test gif 1.gif (758.58 KiB) Viewed 4369 times
User avatar
Hellbent
Posts: 2103
Joined: 23 Sep 2017, 13:34

Re: GDIP Art ?

27 Mar 2020, 16:44

I have no idea what inspired this. Nope, no idea at all.

***Viewer Discretion Advised***

Code: Select all

;***************************************************************************************************
#Include <My Altered Gdip Lib>  ;<------       Replace with your copy of GDIP
;***************************************************************************************************
#SingleInstance, Force
SetBatchLines, -1
MyWindow := New LayeredWindow( x := "" , y := "" , w := 302 , h := 302 , window := 2 , title := " " , smoothing := 2 , options := "+AlwaysOnTop -DPIScale" , autoShow := 1 , GdipStart := 1 , WinMover := {x:0,y:0,w:300,h:30} )
Brush1 := Gdip_BrushCreateSolid( "0xFF880000" ), Pen1 := Gdip_CreatePen( "0xFF000000" , 1 ), BP := []
Loop, 100
	BP[A_Index] := {X:Ran(20,250), Y:Ran(20,250), W:Ran(0,20), Phase:Ran(0,1), Co:Ran(0,3), Max: Max := Ran(10,50), Min: Ran(2,Max)}
MyWindow.PaintBackground( BackgroundColor := "0xFF000000" )
SetTimer, Blob, 10
return
2GuiContextMenu:
*ESC::
	ExitApp
Numpad1::
	inject := 1
	return
Ran(Min,Max){
	Random, Out, Min, Max
	return Out
}	
Blob:
	if(Inject){
		Inject := 0
		loop, 10
			BP.Push({X:Ran(20,250), Y:Ran(0,300), W:Ran(0,20), Phase:Ran(0,1), Co:Ran(0,3), Max: Max := Ran(10,50), Min: Ran(2,Max)})
	}
	loop, % BP.Length(){
		(BP[A_Index].Phase=1&&BP[A_Index].W<BP[A_Index].Min)?(BP[A_Index].Phase := 0):(BP[A_Index].Phase=0&&BP[A_Index].W>BP[A_Index].Max)?(BP[A_Index].Phase := 1 , BP[A_Index].Co += 1)
		(BP[A_Index].Phase=1)?(BP[A_Index].X += 1,BP[A_Index].Y += 1,BP[A_Index].W -= 2,BP[A_Index].H -= 2):(BP[A_Index].X -= 1,BP[A_Index].Y -= 1,BP[A_Index].W += 2,BP[A_Index].H += 2)
		(BP[A_Index].Co>4)?(BP[A_Index] := {X:Ran(0,300), Y:Ran(0,300), W:Ran(0,20), Phase:Ran(0,1), Co:Ran(0,3), Max: Max := Ran(10,50), Min: Ran(2,Max)})
		Gdip_FillEllipse(MyWindow.G, Brush1, BP[A_Index].x, BP[A_Index].y, BP[A_Index].w, BP[A_Index].w)
		Brush3 := Gdip_CreateLineBrushFromRect( BP[A_Index].x, BP[A_Index].y, BP[A_Index].w, BP[A_Index].w , "0x55660000" , "0xff000000" , 1 , 1 )
		Gdip_FillEllipse(MyWindow.G, Brush3, BP[A_Index].x, BP[A_Index].y, BP[A_Index].w, BP[A_Index].w)
		Gdip_DeleteBrush( Brush3 )
		Gdip_DrawEllipse(MyWindow.G, Pen1, BP[A_Index].x, BP[A_Index].y, BP[A_Index].w, BP[A_Index].w)
	}
	if(Ran(0,10)=5){
		if(Ran(1,2)=2&&BP.Length()>1)
			loop, 5
				BP.Pop()
		else
			loop, 10
				BP.Push({X:Ran(20,250), Y:Ran(0,300), W:Ran(0,20), Phase:Ran(0,1), Co:Ran(0,3), Max: Max := Ran(10,50), Min: Ran(2,Max)})
	}
	if(BP.Length()>200){
		BP := []
		Loop, 30
			BP[A_Index] := {X:Ran(0,300), Y:Ran(0,300), W:Ran(0,20), Phase:Ran(0,1), Co:Ran(0,3), Max: Max := Ran(10,50), Min: Ran(2,Max)}
	}
	MyWindow.UpdateWindow()
	return	
class LayeredWindow	{
	__New( x := 0 , y := 0 , w := 100 , h := 100 , window := 1 , title := " " , smoothing := 4 , options := "" , autoShow := 1 , GdipStart := 0 , WinMover := "" , BackgroundColor := "" ){
		This.X := x , This.Y := y , This.W := w , This.H := h 
		This.Window := window , This.Title := title
		This.Options := options , This.Smoothing := smoothing
		( GdipStart ) ? ( This.Token := Gdip_Startup() )
		This._CreateWindow()
		( autoShow ) ? ( This.ShowWindow() )
		This._SetUpdateLayeredWindow()
		( WinMover ) ? ( This._AddMoveTrigger( WinMover ) )
		( BackgroundColor ) ? ( This.PaintBackground( BackgroundColor , 1 ) )
	}
	_CreateWindow(){
		Gui , % This.Window ": New" , % " +E0x80000 +LastFound -Caption " This.Options 
		This.Hwnd := WinExist()
		This.hbm := CreateDIBSection( This.W , This.H )
		This.hdc := CreateCompatibleDC()
		This.obm := SelectObject( This.hdc , This.hbm )
		This.G := Gdip_GraphicsFromHDC( This.hdc )
		Gdip_SetSmoothingMode( This.G , This.Smoothing )
	}
	_SetUpdateLayeredWindow(){
		UpdateLayeredWindow( This.hwnd , This.hdc , This.X , This.Y , This.W , This.H )
	}
	UpdateWindow(){
		UpdateLayeredWindow( This.hwnd , This.hdc )
	}
	ShowWindow( update := 1 , Position := "" ){ 
		if( !Position )
			Gui , % This.Window ": Show" , % "w" This.W " h" This.H  , % ( This.Title ) ? ( This.Title ) : ( "" )
		else
			Gui , % This.Window ": Show" , % "x" Position.X " y" Position.Y "w" Position.W " h" Position.H  , % ( This.Title ) ? ( This.Title )  : ( "" )
		( update ) ? ( This.UpdateWindow() )
	}
	_AddMoveTrigger( positons ){ 
		local hwnd , bd
		Gui , % This.Window " : Add" , Text , % "x" positons.x " y" positons.y " w" positons.w " h" positons.h " hwndhwnd"
		This.MoveHwnd := hwnd
		bd := This._WindowMover.Bind( This )
		GuiControl , % This.Window ": +G" , % This.MoveHwnd , % bd
	}
	_WindowMover(){ 
		PostMessage, 0xA1 , 2
	}
	PaintBackground( BackgroundColor := "0xFF000000" , update := 0){ 
		local Brush
		This.BackgroundColor := BackgroundColor
		Brush := Gdip_BrushCreateSolid( BackgroundColor )
		Gdip_FillRectangle( This.G , Brush , -1 , -1 , This.W+2 , This.H+2 )
		Gdip_DeleteBrush( Brush )
		( update ) ? ( This.UpdateWindow() )
	}
}
Spoiler
Last edited by Hellbent on 27 Mar 2020, 19:10, edited 1 time in total.
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

Re: GDIP Art ?

27 Mar 2020, 17:16

@Hellbent , I hadn't seen this thread. Amazing. Thank you!
Regards,
burque505

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: IfThenElse and 149 guests