Colour Changing in Images - fastest way?

BlitzMax Forums/BlitzMax Programming/Colour Changing in Images - fastest way?

Fry Crayola(Posted 2007) [#1]
Tonight's searching revealed that this is an oft discussed topic, but alas I wasn't able to find any answer as to what's likely to be the fastest way between two different methods.

The first is that I load in the image containing all my frames of animation, and before I ever do any drawing with them (and therefore, as I understand it, before the image is ever transferred to video RAM) I use a combination of WritePixel and ReadPixel on the pixmap to change specific pixels to the desired colour values. These pixmaps are then loaded into images for each game object that requires them, and no more colour cycling is done from this point on as everything's ready.

The second method is that I break each animation frame into seven different parts, representing the seven different elements that need recolouring. These parts are greyscale, and therefore when I need to draw the frame to the screen I simply draw each part, in its correct position, using SetColor accordingly.

Each animation frame is around 32x32, but I have no idea how many frames of animation I need so there's certainly a possibility that the image being altered using pixmaps could be as large as 512x512, which I understand would be slower.

The real question is, would any possible delay during the initialisation phase (which will happen every time a new match begins in a football game) be worthwhile for any speed benefit in drawing those frames to the screen, as well as the easier development? Or would greyscale still be the better option?


tonyg(Posted 2007) [#2]
Can't the greyscale method also be done in an initialisation phase? Personally, I wouldn't draw each 'bit' with setcolor even though Blitzmax should be able to handle 140ish images.


Fry Crayola(Posted 2007) [#3]
By using DrawImage/GrabImage without a flip, I guess there could be an initialisation phase for that. There's a potential problem though in that there could be up to 25 different combinations required. If the size of the AnimImage was 512x512, that'd make 25MB just for images, rather than the 2MB or so maximum by drawing each bit.


H&K(Posted 2007) [#4]
3) You make a 3d model of what you are going to animate, then you apply different textures to it, then you animate and grab the inages you want. Then you use these to paste as your sprites. If you split the model into differnt parts ie weapon, body etc you can just change small parts.

(If you think this sounds stupid, go look at diablo ii)


ImaginaryHuman(Posted 2007) [#5]
One thing to bear in mind is that whether you use the grayscale or not, the images will be drawn with whatever the current color is as set with SetColor, whether it's white (has no effect on the final color) or something else (to apply a tint). It is still combining the current color with the texture pixels in realtime. The only extra overhead is when you start adding extra calls to SetColor for each object part.

I would recommend it may be faster to let the hardware recolor your frames, ie draw your frame to the backbuffer as grayscale with a tint, and then grab it into a new image. That should be much faster than doing it with the pixmap.


Derron(Posted 2007) [#6]
In my opinion recoloring them before the start (so only once per match) should be faster than "setcolor drawimagepart setcolor drawnextimage"-methods...

The first method just uses CPU and RAM, the second may also depend on vram - which could slow down the fps-rate on grandpa-graphic cards.

In my game I just made some functions to colorize the grey parts in images/pixmaps/animimages. To combine different things like "base figure" + weapon or so, you can write a function "drawImageToPixmap" and then combine the basefigure and the weapon/extra to an individual player-sprite.
(you can also use this to place items on bigger backgroundsprites to minimize drawing-commands for small items no longer needed to be drawn).

This would not produce small lags and for only being done during the creation-period of a new match (and only if the colors changed) you would gain a hit in efficiency.

Using a combination of "precoloring" and "painting on pixmaps" gave me nearly a 10% improvement on fps.

You may also save memory if you free unneeded small sprites if you know that they won't be used again up to the next start of the application (I just separated small plants from the background to position them a bit randomly - and the plants have also random colors for the flowers or fruits and so on).



I know this may not be one of the answers you wanted to read, but it's a kind of opinion ;D.


bye
MB


tonyg(Posted 2007) [#7]
By using DrawImage/GrabImage without a flip, I guess there could be an initialisation phase for that. There's a potential problem though in that there could be up to 25 different combinations required. If the size of the AnimImage was 512x512, that'd make 25MB just for images, rather than the 2MB or so maximum by drawing each bit.


but wouldn't you scrap the images after each match and re-use/re-build them?
I might be missing something though.
Pastepixmap might be useful. Last time I looked it didn't respect the maskcolor but you might simple be able to maskpixmap again.
I wrote some code ages ago which did a memcopy and was pretty quick on small images.
Otherwise writepixel is not a slouch either any more.
Guess you'd really have to check them all out.


Fry Crayola(Posted 2007) [#8]
Last night I whipped up some code which acted on a single 32x32 image (obviously not representative given that my guys are actually going to be animated), and it produced more than pleasing results even on my integrated-graphics laptop. I went one step further and made it carry out the colour change on the fly, when the sprite needs drawn, and it wasn't the major drain I expected on that machine. Not that I'll be doing that - it's fine for one player but not for twenty two.

Given those results, I'll stick with pixmaps for now as they're easiest to get up and running, and then concern myself with tweaking further down the line.

TonyG, the images are indeed scrapped but I'm just very memory-sensitive, especially as I've already got a 50MB or thereabouts database in memory at all times. Not a problem on many machines but when you go as low as 256MB you might start to see problems. Maybe. I might get lucky.