grabpixmap and save with alpha

BlitzMax Forums/BlitzMax Programming/grabpixmap and save with alpha

Think I've cracked it, this probably isn't the fastest way to do this but I'm not too worried about that, just that it works. This is just OpenGL version but I'm sure DX shouldn't be too hard to replicate.

Basically I render the scene in 2 passes, one with colormask set to not draw to alpha, the other with alpha. Although if you use lightblend then the first pass needs to be drawn with no color mask, but the second pass should always be alpha only. Then I made 2 new grabpixmap functions, one that grabs colour only and another that grabs alpha. I then merge these pixmaps together dividing each colour in the pixmap by the alpha to restore the colour to its original value.

SuperStrict

SetGraphicsDriver GLMax2DDriver() 

Graphics (1000, 500,,,GRAPHICS_ALPHABUFFER) 



SetClsColor2 0, 0, 0, 0
Cls

SeedRnd 0

For Local c:Int = 1 To 50

	Local size:Int = Rnd(50, 125) 
	Local x:Int = Rnd(100, 300) 
	Local y:Int = Rnd(100, 300) 
	
	SetColor Rnd(255), Rnd(255), Rnd(255) 
	
	ColorMaskColor
	
	SetBlend ALPHABLEND
	
	SetAlpha.5
	
	DrawOval x, y, size, size
	
	SetColor 150, 150, 150
	
	ResetColorMask
	
	SetBlend LIGHTBLEND
	
	SetAlpha.5
	
	x = Rnd(100, 300) 
	y = Rnd(100, 300) 
	
	DrawOval x, y, size, size
	
Next

SeedRnd 0

ColorMaskAlpha

For Local c:Int = 1 To 50

	Local size:Int = Rnd(50, 125) 
	Local x:Int = Rnd(100, 300) 
	Local y:Int = Rnd(100, 300) 
	
	SetColor Rnd(255), Rnd(255), Rnd(255) 
	
	SetBlendAlphaONE
	        
	SetAlpha.5
	DrawOval x, y, size, size
	
	glEnable GL_BLEND
	glBlendFunc GL_SRC_ALPHA, GL_ONE
	
	SetColor 150, 150, 150
	
	SetAlpha.5
	
	x = Rnd(100, 300) 
	y = Rnd(100, 300) 
	
	DrawOval x, y, size, size

        
Next

glColorMask(True, True, True, True) 
Local pixmapalpha:TPixmap = GrabPixmapAlpha(0, 0, 500, 500) 
Local pixmapcolor:TPixmap = GrabPixmapColor(0, 0, 500, 500) 
Local pixmapfinal:TPixmap = mergepixmaps(pixmapalpha, pixmapcolor) 

SavePixmapPNG(pixmapfinal, "test.png") 
SetAlpha 1
SetColor 255, 255, 255
SetBlend ALPHABLEND
Local testimg:TImage = LoadImage("test.png") 
DrawImage testimg, 500, 0

Flip
WaitKey

Function SetClsColor2(red:Float, green:Float, blue:Float, alpha:Float = 255) 
	glClearColor red / 255.0, green / 255.0, blue / 255.0, alpha / 255.0
End Function

Function GrabPixmapAlpha:TPixmap(x:Float, y:Float, w:Float, h:Float) 

	Local p:TPixmap = CreatePixmap(w, h, PF_A8) 
	glReadPixels x, GraphicsHeight() - h - y, w, h, GL_ALPHA, GL_UNSIGNED_BYTE, p.pixels
	p = YFlipPixmap(p) 
	
	Return ConvertPixmap(p, PF_RGBA8888) 
        
End Function

Function GrabPixmapColor:TPixmap(x:Float, y:Float, w:Float, h:Float) 

	Local p:TPixmap = CreatePixmap(w, h, PF_RGB888) 
	glReadPixels x, GraphicsHeight() - h - y, w, h, GL_RGB, GL_UNSIGNED_BYTE, p.pixels
	p = YFlipPixmap(p) 
	
	Return ConvertPixmap(p, PF_RGBA8888) 
        
End Function

Function SetBlendAlphaSRC() 
	glEnable GL_BLEND
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) 
	glDisable GL_ALPHA_TEST
End Function

Function SetBlendAlphaONE() 
	glEnable GL_BLEND
	glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA) 
	glDisable GL_ALPHA_TEST
End Function

Function ColorMaskColor() 
	glColorMask(True, True, True, False) 
End Function

Function ColorMaskAlpha() 
	glColorMask(False, False, False, True) 
End Function

Function ResetColorMask() 
	glColorMask(True, True, True, True) 
End Function

Function mergepixmaps:TPixmap(alpha:TPixmap, color:TPixmap) 
	Local p:TPixmap = CreatePixmap(alpha.width, alpha.height, PF_RGBA8888) 
	ClearPixels(p, 0) 
	Local c:Int
	Local a:Int
	Local r:Int
	Local g:Int
	Local b:Int
	Local t1:Int
	For Local x:Int = 0 To alpha.width - 1
		For Local y:Int = 0 To alpha.height - 1
			a = ReadPixel(alpha, x, y) 
			c = ReadPixel(color, x, y) 
			b = c & $000000FF
			g = (c & $0000FF00) Shr 8
			r = (c & $00FF0000) Shr 16
			t1 = (a & $FF000000) Shr 24
			If r Then r = Float(r) / (Float(t1) / 255.0) 
			If g Then g = Float(g) / (Float(t1) / 255.0) 
			If b Then b = Float(b) / (Float(t1) / 255.0) 
			WritePixel(p, x, y, b + (g Shl 8) + (r Shl 16) + (t1 Shl 24)) 
		Next
	Next
	Return p
End Function


This example shows how to use alphablend and lightblend in the same scene.