graphics: kaleidoscope/brush mirrors

Post your working scripts, libraries and tools
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

graphics: kaleidoscope/brush mirrors

07 Aug 2017, 14:37

The idea behind this script is that when you draw 1 pixel onto a bitmap, 3 other pixels are also drawn. It as though there were mirrors, so you get a kaleidoscope or brush mirrors effect (similar to MacPaint).

I had tried something similar with detecting and sending clicks to MS Paint, but it didn't work very well, so in effect I ended up creating the basis of a bitmap editor in order to achieve this.

If anyone has built a bitmap editor in AutoHotkey it would be nice to know. It would not necessarily be so difficult to achieve this, although certain features could be trickier to implement.

I have a few queries:
- which is the better approach for constant screen updating: STM_SETIMAGE or UpdateLayeredWindow?
- could the script be modified to show a standard GUI window, with other controls ... is it possible to draw on top of some/all of a window/control (I had some trouble trying to achieve this, I'm not familiar with WS_EX_LAYERED or layered windows)
- anything to smoothen/quicken the drawing of pixels when the mouse is held down (e.g. MS Paint (Windows XP) is very responsive)

Code: Select all

;kaleidoscope/brush mirrors by jeeswg
;this script could also form the basis of a bitmap editor
;based on Gdip.Tutorial.12-Pixelate.a.bitmap.using.machine.code.ahk
;requires Gdip.ahk or Gdip_All.ahk

#SingleInstance, Force
#NoEnv
SetBatchLines, -1
ListLines, Off

;settings:
vDoKaleidoscope := 1 ;similar to Brush Mirrors (MacPaint)
vColFgd := 0xff008080 ;teal
vColBgd := 0xffffff00 ;yellow

;colour list:
;Progress/SplashImage
;https://autohotkey.com/docs/commands/Progress.htm

pToken := Gdip_Startup()
OnExit, Exit
Gui, 1: -Caption +E0x80000 +LastFound +OwnDialogs +Owner +HwndhWnd1
Gui, 1: Show, NA
GroupAdd, WinGroupGui, % "ahk_id " hWnd1
vImgW := 600, vImgH := 600
;increase width/height if not multiples of 8 (each 'pixel' is 8x8)
Mod(vImgW, 8) && vImgW := vImgW - Mod(vImgW, 8) + 8
Mod(vImgH, 8) && vImgH := vImgH - Mod(vImgH, 8) + 8
;increase width/height if not multiples of 32 (each 'pixel' is 8x8, and there are 4 quadrants, 8*4=32)
Mod(vImgW, 32) && vImgW := vImgW - Mod(vImgW, 32) + 32
Mod(vImgH, 32) && vImgH := vImgH - Mod(vImgH, 32) + 32
pBitmap := Gdip_CreateBitmap(vImgW, vImgH)
hbm := CreateDIBSection(vImgW, vImgH), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
pBrush := pBrushFgd := Gdip_BrushCreateSolid(vColFgd)
pBrushBgd := Gdip_BrushCreateSolid(vColBgd)
vColIsFgd := 1
Gdip_FillRectangle(G, pBrushBgd, vX, vY, vImgW, vImgH)
;OnMessage(0x201, "WM_LBUTTONDOWN")
UpdateLayeredWindow(hWnd1, hdc, (A_ScreenWidth-vImgW)//2, (A_ScreenHeight-vImgH)//2, vImgW, vImgH)
return

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

#IfWinActive, ahk_group WinGroupGui
q:: ;draw a pixel
~LButton:: ;draw a pixel
Loop
{
	if (A_Index > 1)
	&& (!GetKeyState("LButton", "P") || InStr(A_ThisHotkey, "q"))
		break
	MouseGetPos, vX, vY, hWnd2
	if (vX = vXLast) && (vY = vYLast)
		continue
	vXLast := vX, vYLast := vY
	if !(hWnd1 = hWnd2)
		return
	vX := vX - Mod(vX, 8) + 4, vY := vY - Mod(vY, 8) + 4

	Gdip_FillRectangle(G, pBrush, vX-4, vY-4, 8, 8)
	if vDoKaleidoscope
	{
		vX2 := vImgW - vX, vY2 := vImgH - vY
		Gdip_FillRectangle(G, pBrush, vX-4, vY2-4, 8, 8)
		Gdip_FillRectangle(G, pBrush, vX2-4, vY-4, 8, 8)
		Gdip_FillRectangle(G, pBrush, vX2-4, vY2-4, 8, 8)
	}
	UpdateLayeredWindow(hWnd1, hdc, (A_ScreenWidth-vImgW)//2, (A_ScreenHeight-vImgH)//2, vImgW, vImgH)
}
return

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

w:: ;save current image to file
vPath = %A_Desktop%\z %A_Now%.png
pBitmap2 := Gdip_CreateBitmapFromHBITMAP(hbm)
Gdip_SaveBitmapToFile(pBitmap2, vPath, 100)
Gdip_DisposeImage(pBitmap2)
return

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

e:: ;set paintbrush colour to foreground/background colour
vColIsFgd := !vColIsFgd
pBrush := vColIsFgd ? pBrushFgd : pBrushBgd
MsgBox, % "colour is " (vColIsFgd ? "foreground" : "background")
return

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

WM_LBUTTONDOWN()
{
	PostMessage, 0xA1, 2 ;WM_NCLBUTTONDOWN := 0xA1
}

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

Esc::
Exit:
Gdip_DisposeImage(pBitmap)
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
Gdip_DeleteGraphics(G)
Gdip_DeleteBrush(pBrushFgd), Gdip_DeleteBrush(pBrushBgd)
Gdip_Shutdown(pToken)
ExitApp
return
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
concepter
Posts: 47
Joined: 24 Aug 2017, 13:02

Re: graphics: kaleidoscope/brush mirrors

04 Dec 2017, 09:08

I'm curious to see how it works but I've tried and the code does not work the way it is.
Helgef
Posts: 4663
Joined: 17 Jul 2016, 01:02
Contact:

Re: graphics: kaleidoscope/brush mirrors

04 Dec 2017, 11:37

It works great for me, thanks for sharing jeeswg, really cool :thumbup: :clap: .
@ concepter, make sure you have Gdip.ahk or Gdip_All.ahk, use the latter if you are using AHK 64 bit.

Cheers.
concepter
Posts: 47
Joined: 24 Aug 2017, 13:02

Re: graphics: kaleidoscope/brush mirrors

04 Dec 2017, 14:33

Sorry everyone, but maybe I'm still wrong:

I use AHK 1.1.26.01 version 64bit ;
I copy Gdip.ahk to lib autohotkey directory ;
Gdip version v1.45 ;
I use Windows 10 pro build 15063 ;
I start paint ;
I press the q key while drawing ;

but nothing happens ...
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: graphics: kaleidoscope/brush mirrors

04 Dec 2017, 15:28

- If you use 64-bit AHK, try Gdip_All.ahk.
- If you use 32-bit AHK, try Gdip_All.ahk or Gdip.ahk.
- The script makes no reference to MS Paint, it creates its own window.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
concepter
Posts: 47
Joined: 24 Aug 2017, 13:02

Re: graphics: kaleidoscope/brush mirrors

04 Dec 2017, 18:19

Thanks, all ok jeeswg,
after the copy of Gdip_All.ahk to the same directory of kaleidoscope.ahk file
I insert the next line into kaleidoscope.ahk :
#include Gdip_All.ahk

interesting effect and start point for new experiment.

Return to “Scripts and Functions”

Who is online

Users browsing this forum: No registered users and 17 guests