PDA

View Full Version : Bitmap.monochrome



Sander
28-05-2003, 06:22 PM
Right, I didn't know where else to put this, so I thought I'd put it here.

I just got some time together and created a small test project to check some times on Windows API methods, and transparent drawing with it. Actually, I only checked BitBlt vs. Canvas.Draw(which is actually VCL), and bitblt won easily.

So, I went on with it(trying to draw transparent by creating a mask on the fly), and when I was done, I ran it, and it seemed a bit slow(FYI, it was 28-30 FPS, on a 1024*800 window(no fullscreen)......). After doing some speed tests, I noticed that the blitting itself took 1 milliseconds(rounded down) in total, BUT making the mask image took a whopping 30-35 milliseconds(!). It seems that making a TBitmap monochrome takes almost all of that time(approx. 29-34 milliseconds). SO, I'd like to know if there is any way of making a bitmap monochrome faster, or if there is any way to bypass the monochromization(is that a word???) altogether without having to manually create and load masks.

Ultra
28-05-2003, 11:42 PM
Hi!

Are you making a new mask image every frame? (If your not you can probably ignore this.) If so you should try to only create it at the begining of the program. In half pseudo code, half VCL (so if you don't use it consider it more psuedo code), half something else it would look like this:


var
MyBitmap, MyMask: TBitmap;

procedure StartUp;
var
x,y: Integer;
begin
MyBitmap.LoadFromFile('Picture.bmp');
MyMask.Canvas.Draw(0,0,MyBitmap);
MyMask.Mask(clFuchsia);
{this could be improved using scanlines}
for y := 0 to MyBitmap.Height - 1 do
for x := 0 to MyBitmap.Width - 1 do
begin
if MyBitmap.Canvas.Pixels[x,y] = clFuchsia then
MyBitmap.Canvas.Pixels[x,y] := clBlack;
end;
end;

procedure Draw(Canv: TCanvas);
begin
Canv.Copymode := cmSrcAnd;
Canv.CopyRect(DestRect, MyMask.Canvas, SourceRect);
Canv.Copymode := cmSrcPaint;
Canv.CopyRect(DestRect, MyBitmap.Canvas, SourceRect);
end;

{hmm... maybe not so much pseudo code... ;)}


Notice that I haven't check how much time, memory or anything else this code takes and there are probably many other, better, ways of doing it.

By the way, how much faster was BitBlt vs. Canvas.Draw?

Sander
29-05-2003, 11:29 AM
Well, I went for it in a relatively different way. I created the mask every frame again, since I wanted to test how fast it would be if there were continuous changes to the map. Ofcourse, I think I have a way past that, because I will only need to make a new mask every time something in the map itself changes, and if I didvide the map in parts(say....4*4 tiles or so), it'd save a lot of time and such. So I think that that is out of the way.

Hmm, your code looks interesting, I'll go see in a minute which one is actually faster, since I was trying to do it by copying the inverted image to a mask image(Because the base image had black instead of fuchsia as backcolor), and then blitting it with AND and OR arguments.

And ehmm, bitblt was 2 to 3 three times as fast as canvas.draw(after a lot of tests), so I think you can safely say it's better to use bitblt.

Sander
29-05-2003, 12:48 PM
Alright, I tried it and speed tested it(didn't count making the mask), and your draw and rect method averaged a nice 1.2 milliseconds, while my bitblt method averaged a nice 1.2 milliseconds as well. Interesting, no difference here, while I had noticed a relatively large difference whenusing normal drawing. Apparently, copyrect is just a front for Bitblt(I think), and draw is something else(since that is about twice as slow);

BUT, if I take into account the time it takes to create the rects for copyrect, copyrect takes a whole .1 millisecond longer.

Heh, so no difference there.

In any case, I'll just keep at it with my monochrome thingie, and not redraw every frame :oops:

Harry Hunt
29-05-2003, 03:23 PM
How about if you draw you image onto another TBitmap and then BitBlt the TBitmap onto the screen...
that way you could see how fast TBitmap.ScanLine is.

Here's some pseudo-code:

if (SrcScanline.Red <> MyTransparentColor.Red) or (SrcScanline.Green<> MyTransparentColor.Green) or (SrcScanline.Blue<> MyTransparentColor.Blue) then
begin
DestScanline.Red := SrcScanline.Red;
DestScanline.Green := SrcScanline.Green;
DestScanline.Blue := SrcScanline.Blue;
end;

I dunno if scanline is faster than on-the-fly mask creation, but you might want to check that out, too.

Sander
29-05-2003, 05:02 PM
Alright, I haven't tried it yet, but I will as soon as I know why monochrome is NOT monochrome. It's grey and black, not white and black. Could somebody explain to me why making a bitmap monochrome doesn't make it white and black, but instead makes it grey and black(which is why it seemed to me as if it WAS drawing transparent, since the grey is the same thing as the grey used for the forms).

Oh, and Harry, when I did a speed check, it turns out that(when counting the monochrome thing as well), your XCESS method was 3 times as slow.

Harry Hunt
29-05-2003, 05:08 PM
Hey, I also made a test program and at least on my comp, plain Scanline is faster than anything else...

Download it at http://jaeger.xenoware.de/blttest.zip

And yes, XCESS' transparent blit routine is super-slow. It's actually a translation of a code snippet I found @ MSDN a long time ago.
The transparent-blt routine used in my blt-test program is the same that is used in XCESS.

Ultra
29-05-2003, 11:34 PM
I've also had the problem of not getting the right colour of the monochrome bitmap (but in my case it was blue and black :wink: ). A guess is that you must write Canvas.Brush.Color := clWhite (don't ask me which Canvas, you'll have to try everyone :wink: ) before making the mask. However, I have not had the time to try if this work.

Sander
30-05-2003, 10:12 PM
Yep, you're right. Scanline is fastest transparent draw, and Bitblt(the way I did it) was twice as slow, but still way before canvas.draw.

So, scanline is the fastest and best way to go, hmm, may want to change your XCess SDK accordingly, Harry.

And to make the blitting work properly, you'll need to set the brush color of the canvas on which you are drawing the mask to clWhite.