combining 2 pixmaps, including alpha

BlitzMax Forums/BlitzMax Programming/combining 2 pixmaps, including alpha

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

The finished product. I found a working formula on the apple site.

http://www.devworld.apple.com/documentation/Performance/Conceptual/vImage/Chapter8/chapter_8_section_3.html

SuperStrict

Framework BRL.LinkedList
Import BRL.Pixmap
Import BRL.PNGLoader
Import BRL.StandardIO

'output.png 46 46 tile.png 0 0 letter.png 0 0 score.png 92 0
'output.png 30 30 test1.png 0 0 test2.png 0 0

Type ttilemaker
	Field pixmap:tpixmap
	Field output:String
	Field width:Int
	Field height:Int
	Field layers:tlist = CreateList()
	
	Method Save()
		Local array:Int[,,]
		Local layer:tlayer
		
		For layer = EachIn layers
			If array = Null
				array = PixmapToPixelArray(layer.pixmap,layer.x,layer.y)
			Else
				CombinePixelArrays(array,PixmapToPixelArray(layer.pixmap,layer.x,layer.y))
			End If
		Next

		SavePixelArray(array,output)
	End Method
	
	Method PixmapToPixelArray:Int[,,](pixmap:tpixmap,offsetx:Int=0,offsety:Int=0)
		Local x:Int
		Local y:Int
		Local array:Int[width,height,4]
		Local pixel:Int
		
		For y = 0 Until height
			For x = 0 Until width
				pixel = ReadPixel(pixmap,x+offsetx,y+offsety)
				
				array[x,y,0] = GetA(pixel)
				array[x,y,1] = GetR(pixel)
				array[x,y,2] = GetG(pixel)
				array[x,y,3] = GetB(pixel)
			Next
		Next
		
		Return array
	End Method
	
	Method CombinePixelArrays:Int[,,](bottom:Int[,,],top:Int[,,])
		'this function will take 2 pixel arrays [x,y,rgba] and combine them.
		Local x:Int
		Local y:Int
		Local a:Float
		Local r:Float
		Local g:Float
		Local b:Float
		
		For y = 0 Until height
			For x = 0 Until width
				If top[x,y,0] = 255
					a = 255
					r = top[x,y,1]
					g = top[x,y,2]
					b = top[x,y,3]
				ElseIf top[x,y,0] = 0
					a = bottom[x,y,0]
					r = bottom[x,y,1]
					g = bottom[x,y,2]
					b = bottom[x,y,3]
				Else
					a = (top[x,y,0] * 255 + (255 - top[x,y,0]) * bottom[x,y,0] + 127) / 255
					r = (top[x,y,0] * top[x,y,1] + (((255 - top[x,y,0]) * bottom[x,y,0] + 127) / 255) * bottom[x,y,1] + 127) / a
					g = (top[x,y,0] * top[x,y,2] + (((255 - top[x,y,0]) * bottom[x,y,0] + 127) / 255) * bottom[x,y,2] + 127) / a
					b = (top[x,y,0] * top[x,y,3] + (((255 - top[x,y,0]) * bottom[x,y,0] + 127) / 255) * bottom[x,y,3] + 127) / a
				End If
				bottom[x,y,0] = a
				bottom[x,y,1] = r
				bottom[x,y,2] = g
				bottom[x,y,3] = b
			Next
		Next
	End Method
	
	Method SavePixelArray:Int(array:Int[,,],url:Object)
		Local x:Int
		Local y:Int
		Local savepixmap:tpixmap = CreatePixmap(width,height,PF_BGRA8888)
		
		For y = 0 Until height
			For x = 0 Until width
				WritePixel(savepixmap,x,y,GetRGBA(array[x,y,1],array[x,y,2],array[x,y,3],array[x,y,0]))
			Next
		Next
		
		SavePixmapPNG(savepixmap,url)
	End Method
	
	Method GetRGBA:Int(r:Int,g:Int,b:Int,a:Int=255)
		Return r | (g Shl 8) | (b Shl 16) | (a Shl 24)
	End Method
	
	Method GetA:Int(argb:Int)
		Return argb Shr 24 & %11111111
	End Method
	
	Method GetR:Int(argb:Int)
		Return argb & %11111111
	End Method
	
	Method GetG:Int(argb:Int)
		Return argb Shr 8 & %11111111
	End Method
	
	Method GetB:Int(argb:Int)
		Return argb Shr 16 & %11111111
	End Method
End Type

Function CreateTileMaker:ttilemaker()
	If appargs.length < 5 Return Null
	
	Local tilemaker:ttilemaker = New ttilemaker
	
	tilemaker.output = AppArgs[1]
	tilemaker.width = AppArgs[2].toint()
	tilemaker.height = AppArgs[3].toint()
	
	Local arg:Int = 4
	Local layer:tlayer
	
	While arg <= appargs.length - 3
		layer = New tlayer
		layer.pixmap = LoadPixmapPNG(AppArgs[arg])
		If layer.pixmap = Null Return Null
		layer.x = AppArgs[arg+1].toint()
		layer.y = AppArgs[arg+2].toint()
		tilemaker.layers.addlast(layer)
		arg:+3
	Wend
	
	tilemaker.pixmap = CreatePixmap(tilemaker.width,tilemaker.height,PF_BGRA8888)
	
	Return tilemaker
End Function

Type tlayer
	Field pixmap:tpixmap
	Field x:Int
	Field y:Int
End Type


'-----------------------------------------------------
Local tilemaker:ttilemaker = CreateTileMaker()

If tilemaker <> Null
	tilemaker.Save()
	Print "RESULT=1"
Else
	Print "RESULT=0"
End If