Using SpriteMaps / Copying Pixels

BlitzMax Forums/BlitzMax Beginners Area/Using SpriteMaps / Copying Pixels

GuntiNDDS(Posted 2010) [#1]
Hi,

i am looking for a way to copy pixels from an image and creating a second image from them without having to draw to the backbuffer.
Something where all the operation is only being done in the memmory and nothing is being drawn as is with use of grabimage().

Thanks.


Jesse(Posted 2010) [#2]
look up:
loadImage() 'loads from file also converts Tpixmap to Timage
createimage()
lockImage()
pixmapwidth()
pixmapheight()
readPixel()
writepixel()

that should give you an idea on how to do it.


GuntiNDDS(Posted 2010) [#3]
Hi Jesse,

thanks for your input. I will have a look into this.

Even tho i have the feeling that copying pixel by pixel via readpixel() and writepixel() is a kind of slow approach. I had hopes for there being functions for copying entire rectangular regions of pixels at once.
However, i will write a little test app and observe the performance of read/writepixel().


GuntiNDDS(Posted 2010) [#4]
Allright.

My Testapp has been written and performance seems to be no issue using read/writepixel() it can copy 8000 32x32 sprites out in 3.2 seconds.
But even better: i actually found the function i was looking for to copy entire regions. it is called [TPixmap].Window(x,y,w,h) and using this method the 8000 32x32 sprites can be generated in just 0.003 seconds ^^.


Midimaster(Posted 2010) [#5]
Can you please tell me, how to use this TPixmap.window? This sounds very interesting....

I never hearded about it before and in the BlitzMax Help there is no example.


GuntiNDDS(Posted 2010) [#6]
Yes.

Imagine you have a spritesheet with a number of 32x32 sized sprites in it.

first you load it as image:


Local SpriteSheet:TImage = LoadImage("myspritesheet.png")



then you lock it and convert it to a pixmap:


Local SpriteSheetPM:TPixmap = LockImage(SpriteSheet)



and now you can use the Window function to extract parts of the spritesheet (e.g. the single sprites) like this:


Local Sprite1:TPixmap = SpriteSheetPM.Window(0, 0, 32, 32)



in this example it will copy the rectangular area from point xy 0,0 to xy 32,32 from the Spritesheet into a new 32x32 pixmap/graphic. you may then convert this back to a timage or use the drawpixmap() command.


Below is a complete example using the following spritesheet as test:


Graphics 800, 600, 0
SetClsColor(0, 255, 0)
Cls
Flip()

Local SpriteMapPM:TPixmap = LockImage(LoadImage("Spritesheet.png"))

Local SpriteCountX:Int = 6
Local SpriteCountY:Int = 5
Local Border:Int = 1
Local SpriteSize:Int = 32
Local SpriteList:TList = CreateList()

' Draw Spritemap for visual reference
DrawPixmap(SpriteMapPM, 5, 5)

' Create the Sprites from the Spritesheet
For Local a:Int = 0 To SpriteCountY - 1
	For Local b:Int = 0 To SpriteCountX - 1
		Local crSpritePM:TPixmap = SpriteMapPM.Window(Border + (b * (Border + SpriteSize)), Border + (a * (Border + SpriteSize)), SpriteSize, SpriteSize)
		Local nSpritePM:TPixmap = crSpritePM.Copy()
		SpriteList.AddLast(nSpritePM)
	Next
Next

Local StartX:Int = 10
Local StartY:Int = 400
Local Count:Int = 0
' Draw all Sprites in horizontal pattern
For Local a:Int = 1 To SpriteCountX
	For Local b:Int = 1 To SpriteCountY
		DrawPixmap(TPixmap(SpriteList.ToArray()[Count]) , StartX + (a * SpriteSize), StartY + (b * SpriteSize))
		Count:+1
	Next
Next


Flip()
WaitKey()
End



_Skully(Posted 2010) [#7]
I did not know about that pixelmap window method... learn something new every day... Off to clean up some work-around code :)


Jesse(Posted 2010) [#8]
I forgot to mention that one.
It always help to look at the module's source code. Next best thing to having a Manual, Me think.


_Skully(Posted 2010) [#9]
Me2.. Missed it! ;)


Midimaster(Posted 2010) [#10]
Is it possible to use the window as a target? So this could be used like a BITBLT-function?

What else can you do with this?


jsp(Posted 2010) [#11]
Not as target, but you can use the paste method of a pixmap then.
Get your window pixmap and just paste it into the final pixmap at a certain position.

Rem
bbdoc: Paste a pixmap
end rem
Method Paste( source:TPixmap,X,Y )


Jesse(Posted 2010) [#12]

Is it possible to use the window as a target? So this could be used like a BITBLT-function?


if you mean to set the output to a buffer like in blitzBasic then no you can't do that.
most of the pixmap functions are made so you can edit copy and paste pixels from one pixmap to another. copying pixels to a pixmap then bliting to the screen is faster than doing it with pixelfast in blitzBasic.

there are ways to a do it faster but that means figuring and getting into the inner workings of the pixmap modules.
you can access the pixels of the pixmap directly and manipulate them as such.
once you have access you can even copy chunks of pixels directly with memcopy but its use will be mostly benefited when used between two or more pixmaps. The best help for figuring out is to look directly at the module's source code and try to understand it.

here is some simple source code on manipulating pixmaps pixels directly:


need to be carefull when working with pointers as the data can be written to addresses that may cause windows to crash.