New 2D drawing mode: AlphaAdjust

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
Seymour Clufley
Addict
Addict
Posts: 1233
Joined: Wed Feb 28, 2007 9:13 am
Location: London

New 2D drawing mode: AlphaAdjust

Post by Seymour Clufley »

Something that comes up a lot in my work is the need to use one image as the alpha mask for another. Unfortunately, none of PB's drawing modes are ideal for this. AlphaChannel simply sets the alpha without regard for the target alpha (new alpha is absolute, not relative to original), and AlphaClip paints on top of the source rather than adjust its alpha. I would like a drawing mode that adjusts the target alpha by the source alpha. An appropriate name for it would be AlphaAdjust or AlphaMultiply. Just now, the only way to do this is by using CustomFilterCallback (see demo below), which is very slow compared to a native drawing mode.

Demo of what it would do:

Code: Select all

Procedure RAIM(simg.i,bgcolour.i=#PB_Ignore,title.s="Report alpha image")
	
	If bgcolour=#PB_Ignore
		bgcolour = RGB(17,17,17)
	EndIf
	
	iw.d = ImageWidth(simg)
	ih.d = ImageHeight(simg)
	img = CreateImage(#PB_Any,iw,ih)
	StartDrawing(ImageOutput(img))
	Box(0,0,iw,ih,bgcolour)
	DrawAlphaImage(ImageID(simg),0,0)
	StopDrawing()
	
	
	aimg = CreateImage(#PB_Any,iw,ih,32,bgclr)
	StartDrawing(ImageOutput(aimg))
	DrawAlphaImage(ImageID(img),0,0)
	StopDrawing()
	
	If fit_on_screen
	  d = ExamineDesktops()
	  kw.d = DesktopWidth(0)
	  kh.d = DesktopHeight(0)
	  While iw>kw Or ih>kh
	    iw * 0.999
	    ih * 0.999
	  Wend
	  ResizeImage(aimg,iw,ih)
	EndIf
	
	If Not title=""
		title = "Report Image"
	EndIf
	
	win = OpenWindow(#PB_Any,0,0,iw,ih,title,#PB_Window_BorderLess|#PB_Window_ScreenCentered)
	
	imgad = ImageGadget(#PB_Any,0,0,iw,ih,ImageID(aimg))
	
	escapekey = 1
	spacekey = 2
	returnkey = 3
	AddKeyboardShortcut(win,#PB_Shortcut_Escape,escapekey)
	AddKeyboardShortcut(win,#PB_Shortcut_Space,spacekey)
	AddKeyboardShortcut(win,#PB_Shortcut_Return,returnkey)
	
	killtime = ElapsedMilliseconds()+timelimit
	Repeat
		we = WindowEvent()
		If we
			If we=#PB_Event_Menu
				Break
			EndIf
		Else
			Delay(10)
		EndIf
		If timelimt>0 And ElapsedMilliseconds()>killtime : Break : EndIf
	ForEver
	
	CloseWindow(win)
	
	
	FreeImage(aimg)
	
EndProcedure


Procedure.i AlphaAdjust(x, y, SourceColor, TargetColor)
  
  r.i = Red(TargetColor)
  g.i = Green(TargetColor)
  b.i = Blue(TargetColor)
  a.d = Alpha(TargetColor)
  a_adjuster.d = Alpha(SourceColor)
  a / 255 * a_adjuster
  ProcedureReturn RGBA(r,g,b,a)
  
EndProcedure


iw = 400
ih = 400
img = CreateImage(#PB_Any,iw,ih,32,#PB_Image_Transparent)
StartDrawing(ImageOutput(img))
DrawingMode(#PB_2DDrawing_AlphaBlend)
Box(0,0,OutputWidth(),OutputHeight(),RGBA(255,0,0,128))
StopDrawing()

mask_img = CreateImage(#PB_Any,iw,ih,32,#PB_Image_Transparent)

StartDrawing(ImageOutput(mask_img))
DrawingMode(#PB_2DDrawing_AlphaBlend)
For x = 0 To iw Step 40
  alp.d = 255 - (255 / iw * x)
  Box(x,0,40,ih,RGBA(0,0,0,alp))
Next x
StopDrawing()

StartDrawing(ImageOutput(img))
;DrawingMode(#PB_2DDrawing_AlphaChannel)
DrawingMode(#PB_2DDrawing_CustomFilter) : CustomFilterCallback(@AlphaAdjust())
DrawAlphaImage(ImageID(mask_img),0,0)
StopDrawing()

RAIM(img,#Yellow)
JACK WEBB: "Coding in C is like sculpting a statue using only sandpaper. You can do it, but the result wouldn't be any better. So why bother? Just use the right tools and get the job done."