Pixmap to brush?

BlitzMax Forums/MiniB3D Module/Pixmap to brush?

ima747(Posted 2008) [#1]
LoadBrush requires a path, rather than a URL for loading an image so as far as I can determine that means you need to have your images saved as files to load them. I need to be able to turn a pixmap into a brush so I poked around and came up with the following.

Strict

Import sidesign.minib3d

Function LoadBrushPixmap:TBrush(pixmapin:TPixmap,flags=1,u_scale#=1.0,v_scale#=1.0)
	Return PixTBrush.LoadBrushPixmap(pixmapin,flags,u_scale#,v_scale#)
End Function

Function LoadTexturePixmap:TTexture(pixmapin:TPixmap,flags=1)
	Return PixTTexture.LoadTexturePixmap(pixmapin,flags)
End Function

Type PixTBrush Extends TBrush
	Function LoadBrushPixmap:TBrush(pixmapin:TPixmap,flags=1,u_scale#=1.0,v_scale#=1.0)
		Local brush:TBrush=New TBrush
		brush.tex[0]=PixTTexture.LoadTexturePixmap:TTexture(pixmapin,flags)
		brush.no_texs=1
		'brush.tex[0].u_scale#=u_scale#
		'brush.tex[0].v_scale#=v_scale#
				
		Return brush
		
	End Function
End Type

Type PixTTexture Extends TTexture
	Function LoadTexturePixMap:TTexture(pixmapin:TPixmap,flags=1,tex:TTexture=Null)
		Return LoadAnimTexturePixMap:TTexture(pixmapin,flags,0,0,0,1,tex)
	End Function

	Function LoadAnimTexturePixMap:TTexture(pixmapin:TPixmap,flags,frame_width,frame_height,first_frame,frame_count,tex:TTexture=Null)
	
		If flags&128 Then Return LoadCubeMapTexture("pixmap",flags,tex)
	
		If tex=Null Then tex:TTexture=New TTexture
		
		tex.file$="pixmap"
		tex.file_abs$="pixmap"
		
		' set tex.flags before TexInList
		tex.flags=flags
		tex.FilterFlags()
		
		' check to see if texture with same properties exists already, if so return existing texture
		Local old_tex:TTexture
		old_tex=tex.TexInList()
		If old_tex<>Null And old_tex<>tex
			Return old_tex
		Else
			If old_tex<>tex
				ListAddLast(tex_list,tex)
			EndIf
		EndIf
	
		' load pixmap
		tex.pixmap = CopyPixmap(pixmapin)
		
		' check to see if pixmap contain alpha layer, set alpha_present to true if so (do this before converting)
		Local alpha_present=False
		If tex.pixmap.format=PF_RGBA8888 Or tex.pixmap.format=PF_BGRA8888 Or tex.pixmap.format=PF_A8 Then alpha_present=True
	
		' convert pixmap to appropriate format
		If tex.pixmap.format<>PF_RGBA8888
			tex.pixmap=tex.pixmap.Convert(PF_RGBA8888)
		EndIf
		
		' if alpha flag is true and pixmap doesn't contain alpha info, apply alpha based on color values
		If tex.flags&2 And alpha_present=False
			tex.pixmap=ApplyAlpha(tex.pixmap)
		EndIf		
	
		' if mask flag is true, mask pixmap
		If tex.flags&4
			tex.pixmap=MaskPixmap(tex.pixmap,0,0,0)
		EndIf
		
		' ---
		
		' if tex not anim tex, get frame width and height
		If frame_width=0 And frame_height=0
			frame_width=tex.pixmap.width
			frame_height=tex.pixmap.height
		EndIf
	
		' ---
		
		tex.no_frames=frame_count
		tex.gltex=tex.gltex[..tex.no_frames]
	
		' ---
		
		' pixmap -> tex
	
		Local xframes=tex.pixmap.width/frame_width
		Local yframes=tex.pixmap.height/frame_height
			
		Local startx=first_frame Mod xframes
		Local starty=(first_frame/yframes) Mod yframes
			
		Local x=startx
		Local y=starty
	
		Local pixmap:TPixmap
	
		For Local i=0 To tex.no_frames-1
	
			' get static pixmap window. when resize pixmap is called new pixmap will be returned.
			pixmap=tex.pixmap.Window(x*frame_width,y*frame_height,frame_width,frame_height)
			x=x+1
			If x>=xframes
				x=0
				y=y+1
			EndIf
		
			' ---
		
			pixmap=AdjustPixmap(pixmap)
			tex.width=pixmap.width
			tex.height=pixmap.height
			Local width=pixmap.width
			Local height=pixmap.height
	
			Local name
			glGenTextures 1,Varptr name
			glBindtexture GL_TEXTURE_2D,name
	
			Local mipmap
			If tex.flags&8 Then mipmap=True
			Local mip_level=0
			Repeat
				glPixelStorei GL_UNPACK_ROW_LENGTH,pixmap.pitch/BytesPerPixel[pixmap.format]
				glTexImage2D GL_TEXTURE_2D,mip_level,GL_RGBA8,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixels
				If Not mipmap Then Exit
				If width=1 And height=1 Exit
				If width>1 width:/2
				If height>1 height:/2
	
				pixmap=ResizePixmap(pixmap,width,height)
				mip_level:+1
			Forever
			tex.no_mipmaps=mip_level
	
			tex.gltex[i]=name
	
		Next
				
		Return tex
		
	End Function
End Type


which works... only once... every other brush you make is the same as the first. replacing the loadpixmap with a copypixmap and changing the pathstring to a Tpixmap was the only changes I made, but I also don't understand the nuts and bolts of what's going on here with the gl functions so I assume there's something missing between a loaded pixmap and a copy of a pixmap that makes all the difference...


ima747(Posted 2008) [#2]
nevermind, I found it. seems like LoadCubeMapTexture uses the filename provided to determine if the texture already exists somewhere so it might not need to load it. Since everything was being named pixmap it thought it was already loaded. Below is a modified version that creates a fake name for the texture to force it to load, it uses the time and then a random number on the off chance the computer is fast enough to load multiple textures in a millisecond... p.s. I want that computer

you can use this as an include so you don't need it dumped into your code.

Strict

Import sidesign.minib3d

Function LoadBrushPixmap:TBrush(pixmapin:TPixmap,flags=1,u_scale#=1.0,v_scale#=1.0)
	Return PixTBrush.LoadBrushPixmap(pixmapin,flags,u_scale#,v_scale#)
End Function

Function LoadTexturePixmap:TTexture(pixmapin:TPixmap,flags=1)
	Return PixTTexture.LoadTexturePixmap(pixmapin,flags)
End Function

Type PixTBrush Extends TBrush
	Function LoadBrushPixmap:TBrush(pixmapin:TPixmap,flags=1,u_scale#=1.0,v_scale#=1.0)
		Local brush:TBrush=New TBrush
		brush.tex[0]=PixTTexture.LoadTexturePixmap:TTexture(pixmapin,flags)
		brush.no_texs=1
		'brush.tex[0].u_scale#=u_scale#
		'brush.tex[0].v_scale#=v_scale#
				
		Return brush
		
	End Function
End Type

Type PixTTexture Extends TTexture
	Function LoadTexturePixMap:TTexture(pixmapin:TPixmap,flags=1,tex:TTexture=Null)
		Return LoadAnimTexturePixMap:TTexture(pixmapin,flags,0,0,0,1,tex)
	End Function

	Function LoadAnimTexturePixMap:TTexture(pixmapin:TPixmap,flags,frame_width,frame_height,first_frame,frame_count,tex:TTexture=Null)
		Local pixmapFileName$ = "pixmap"+MilliSecs()+Rnd()
		
		If flags&128 Then Return LoadCubeMapTexture(pixmapFileName$,flags,tex)
	
		If tex=Null Then tex:TTexture=New TTexture
		
		tex.file$=pixmapFileName$
		tex.file_abs$=pixmapFileName$
		
		' set tex.flags before TexInList
		tex.flags=flags
		tex.FilterFlags()
		
		' check to see if texture with same properties exists already, if so return existing texture
		Local old_tex:TTexture
		old_tex=tex.TexInList()
		If old_tex<>Null And old_tex<>tex
			Return old_tex
		Else
			If old_tex<>tex
				ListAddLast(tex_list,tex)
			EndIf
		EndIf
	
		' load pixmap
		tex.pixmap = CopyPixmap(pixmapin)
		
		' check to see if pixmap contain alpha layer, set alpha_present to true if so (do this before converting)
		Local alpha_present=False
		If tex.pixmap.format=PF_RGBA8888 Or tex.pixmap.format=PF_BGRA8888 Or tex.pixmap.format=PF_A8 Then alpha_present=True
	
		' convert pixmap to appropriate format
		If tex.pixmap.format<>PF_RGBA8888
			tex.pixmap=tex.pixmap.Convert(PF_RGBA8888)
		EndIf
		
		' if alpha flag is true and pixmap doesn't contain alpha info, apply alpha based on color values
		If tex.flags&2 And alpha_present=False
			tex.pixmap=ApplyAlpha(tex.pixmap)
		EndIf		
	
		' if mask flag is true, mask pixmap
		If tex.flags&4
			tex.pixmap=MaskPixmap(tex.pixmap,0,0,0)
		EndIf
		
		' ---
		
		' if tex not anim tex, get frame width and height
		If frame_width=0 And frame_height=0
			frame_width=tex.pixmap.width
			frame_height=tex.pixmap.height
		EndIf
	
		' ---
		
		tex.no_frames=frame_count
		tex.gltex=tex.gltex[..tex.no_frames]
	
		' ---
		
		' pixmap -> tex
	
		Local xframes=tex.pixmap.width/frame_width
		Local yframes=tex.pixmap.height/frame_height
			
		Local startx=first_frame Mod xframes
		Local starty=(first_frame/yframes) Mod yframes
			
		Local x=startx
		Local y=starty
	
		Local pixmap:TPixmap
	
		For Local i=0 To tex.no_frames-1
	
			' get static pixmap window. when resize pixmap is called new pixmap will be returned.
			pixmap=tex.pixmap.Window(x*frame_width,y*frame_height,frame_width,frame_height)
			x=x+1
			If x>=xframes
				x=0
				y=y+1
			EndIf
		
			' ---
		
			pixmap=AdjustPixmap(pixmap)
			tex.width=pixmap.width
			tex.height=pixmap.height
			Local width=pixmap.width
			Local height=pixmap.height
	
			Local name
			glGenTextures 1,Varptr name
			glBindtexture GL_TEXTURE_2D,name
	
			Local mipmap
			If tex.flags&8 Then mipmap=True
			Local mip_level=0
			Repeat
				glPixelStorei GL_UNPACK_ROW_LENGTH,pixmap.pitch/BytesPerPixel[pixmap.format]
				glTexImage2D GL_TEXTURE_2D,mip_level,GL_RGBA8,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixels
				If Not mipmap Then Exit
				If width=1 And height=1 Exit
				If width>1 width:/2
				If height>1 height:/2
	
				pixmap=ResizePixmap(pixmap,width,height)
				mip_level:+1
			Forever
			tex.no_mipmaps=mip_level
	
			tex.gltex[i]=name
	
		Next
				
		Return tex
		
	End Function
End Type



Krischan(Posted 2015) [#3]
I'm using this function excessively, thanks for that. But I have a small improvement - your function does not clear the tex.pixmap after loading which causes a memory leak each time you load the same pixmap again and again. So I had to add "tex.pixmap = Null" at the end before returning the tex to fix it.

Here my corrected function: