# Help need to optimize Cross fader

I am trying to re-create an old-demo routine I wrote AGES ago in pascal.
It’s basically a linear cross-fade between to images (both 800*600) using
the old formula C = A + (B-A) * k

where C is the final colour, A is the first image colour, B is the second
image and k is a number between 0 and 1. Now I have to do this for every
pixel on screen, What would be the fastest way to do this. Currently I am
getting about .5 frames a second. WAY to slow.

Piotr Dubla

use alpha blending…
have both surfaces for maximal performance in video memory and change
the final picture alpha from 0 - 100 and blit it to the screen. First of
course you should blit the initial picture to the screen.

``````KovacsOn Mon, 13 Nov 2000, Piotr Dubla wrote:
``````

I am trying to re-create an old-demo routine I wrote AGES ago in pascal.
It’s basically a linear cross-fade between to images (both 800*600) using
the old formula C = A + (B-A) * k

where C is the final colour, A is the first image colour, B is the second
image and k is a number between 0 and 1. Now I have to do this for every
pixel on screen, What would be the fastest way to do this. Currently I am
getting about .5 frames a second. WAY to slow.

Piotr Dubla

Mon, 13 Nov 2000 Piotr Dubla wrote:

I am trying to re-create an old-demo routine I wrote AGES ago in pascal.
It’s basically a linear cross-fade between to images (both 800*600) using
the old formula C = A + (B-A) * k

where C is the final colour, A is the first image colour, B is the second
image and k is a number between 0 and 1. Now I have to do this for every
pixel on screen, What would be the fastest way to do this. Currently I am
getting about .5 frames a second. WAY to slow.

Well, one real fast way is to hack up a few highly optimized alpha blending
routines of the kind 25/75, 50/50, 75/25 etc (just shifting, masking and adding

• works great with MMX), and then building dither patterns (4x4 pixels for
example) out of these.

If the fade is quick enough, the dithering will look more like analog noise
than dithering. You can see a similar effect on some 16 bit 3D accelerator
drivers on DirectX.

* Fast
* Doesn’t rely on 24 bit color for smooth fading

* Noisy

If you want full color resolution and no dithering tricks, you could try using
look-up tables, but do keep these small. If they’re too big for the L2 cache,
you’re usually better off doing the real math! Cache misses are quite expensive
these days, especially on the higher frequency CPUs…

As for 24 and 32 bit modes, MMX rules. There are perfect instructions for this
kind of stuff, although there are only 16x16 bit multiplications. Still, you
can do 4 of them at a time (theoretically in 3 cycles, fully piplined so that
you can start one every cycle), so that’s quite a few muls/s. (There are
saturating add and sub as well, but you shouldn’t need that in this particular
case, unless I’m missing something…)

//David

…- M u C o S -------------------------. .- David Olofson --------.
| A Free/Open Source | | Audio Hacker |
| Plugin and Integration Standard | | Linux Advocate |
| for | | Open Source Advocate |
| Professional and Consumer | | Singer |
| Multimedia | | Songwriter |
`-----> http://www.linuxdj.com/mucos -'`—> david at linuxdj.com -’

I am trying to re-create an old-demo routine I wrote AGES ago in pascal.
It’s basically a linear cross-fade between to images (both 800*600) using
the old formula C = A + (B-A) * k

This is what the alpha-blending blit function does in SDL. Either use it
directly, or look at the SDL sources to see how you can do it yourself.

Basically, you can try the following:

for k = 0…255:
copy image A opaquely to the screen (use SDL_BlitRect())
copy image B with per-surface alpha value k onto the screen
(SDL_SetAlpha() with flags=SDL_SRCALPHA, then SDL_BlitRect())
update the screen (SDL_UpdateRect())

Make sure you use a SWSURFACE for the screen, to avoid reading from video
memory for each pixel.

Currently I am
getting about .5 frames a second. WAY to slow.

How are you doing it, and on what? Note that this can take quite some
time even on a fast machine, and it may take a while to transport an
800x600 image from memory to the screen. If you can use 15/16bpp instead
of 32bpp it will probably be faster. 8bpp is likely to be faster still,
but SDL does not currently support alpha-blending in 8bpp; you have to
do it yourself

As for 24 and 32 bit modes, MMX rules.

He didn’t say he was using a PC. Besides, MMX is pathetic compared to
AltiVec or even VIS

Mon, 13 Nov 2000 kovacs at mt.lv wrote:

use alpha blending…
have both surfaces for maximal performance in video memory and change
the final picture alpha from 0 - 100 and blit it to the screen. First of
course you should blit the initial picture to the screen.

Well, that would be lightning fast - with a 3D accelerator, at least.

//David

…- M u C o S -------------------------. .- David Olofson --------.
| A Free/Open Source | | Audio Hacker |
| Plugin and Integration Standard | | Linux Advocate |
| for | | Open Source Advocate |
| Professional and Consumer | | Singer |
| Multimedia | | Songwriter |
`-----> http://www.linuxdj.com/mucos -'`—> david at linuxdj.com -’

Mon, 13 Nov 2000 Mattias Engdeg?rd wrote:

As for 24 and 32 bit modes, MMX rules.

He didn’t say he was using a PC. Besides, MMX is pathetic compared to
AltiVec or even VIS

Yep, but (unfortunately) the vast majority of users are (still) running these

My next machine will probably be PPC based, but that won’t change the world…

//David

…- M u C o S -------------------------. .- David Olofson --------.
| A Free/Open Source | | Audio Hacker |
| Plugin and Integration Standard | | Linux Advocate |
| for | | Open Source Advocate |
| Professional and Consumer | | Singer |
| Multimedia | | Songwriter |
`-----> http://www.linuxdj.com/mucos -'`—> david at linuxdj.com -’

Mon, 13 Nov 2000 Mattias Engdeg?rd wrote:

I am trying to re-create an old-demo routine I wrote AGES ago in pascal.
It’s basically a linear cross-fade between to images (both 800*600) using
the old formula C = A + (B-A) * k

This is what the alpha-blending blit function does in SDL. Either use it
directly, or look at the SDL sources to see how you can do it yourself.

Basically, you can try the following:

for k = 0…255:
copy image A opaquely to the screen (use SDL_BlitRect())
copy image B with per-surface alpha value k onto the screen
(SDL_SetAlpha() with flags=SDL_SRCALPHA, then SDL_BlitRect())
update the screen (SDL_UpdateRect())

Make sure you use a SWSURFACE for the screen, to avoid reading from video
memory for each pixel.

Currently I am
getting about .5 frames a second. WAY to slow.

How are you doing it, and on what? Note that this can take quite some
time even on a fast machine, and it may take a while to transport an
800x600 image from memory to the screen. If you can use 15/16bpp instead
of 32bpp it will probably be faster. 8bpp is likely to be faster still,
but SDL does not currently support alpha-blending in 8bpp; you have to
do it yourself

hehe Remembering the good ol’ Amiga days; here’s another really fast way to

Use to 16 color images (ie 4 bits per pixel), encoded into the low and high
nibbles of the 8 bit pixels. Display this in 256 color palletized mode.

Start out with a palett where only the 4 low bits are significant, and then
fade the palette, so that the higher 4 bits gradually become more dominant,
until finally, the lower 4 bits are insignificant.

That is, the first palette is actually 16 copies of the 16 color palette of the
first image, and the final palette is 16 entries of each of the 16 entries of
the palette of the second image. What you do is actually a simple cross fade
between these two palettes.

Well, 16 colors aren’t that hot these days, but you get what you pay for!

//David

…- M u C o S -------------------------. .- David Olofson --------.
| A Free/Open Source | | Audio Hacker |
| Plugin and Integration Standard | | Linux Advocate |
| for | | Open Source Advocate |
| Professional and Consumer | | Singer |
| Multimedia | | Songwriter |
`-----> http://www.linuxdj.com/mucos -'`—> david at linuxdj.com -’