MultiplyImage Function
Monkey Forums/Monkey Code/MultiplyImage Function| 
 | ||
| This code was re-factored from inside my current project where it generates colored versions of bitmap font images to avoid the SetColor DrawImage penalty in html5. [edit] tested and fixed code x 2 [edit2] changed white pass to to additive 
' processimage.monkey
' 
' the beginnings of an image processing toolkit for monkey
'
' images can ONLY be processed 
'   once they are fully loaded
'   from inside an OnRender handler
'
' a Cls command should be used after processing any images
Strict
Import mojo
Function Main%()
	New TestProcess()
	Return 0
End
Class TestProcess Extends App
	Field font:Image
	Field redfont:Image
	Method OnCreate%()
		font=LoadImage("motorwerk.png")
		Return 0
	End
	
	Method OnRender%()
	
		If Not redfont
			redfont=MultiplyImage(font,$ff0000)		
		Endif
		
		Cls
		DrawImage redfont,0,0
		Return 0
	End
	
End
Function MultiplyImage:Image( image:Image,rgb% )
	Return ProcessImage( image,New MultiplyPixel(rgb) )
End
Interface PixelProcessor
	Method ProcessPixel%( argb% )
End
Class MultiplyPixel Implements PixelProcessor
	Field factor%
	
	Method New(rgb%)
		factor=rgb
	End
	Method ProcessPixel%(argb%)
		Local a24%=argb & $ff000000
		Local r16%=((((argb Shr 16)&$FF)*((factor Shr 16)&$FF))Shr 8)Shl 16
		Local g8%=((((argb Shr 8)&$FF)*((factor Shr 8)&$FF))Shr 8)Shl 8
		Local b0%=((((argb)&$FF)*((factor)&$FF))Shr 8)
		Return a24|r16|g8|b0
	End
End
' batch convert image by reading display size tiles of pixels
' does two pass, white is for color and black is for mask
' write result of callback processing to black 
' return result in new image
Function ProcessImage:Image(image:Image,pixelproc:PixelProcessor)		
	Local width%=image.Width()
	Local height%=image.Height()
			
	Local stepw%=DeviceWidth()
	Local steph%=DeviceHeight()
	
	If stepw>width stepw=width
	If steph>height steph=height		
	
	Local black:=New Int[width*height]
	Local white:=New Int[width*height]
	
	Local x%=0
	Local y%=0
	While y<height
		Local h%=height-y
		If h>steph h=steph
		While x<width
			Local w%=width-x
			If w>stepw w=stepw				
			
			Cls 255,255,255
			SetColor 0,0,0
			DrawImage image,-x,-y	
	
			ReadPixels(black,0,0,w,h,y*width+x,width)
	
			Cls 0,0,0
			SetBlend AdditiveBlend
			SetColor 255,255,255
			DrawImage image,-x,-y
			SetBlend AlphaBlend
	
			ReadPixels(white,0,0,w,h,y*width+x,width)				
			
			x+=stepw				
		Wend
		y+=steph
		x=0
	Wend
	Local n%=width*height
	For Local i%=0 Until n
		Local a%=255-(black[i] & $ff)
		Local rgb%=white[i] & $ffffff
		Local rgba%=(a Shl 24) | rgb
		black[i]=pixelproc.ProcessPixel(rgba)
	Next
	
	Local mult:=CreateImage(width,height)
	mult.WritePixels black,0,0,width,height		
	Return mult
End
	
 | 
| 
 | ||
| not bad!  To note, this still has all the same limitations that come with ReadPixels (no alpha), plus a small penalty for producing the bitmap, of course.   IIRC, Android has some slowness with colored images too, so baking a bitmap there could also be beneficial.  In the case of Android, since it's an ogl target, you can also replace readpixels with GetImageData from gles11 and regain the alpha support. | 
| 
 | ||
| It uses white black sampling which should solve the alpha problem. Actually there is possibly a problem with the rgb which my recent change to additive has probably not solved. It's likely I need extra code as my ARGB input is I think now pre-multiplied alpha (darker the more transparent the src). Monkey should probably if it's not already be using pre-multiplied pixel format internally as it is best practice on a lot of EGL chipsets but the Read and Write pixel commands should logically be using plain ARGB so version 3 here we go... TBC |