Speedier sprites (effective png)

Hello dear people,

I’m totally new to this mailing list, but not so “new” to programming. I
haven’t watched this topic from its’ begining, so I’m not totally sure if
I’m off-topic or not… in any case, I suppose a lot were said about whether
or not PNG blitting is fast or not.

I’m developing a Worms-clone under linux, and my friend that deals with the
graphics insisted that the worms use PNG surfaces. I developed the engine
using BMPs, and was ultra-fast. When I switched to PNG, using SDL_Image, I
was so disappointed. Even under windows, with hardware accelaration, the
engine struggled to get over 30fps, which was unacceptable (linux struggled
for 5fps…)

After some thinking, I found out the following::

SDL_Image & SDL_BlitSurface is a not so “smart” combination. If you have a
surface with, say, 1,000,000 totally transparent pixels (empty, if you
prefer, or alpha=0), the library will try to render them as If they are
normal, semi-transparent pixels. To see that, create a small PNG, with a
sprite in it’s center and empty pixels around it, say 60x60 total. Blit it
and benchmark. Now, expand the sprite to 160x160 pixels, all the new pixels
being empty. Blit and benchmark again. Result = disappointment.

What I came up with::

If you have a PNG surface, hardly all the pixels are semi-transparent. If
they are, use SDL_BlitSurface. If some pixels are semi-transparent, but most
of them are full-transparent (empty) or full-opaque (alpha=255), then you
may want to forget about SDL_Surface.

struct WM_RGBA_Pixel
{
Uint8 r,g,b; //reg-green-blue values
Uint16 x,y;
float a, al; //alpha value (alpha/255) E [0,1], al = 1-a
};

class WM_Surface
{
private:
SDL_Surface * srf; //typical SDL_Surface

 WM_RGBA_Pixel *pix;   //pointer to an array of RGBA pixels
 Uint16   rgbaPix;  //count of rgba Pixels

};

Here is the idea::
1)LOAD the PNG surface using IMG_Load
2)CREATE a BMP surface with color key for transparency. Name it ,
SDL_BlitRect it with color key. srf is now transparent.
3)SCAN the PNG surface:
> if a pixel is FULL OPAQUE (alpha=255), BLIT it to srf.
> if a pixel is EMPTY (alpha=0), ignore it.
> else, rgbaPix += 1
4)REPEAT for all pixels

5)CREATE pix = new WM_RGBA_Pixel[rgbaPix]
6)SCAN the PNG surface again (OK, this could be optimized… lol :wink:
> if a pixel is NOT OPAQUE, NOR EMPTY, put it in pix
7)REPEAT for all pixels
8)FREE the PNG surface

LOADING Done! Now you have a that contains all the opaque pixels of
your PNG. All the semi-tranparent pixels are held in the pointer. If
you want to blit this kind of surface (WM_Surface), you should write your
own code. First, you blit the using default SDL_BlitSurface. This is
ultra fast. Then, for every pixel in the pointer, blit using software
alpha blending.

My results showed an increase in speed of about 10-600 times… no kidding
:slight_smile: (the more the PNGs loaded, the greater the effectiveness of the
algorithm)

Many of you may complain about not giving the code for bliting
WM_Surface(s)… the reason is that I have to go offline now, and the code is
not 100% final yet. Just in case you wonder, the whole game will be free and
open-source, so don’t blame me for anything I haven’t done :wink:

If you want to, I’ll post the code to this mailing list soon… I’m just a
bit afraid about getting feedback like “this code sucks…” etc etc… I’m new
to open-source, so be gentle :wink:

in any case, if you can’t wait to try it, mail me at clairvoant at freemail.gr
and I’ll send it to you…

cheers!–
http://www.freemail.gr - ??? ??? ??? ???.

Please don’t respond to existing threads to start new ones. They get
threaded together. Many people won’t even notice your post if they’re
not paying attention to the thread you got threaded with. Send a new
mail to the list address.On Thu, Mar 13, 2003 at 06:42:45PM +0200, George wrote:

SDL_Image & SDL_BlitSurface is a not so “smart” combination. If you have a
surface with, say, 1,000,000 totally transparent pixels (empty, if you
prefer, or alpha=0), the library will try to render them as If they are
normal, semi-transparent pixels. To see that, create a small PNG, with a
sprite in it’s center and empty pixels around it, say 60x60 total. Blit it
and benchmark. Now, expand the sprite to 160x160 pixels, all the new pixels
being empty. Blit and benchmark again. Result = disappointment.

Enable RLE.


Glenn Maynard