Simple image editor

Just starting out? Need help? Post your questions and find answers here.
User avatar
Michael Vogel
Addict
Addict
Posts: 2677
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Simple image editor

Post by Michael Vogel »

Has anyone already made an image editor?

For creating a font editor for Garmin apps. I only need to set the color of single pixels on a zoomed image, some simple functions like line and box would be great. If such a code exists, I'd happy to save some time :mrgreen:

Here are my first quick steps - painting can be done already, but the line and box commands won't work because the LeftButtonDown event is not triggered here :| )...

Code: Select all


; Define

	EnableExplicit

	Enumeration
		#WinFont

		#WinEdit
		#WinDrawBoard
		#WinDrawCanvas

		#WinFontImage
		#WinDrawImage
		#WinDrawPenImage
		#WinDrawLineImage
		#WinDrawBoxImage
		#WinDrawSaveImage
		#WinDrawExitImage
		#WinToolbarImage
		#WinFontCharImage

		#KeyQuit
		#KeyDrawBoard
	EndEnumeration

	Enumeration
		#ToolColorBlack
		#ToolColorDark
		#ToolColorLight
		#ToolColorWhite
		#ToolPen
		#ToolLine
		#ToolBox
		#ToolSave
		#ToolExit
	EndEnumeration

	Structure WinFontType
		DrawBoard.i;		0/1: off/on
		DrawMode.i ;		0-2: paint, line, box
		DrawColor.i;		0-3: black to white
		DrawZoom.i;
		DrawX.i;			image size
		DrawY.i;
		DrawWinX.i;		window and canvas size
		DrawWinY.i;
		DrawWinZ.i;		height of the window (including function bar)
		DrawTooltip.s;	toolbar tooltip
		DrawCursor.i;	toolbar cursor
		;DrawTimer.i
	EndStructure

	Global WinFont.WinFontType

	#ToolbarBackColor=	$ff404040
	#ToolbarLineColor=	$ffe09090
	#ToolbarButtonColor=	$ffD0D0C8
	#ToolbarActiveColor=	$ff10C0D0
	#ToolbarActivePlus=	$ff30F0FF
	#ToolbarHighlight=	$8010C0D0
	#ToolbarGridColor=	$c0a06060

	#ToolbarWidth=		264
	#ToolbarHeight=		28
	#ToolbarBorder=		2
	#ToolbarGap=		3
	#ToolbarTop=		2
	#ToolbarButton=		#ToolbarHeight-#ToolbarTop<<1
	#ToolbarButtonStep=	#ToolbarButton+#ToolbarGap

	#ToolbarBlock=		#ToolbarGap*3
	#ToolbarStart=		#ToolbarBorder
	#ToolbarBlock1=		#ToolbarBorder+#ToolbarButtonStep*(1+#ToolColorWhite)
	#ToolbarBlock2=		#ToolbarBorder+#ToolbarButtonStep*(1+#Toolbox)		+ #ToolbarBlock
	#ToolbarBlock3=		#ToolbarBorder+#ToolbarButtonStep*(1+#ToolExit)		+ #ToolbarBlock*2

	#Undefined=			-#True
	#NoChange=			-#True
	#OutOfRange=		-1<<30
	;#ResetTimer=		4


	DataSection

		; Binary data (608 bytes in 76 blocks)
		DrawPen:
		Data.q $A1A0A0D474E5089,$524448490D000000,$1200000012000000,$8ECE560000000608,$5845742B00000057,$6F69746165724374,$4400656D6954206E,$6C754A2036312069,$3631203931303220,$2B2038323A35333A,$519FF71130303130,$454D497407000000,$3A37150F1007E307,$7009000000254C69,$C11E0000735948
		Data.q $535469C301C11E00,$414D416704000000,$561FC0B8FB10000,$54414449B8010000,$C61411206663DA78,$6465AF733985EB14,$30F7BED1E7783E49,$B0BF97510D526671,$C78FC32187E4342A,$4619876CA7FE7FEE,$AA7F0202433041B4,$14FE2A2831B1F1F3,$E10C5083288C3641,$418FFDFCFD8B0565,$DCF6FEFC887F246
		Data.q $431C8980B7BF1D76,$6FF3E5F0CDF97D3E,$E53EED1EF987FD86,$390DB2463120490,$71DA7071EED68F7C,$219F059C482EFAA4,$54FFFBF9D6978A1A,$D10C81174E086426,$1CBBE7D7D9B4B952,$30431C8835608631,$DAC7801010D7220C,$DEBFAE97E29643D7,$4043648FFBEFEF,$DCCC6F8D79048E9E,$170627D1F0FE2AE0
		Data.q $DA22FD7E3F0C4FBB,$F94E0C9FF6831410,$C33F39ECFA26A0C7,$335E748C185F3BCD,$E8F021944BCA3D1C,$F8FE53534E8E0C4F,$4957FDE1818BB2A9,$FCFEFE18343B5586,$10CA2756FEBFAFB,$A70D867E36A6F607,$753D89FC864517BC,$CCE338B7757CF851,$713A5E3C62BF0BAA,$60B43088AFF1DDB,$197F2CD5881E7E46
		Data.q $8F70BB7C32317E18,$C91120C401F62441,$74E427175529FCD6,$89AF5E33631017E8,$5AAAF5777EFA7E09,$7BFEFE193FFFA616,$F7F868B80FEFF0CB,$7E7FDFAAB00FCFF7,$CF1BE1F2C6CAFA7C,$CBFDFF9EB81FD7AF,$32DF302F2BEEF8C4,$AE6DBBFACD7ABE31,$4A7CD691114623D5,$FC2BCA330003025C,$C50BD10,$826042AE444E4549
		DrawLine:
		Data.q $A1A0A0D474E5089,$524448490D000000,$1200000012000000,$8ECE560000000608,$5845742B00000057,$6F69746165724374,$4400656D6954206E,$6C754A2036312069,$3631203931303220,$2B2038323A35333A,$519FF71130303130,$454D497407000000,$C308120F1007E307,$7009000000DFF74E,$C11E0000735948
		Data.q $535469C301C11E00,$414D416704000000,$561FC0B8FB10000,$5441444988000000,$46012A06063DA78,$FC4BA3FF8BECCC11,$302C418A48CB19FD,$258E4108311F9FC6,$69C35E5A8988BB24,$F204196471BBD010,$728D9AFCC0830C0E,$25C82276C87CC340,$FAD11EBE6A439A8B,$30D467CC3529A20F,$367441A48C30D8A
		Data.q $E2D8906124C06190,$2702766A472E8CDF,$4A7CB00644BE500D,$1C9708BCDA011652,$28C89A590B1AF2D5,$A75C9E040006881D,$1BEE1AF5,$826042AE444E4549
		DrawBox:
		Data.q $A1A0A0D474E5089,$524448490D000000,$1200000012000000,$8ECE560000000608,$5845742B00000057,$6F69746165724374,$4400656D6954206E,$6C754A2036312069,$3631203931303220,$2B2038323A35333A,$519FF71130303130,$454D497407000000,$F836180F1007E307,$7009000000FE02C0,$C11E0000735948
		Data.q $535469C301C11E00,$414D416704000000,$561FC0B8FB10000,$54414449ED000000,$46012A06063DA78,$FC4BA3FF8BECCC11,$302C418A48CB19FD,$258E4108311F9FC6,$7018C475F5B60E0C,$60E8418A136370E0,$D778864246EAFB6B,$95F81D08B863D684,$4DE5EEA6D175E246,$F788320EF206BD58,$2B0A0FE2D89CD8BA
		Data.q $C5D16B9B2D9C430C,$FEA7796B6B016098,$7507A3070676DED3,$635E3B0632366BF3,$91B02D2088A0D200,$C20C32002025C801,$69020D0465D58C5F,$4D819C30C5266902,$31867C20D3861AA,$C2D865C20CD203C3,$30186E841BA4FA6D,$4412B9CF89D9C022,$58EB1411B5630235,$B981DE404E96C20D,$8A7A1175613B3D04
		Data.q $721AF7E097500745,$8A9241E6B003C1DE,$17839146A0100A,$F934016B8FA100,$4E4549000000000E,$826042AE44
		DrawSave:
		Data.q $A1A0A0D474E5089,$524448490D000000,$1200000012000000,$8ECE560000000608,$5845742B00000057,$6F69746165724374,$4400656D6954206E,$6C754A2036312069,$3631203931303220,$2B2038323A35333A,$519FF71130303130,$454D497407000000,$F2371D0F1007E307,$70090000002DC6B0,$C11E0000735948
		Data.q $535469C301C11E00,$414D416704000000,$561FC0B8FB10000,$5441444964000000,$998056186063DA78,$657F890C551C717D,$C486B92318661FF2,$9B225FC610B89E3C,$EF2C98604BB64F1F,$436899321086511,$922297043249339F,$9B1602B2629704C2,$390C3744610C5226,$19FDFC9D2800C07D,$5461AA4C51FA88BB
		Data.q $A0321B144BCB,$A749636BC8853FB3,$444E454900000000,$826042AE
		DrawExit:
		Data.q $A1A0A0D474E5089,$524448490D000000,$1200000012000000,$8ECE560000000608,$5845742B00000057,$6F69746165724374,$4400656D6954206E,$6C754A2036312069,$3631203931303220,$2B2038323A35333A,$519FF71130303130,$454D497407000000,$572D220F1007E307,$70090000006B150C,$C11E0000735948
		Data.q $535469C301C11E00,$414D416704000000,$561FC0B8FB10000,$544144495D000000,$666005A06063DA78,$7DC4905AB1471C5F,$2D538618C4FFC646,$2D504619F186024C,$A4853E216D118631,$65C10D9206A71AB8,$219F0C33E0865918,$D78AA02A4E99244C,$24AA7E8954D812A8,$B22D328A11649A48,$124B55896625202
		Data.q $4392ACA9B39A5900,$4E454900000000B5,$826042AE44

	EndDataSection

	UsePNGImageDecoder()
	CatchImage(#WinDrawPenImage,?DrawPen)
	CatchImage(#WinDrawLineImage,?DrawLine)
	CatchImage(#WinDrawBoxImage,?DrawBox)
	CatchImage(#WinDrawSaveImage,?DrawSave)
	CatchImage(#WinDrawExitImage,?DrawExit)

	Procedure Max(a,b)
		If a>b : ProcedureReturn a : Else : ProcedureReturn b : EndIf
	EndProcedure

; EndDefine

Procedure ToolbarIndex(x,y)

	If y>WinFont\DrawWinY+#ToolbarTop And y<WinFont\DrawWinZ-#ToolbarTop
		If x>=#ToolbarStart And x<#ToolbarBlock1
			x-#ToolbarBorder
		ElseIf x>=#ToolbarBlock1+#ToolbarBlock And x<#ToolbarBlock2
			x-#ToolbarBorder-#ToolbarBlock
		ElseIf x>=#ToolbarBlock2+#ToolbarBlock And x<#ToolbarBlock3
			x-#ToolbarBorder-#ToolbarBlock*2
		Else
			x=#OutOfRange
		EndIf
		If x%#ToolbarButtonStep<=#ToolbarButton
			; Debug Str(x)+" > "+Str(x/#ToolbarButtonStep)
			ProcedureReturn x/#ToolbarButtonStep
		EndIf
	EndIf
	ProcedureReturn #Undefined

EndProcedure
Procedure ToolbarOffset(index)

	If index>#ToolBox
		ProcedureReturn #ToolbarBorder+index*#ToolbarButtonStep+#ToolbarBlock*2
	ElseIf index>#ToolColorWhite
		ProcedureReturn #ToolbarBorder+index*#ToolbarButtonStep+#ToolbarBlock
	Else
		ProcedureReturn #ToolbarBorder+index*#ToolbarButtonStep
	EndIf

EndProcedure
Procedure ToolbarInit()

	Protected i,x,c
	;Protected temp.s;	will be replaced by icons

	CreateImage(#WinToolbarImage,#ToolbarWidth,#ToolbarHeight,32,#ToolbarBackColor)
	StartDrawing(ImageOutput(#WinToolbarImage))

	For i=#ToolColorBlack To #ToolExit
		x=#ToolbarBorder+i*#ToolbarButtonStep
		x+#ToolbarBlock*(Bool(i>#ToolColorWhite)+Bool(i>#ToolBox))
		x=ToolbarOffset(i)
		Box(x,#ToolbarTop,#ToolbarButton,#ToolbarButton,#ToolbarLineColor)
		If i<=#ToolColorWhite
			c=$555555*i
		Else
			c=#ToolbarButtonColor
		EndIf
		Box(x+1,#ToolbarTop+1,#ToolbarButton-2,#ToolbarButton-2,c)
		If i>#ToolColorWhite
			;temp=Mid("PLBSX",i-#ToolColorWhite,1)
			;DrawText(x+TextWidth(temp)/2+1,#ToolbarTop+1,temp,#White,#ToolbarButtonColor)
			DrawAlphaImage(ImageID(#WinDrawPenImage-#ToolPen+i),x+3,#ToolbarTop+3)
		EndIf
	Next i

	; 	LineXY(#ToolbarBlock1,0,#ToolbarBlock1,#ToolbarHeight,#Red)
	; 	LineXY(#ToolbarBlock1+#ToolbarBlock,0,#ToolbarBlock1+#ToolbarBlock,#ToolbarHeight,#Red)
	; 	LineXY(#ToolbarBlock2,0,#ToolbarBlock2,#ToolbarHeight,#Red)
	; 	LineXY(#ToolbarBlock2+#ToolbarBlock,0,#ToolbarBlock2+#ToolbarBlock,#ToolbarHeight,#Red)
	; 	LineXY(#ToolbarBlock3,0,#ToolbarBlock3,#ToolbarHeight,#Red)
	; 	LineXY(#ToolbarBlock3+#ToolbarBlock,0,#ToolbarBlock3+#ToolbarBlock,#ToolbarHeight,#Red)

	StopDrawing()

EndProcedure
Procedure ToolbarUpdate(color,mode,update=#Null)

	With WinFont

		If color<>#NoChange And \DrawColor<>color
			\DrawColor=color
			update=#True
		EndIf

		If mode<>#NoChange And \DrawMode<>mode
			\DrawMode=mode
			update=#True
		EndIf

		If update
			StartDrawing(CanvasOutput(#WinDrawCanvas))

			; Toolbar
			LineXY(0,\DrawWinY,\DrawWinX,\DrawWinY,#ToolbarLineColor)
			Box(0,\DrawWinY+1,\DrawWinX,#ToolbarHeight,#ToolbarBackColor)
			DrawImage(ImageID(#WinToolbarImage),0,\DrawWinY+1)

			; Highlight Buttons
			DrawingMode(#PB_2DDrawing_Outlined)
			color=ToolbarOffset(\DrawColor)
			Box(color,\DrawWinY+#ToolbarTop+1,#ToolbarButton,#ToolbarButton,#ToolbarActiveColor)
			Box(color-1,\DrawWinY+#ToolbarTop,#ToolbarButton+2,#ToolbarButton+2,#ToolbarActivePlus)
			color=ToolbarOffset(\DrawMode+#ToolPen)
			Box(color,\DrawWinY+#ToolbarTop+1,#ToolbarButton,#ToolbarButton,#ToolbarActiveColor)
			Box(color-1,\DrawWinY+#ToolbarTop,#ToolbarButton+2,#ToolbarButton+2,#ToolbarActivePlus)

			If \DrawCursor>#Undefined
				DrawingMode(#PB_2DDrawing_AlphaBlend)
				color=ToolbarOffset(\DrawCursor)
				Box(color,\DrawWinY+#ToolbarTop+1,#ToolbarButton,#ToolbarButton,#ToolbarHighlight)
				If \DrawCursor>#ToolColorWhite
					DrawAlphaImage(ImageID(#WinDrawPenImage-#ToolPen+\DrawCursor),color+3,\DrawWinY+#ToolbarTop+4)
				EndIf
			EndIf

			StopDrawing()
		EndIf

	EndWith

EndProcedure
Procedure ToolbarTip(index)

	Protected text.s

	If index<>WinFont\DrawCursor
		WinFont\DrawCursor=index
		ToolbarUpdate(#NoChange,#NoChange,#True)

		Select index
		Case #Undefined
			text=""
		Case #ToolColorBlack
			text="Black Color"
		Case #ToolColorDark
			text="Dark Gray"
		Case #ToolColorLight
			text="Light Gray"
		Case #ToolColorWhite
			text="White Color"
		Case #ToolPen
			text="Drawing Pen"
		Case #ToolLine
			text="Draw Line"
		Case #ToolBox
			text="Draw Box"
		Case #ToolSave
			text="Accept Changes"
		Case #ToolExit
			text="Exit"
		EndSelect

		;If WinFont\DrawTooltip<>text
		WinFont\DrawTooltip=text
		; Debug "> "+text
		GadgetToolTip(#WinDrawCanvas,text)
	EndIf

EndProcedure
Procedure BoardUpdate(init)

	Structure Pixel
		StructureUnion
			RGB.RGBQUAD
			Mem.Long
		EndStructureUnion
	EndStructure

	Protected bmp.Bitmap
	Protected *ptr.Pixel
	Protected Size

	If ImageDepth(#WinDrawImage)<>32
		Debug "PANIK"
		End
	EndIf

	If GetObject_(ImageID(#WinDrawImage),SizeOf(BITMAP),bmp)

		; 	*ptr=bmp\bmBits
		;
		; 	Size=*ptr+ImageWidth(Image)*ImageHeight(Image)<<2
		; 	While *ptr<Size
		; 		*ptr\Mem\l=((#lred * *ptr\RGB\rgbRed&$FF + #lgreen * *ptr\RGB\rgbGreen&$FF + #lblue * *ptr\RGB\rgbBlue&$FF) >> 8)*$10101
		; 		*ptr+4
		; 	Wend

		Protected i,j,x,y

		With WinFont

			StartDrawing(CanvasOutput(#WinDrawCanvas))

			; Image
			;DrawImage(ImageID(#WinDrawImage),0,0,\DrawWinX,\DrawWinY)

			*ptr=bmp\bmBits
			y=\DrawWinY
			For i=1 To \DrawY
				x=0
				y-\DrawZoom
				For j=1 To \DrawX
					Box(x,y,\DrawZoom,\DrawZoom,*ptr\Mem\l)
					*ptr+4
					x+\DrawZoom
				Next j
			Next i

			; Ausnahme - Verbreiterung
			x=\DrawX*\DrawZoom;	(*)
			If init And \DrawWinY<>x
				Box(x,0,\DrawWinX-x-1,\DrawWinY,#ToolbarBackColor)
			EndIf

			; Grid
			DrawingMode(#PB_2DDrawing_AlphaBlend)
			; x=\DrawX*\DrawZoom;	siehe (*)
			y=0
			For i=0 To \DrawY-1
				LineXY(0,y,x,y,#ToolbarGridColor)
				y+\DrawZoom
			Next i

			x=0
			y=\DrawWinY
			For i=0 To \DrawX-1
				LineXY(x,0,x,y,#ToolbarGridColor)
				x+\DrawZoom
			Next i


			StopDrawing()

			If init
				ToolbarUpdate(#NoChange,#NoChange,#True)
			EndIf

		EndWith
	EndIf

EndProcedure
Procedure BoardAction(x,y)

	If y>=0 And y<WinFont\DrawWinY
		If x>=0
			x/WinFont\DrawZoom
			If x<WinFont\DrawX
				y/WinFont\DrawZoom
				StartDrawing(ImageOutput(#WinDrawImage))
				Plot(x,y,$555555*WinFont\DrawColor)
				StopDrawing()
				BoardUpdate(#Null)
			EndIf
		EndIf
	EndIf

EndProcedure

Procedure Main()

	Protected event
	Protected n,x,y

	ToolbarInit()
	WinFont\DrawColor=#ToolColorWhite
	WinFont\DrawMode=#Null

	OpenWindow(#WinFont,16,10,200,200,"Press Ctrl+D",#PB_Window_SizeGadget|#PB_Window_SystemMenu)
	AddKeyboardShortcut(#WinFont,#PB_Shortcut_D|#PB_Shortcut_Control,#KeyDrawBoard)
	AddKeyboardShortcut(#WinFont,#PB_Shortcut_Escape,#KeyQuit)

	OpenWindow(#WinDrawBoard,	200,60,	300,300, "Draw Board",#PB_Window_SystemMenu|#PB_Window_Invisible)
	CanvasGadget(#WinDrawCanvas,0,0,300,300)

	AddKeyboardShortcut(#WinDrawBoard,#PB_Shortcut_D|#PB_Shortcut_Control,#KeyDrawBoard)
	AddKeyboardShortcut(#WinDrawBoard,#PB_Shortcut_Escape,#KeyQuit)
	StickyWindow(#WinDrawBoard,#True)

	CreateImage(#WinFontCharImage,16,20,32)
	StartDrawing(ImageOutput(#WinFontCharImage))
	DrawText(0,0,"W",#White,#Black)
	StopDrawing()

	;AddWindowTimer(#WinDrawBoard,0,50)

	Repeat

		event=WaitWindowEvent()
		Select event

		Case #PB_Event_Gadget,#PB_Event_Menu
			Select EventGadget()

			Case #WinDrawCanvas
				x=GetGadgetAttribute(#WinDrawCanvas,#PB_Canvas_MouseX)
				y=GetGadgetAttribute(#WinDrawCanvas,#PB_Canvas_MouseY)
				Select EventType()
				Case #PB_EventType_MouseLeave
					ToolbarTip(#Undefined)
				Case #PB_EventType_MouseMove
					;WinFont\DrawTimer=#ResetTimer
					If GetGadgetAttribute(#WinDrawCanvas,#PB_Canvas_Buttons) & #PB_Canvas_LeftButton
						BoardAction(x,y)
					EndIf
					n=ToolbarIndex(x,y)
					ToolbarTip(n)
				Case #PB_EventType_LeftButtonDown
					;WinFont\DrawTimer=#ResetTimer
					If y>WinFont\DrawWinY
						n=ToolbarIndex(x,y)
						Select n
						Case #ToolColorBlack To #ToolColorWhite
							ToolbarUpdate(n,#NoChange)
						Case #ToolPen To #ToolBox
							ToolbarUpdate(#NoChange,n-#ToolPen)
						Case #ToolSave
							PostEvent(#PB_Event_Gadget,#WinDrawBoard,#KeyDrawBoard)
						Case #ToolExit
							PostEvent(#PB_Event_Gadget,#WinDrawBoard,#KeyDrawBoard)
						EndSelect
					Else
						BoardAction(x,y)
					EndIf
				EndSelect

			Case #KeyDrawBoard
				WinFont\DrawBoard!1
				With WinFont
					If \DrawBoard
						\DrawCursor=#Undefined
						; SetMessage("Open drawing board...",#True)
						DisableWindow(#WinFont,1)

						CopyImage(#WinFontCharImage,#WinDrawImage)
						\DrawX=ImageWidth(#WinDrawImage)
						\DrawY=ImageHeight(#WinDrawImage)

						n=4
						x=\DrawX
						While x*n<#ToolbarWidth And x*(n+2)<GetSystemMetrics_(#SM_CXSCREEN)
							n+2
						Wend
						y=\DrawY
						While n>4 And y*n>GetSystemMetrics_(#SM_CYSCREEN)-GetSystemMetrics_(#SM_CYCAPTION)-#ToolBarHeight
							n-2
						Wend

						\DrawZoom=n
						\DrawWinX=Max(\DrawX*\DrawZoom,#ToolbarWidth)
						\DrawWinY=\DrawY*\DrawZoom
						\DrawWinZ=\DrawWinY+#ToolbarHeight+1

						ResizeWindow(#WinDrawBoard,#PB_Ignore,#PB_Ignore,\DrawWinX,\DrawWinZ)
						ResizeGadget(#WinDrawCanvas,#PB_Ignore,#PB_Ignore,\DrawWinX,\DrawWinZ)
						BoardUpdate(#True)

						HideWindow(#WinDrawBoard,0)
						SetActiveWindow(#WinDrawBoard)
					Else
						HideWindow(#WinDrawBoard,1)
						DisableWindow(#WinFont,0)
						SetActiveWindow(#WinFont)
					EndIf
				EndWith

			Case #KeyQuit
				PostEvent(#PB_Event_CloseWindow)

			EndSelect

			; Case #PB_Event_Timer
			; With WinFont
			; 	If \DrawBoard And \DrawTimer
			; 		\DrawTimer-1
			; 		If \DrawTimer=0
			; 			ToolbarTip(ToolbarPos(x,y))
			; 		EndIf
			; 	EndIf
			; EndWith

		Case #PB_Event_CloseWindow
			If WinFont\DrawBoard
				PostEvent(#PB_Event_Gadget,#WinDrawBoard,#KeyDrawBoard)
			Else
				End
			EndIf

		EndSelect
	ForEver

EndProcedure

Main()