Fast Blur using C++ and Allegro

Status
Not open for further replies.

Sik

Member
For all who uses C++ and Allegro, I created a fast blur algorithm, yeah, I mean the effect of the fast blur of the Gens:
Code:
unsigned short xl;
unsigned char yl;
unsigned long color1;
unsigned long color2;
unsigned long color3;

for (yl = 0; yl < 224; yl++)
	for (xl = 0; xl < 321; xl++) {
		color1 = _getpixel16(video_buffer, xl, yl);
		color2 = _getpixel16(video_buffer, xl + 1, yl);
		
		color1 =
			(color1 >> 11 << 19) + (((color1 >> 5) & 63) << 10) +
			((color1 & 31) << 3);
		
		color2 =
			(color2 >> 11 << 19) + (((color2 >> 5) & 63) << 10) +
			((color2 & 31) << 3);
		
		color3 =
			makecol16((color1 >> 16) + (color2 >> 16) >> 1,
					((color1 >> 8) & 255) + ((color2 >> 8) & 255) >> 1,
					(color1 & 255) + (color2 & 255) >> 1);
		
		_putpixel16(video_buffer, xl, yl, color3);
	}
Here the video buffer is named "video_buffer", and is 320×224, with a 16-bits depth. I don't suggest use it in high resolutions, but you can always stretch after do it ;) If you think that stretching is slow, then is because you tried to stretch directly to the video card :P Use a temporal buffer instead, and then blit normally.

If you want to use 15-bits of depth, change the 16 -> 24 bits conversion code (the one between the _getpixels() and color3 = makecol16(...)) for use the correct alignement. Under 24/32-bits mode, delete that code.

And change the 16 at the end of _getpixel, _putpixel and makecol to the correct one.

If you want to be able to use different depths, use ifs() and select the correct algorithm :P

What do you think? I tested it and yes, it's fast. Really. I used under a program which runs at 60FPS virtually (VIRTUALLY, another example of virtual frame-rate is Sonic Action, which runs virtually at 100FPS, yes, I mean machine-idependant (did I mispelled it?) speed).
 
Allegro 4.2.0rc2 is out right now.
Nice function, have you extracted it from Gens's sources? :)
Really, Gens is open source.
 
Nice routine, Sik. It runs a little slowly for me, though: it takes about a third of a second to complete using system bitmaps. Using VRAM bitmaps, it takes about three seconds, but I imagine it wasn't intended for that.

You can achieve the same effect using the translucency functions (and it runs a lot more quickly, too... :-P):

Code:
set_trans_blender(0, 0, 0, 127);

/* Our original bitmap is bm and we have another bitmap,
   bm2, of the same dimensions, as a buffer: */
blit(bm, bm2, 0, 0, 0, 0, bm->w, bm->h);
draw_trans_sprite(bm2, bm, 1, 0);
The blurred image is in bm2. For some reason, I can't get it working directly into bm by reversing the params to draw_trans_sprite; could be a bug in the previous blit call, since I'm using the beta. I can work around it by copying from bm2 back to bm, but... nah.

It works with VRAM bitmaps, too, but more slowly: maybe about a two tenths of a second on my machine. It only takes about 10 ms for system bitmaps, though.
 
System and VRAM bitmaps are slow when you use a function which is not hardware accelerated (except basic functions). The same thing happens when you do stretching. Suggestion: use memory bitmaps always. Oh, and there is a theory that draw_sprite() is faster than blit() (I don't know how, but this is true, check the allegro.cc forum). Your transparency idea is good, I've used it in the past, but isn't this slow too?

And Tails92, no, I didn't check the Gens source code (and I haven't it :P). I just tried to do the same effect. If the algorithm is the same, then it's pure coincidence.
 
Sik said:
System and VRAM bitmaps are slow when you use a function which is not hardware accelerated (except basic functions). The same thing happens when you do stretching. Suggestion: use memory bitmaps always.
My first mistake was to forget that system and memory bitmaps are different things (/me slaps himself). I switched from create_bitmap to create_system_bitmap when I found that it was crashing when I tried to destroy bitmaps created with the former, but that's beside the point: it's either a bug in the beta or I'm doing something silly. I'll upgrade to RC2 when I can bothered. But yes, your routine ran much faster with memory bitmaps.

As for using memory bitmaps all the time: fine if you're content with double-buffering, but I prefer page-flipping. Blitting from sprites in VRAM to a VRAM video buffer is exceedingly fast (usually; there are some excpetions that I forget), which is why I'm a page-flipper. But, each to his own.

Returning to your routine, in a moment of idleness (well, several moments), I rejigged it a bit. It produces exactly the same result, using the same general method (averaging the R, G and B of the 16-bit colour value), but follows a different algorithm. Here 'tis:

Code:
/* Originally by Sik; adapted by Oog. */
void fast_blur_2(BITMAP *bm)
{
	unsigned short xl;
	unsigned char yl;
	unsigned long colour1;
	unsigned long colour2;
	unsigned short colour3;

	for (yl = 0; yl < 224; yl++)
	   for (xl = 0; xl < 321; xl++)
	   {
		  colour1 = _getpixel16(bm, xl, yl);
		  colour2 = _getpixel16(bm, xl + 1, yl);
      
		  colour3 =
			 makecol16(((colour1 & 0xF800) + (colour2 & 0xF800)) >> 9,
				       ((colour1 & 0x07E0) + (colour2 & 0x07E0)) >> 4,
				       ((colour1 & 0x001F) + (colour2 & 0x001F)) << 2);
      
		  _putpixel16(bm, xl, yl, colour3);
	   }
}
 
Didn't I think about use "&"??? (Takes the idea)

Oh, for draw on system and VRam bitmaps, adquire them first, so you can edit them faster. It's a bug of DirectX (Allegro uses DirectDraw in the Windows port), not from Allegro. Yeah, other stupid error. Like that video card memory is lost when switching.

Note that use VRam is fast ONLY if the video card supports it accelerated. Check CPU_CAPABILITIES first. If you don't, a better way is the doble buffering then, which is more sure, and memory access sometimes has the same speed that the video card acceleration, so you don't lose anything in that case.

However, in my method I have the advantage that I uses the Genesis colors (3-3-3). No, it's not an emulator, just a game which is completely based on the Sega Genesis hardware.

EDIT: Hey, Oggaland! Your modification works faster! Thanks! [joke]Now the only thing that I can do is convert this to ASM[/joke] :P Well, now, seriously, it works faster now ;)
 
Status
Not open for further replies.

Who is viewing this thread (Total: 1, Members: 0, Guests: 1)

Back
Top