views:

285

answers:

2

When using the TBitmap wrapper for a GDI bitmap from the unit Graphics I noticed it will always clear out the bitmap (using a PatBlt call) when setting up a bitmap with SetSize( w, h ). When I copy in the bits later on (see routine below) it seems ScanLine is the fastest possibility and not SetDIBits.

function ToBitmap: TBitmap;
var
    i, N, x: Integer;
    S, D:    PAnsiChar;
begin
  Result := TBitmap.Create();
  Result.PixelFormat := pf32bit;
  Result.SetSize( width, height );
  S := Src;
  D := Result.ScanLine[ 0 ];
  x := Integer( Result.ScanLine[ 1 ] ) - Integer( D );
  N := width * sizeof( longword );
  for i := 0 to height - 1 do begin
    Move( S^, D^, N );
    Inc( S, N );
    Inc( D, x );
  end;
end;

The bitmaps I need to work with are quite large (150MB of RGB memory). With these iomages it takes 150ms to simply create an empty bitmap and a further 140ms to overwrite it's contents.

Is there a way of initializing a TBitmap with the correct size WITHOUT initializing the pixels itself and leaving the memory of the pixels uninitialized (eg dirty)? Or is there another way to do such a thing. I know we could work on the pixels in place but this still leaves the 150ms of unnessesary initializtion of the pixels.

+2  A: 

There's not many things you can do here - working with huge bitmaps is slow... but you can try following:

  1. Set PixelFormat after calling SetSize() - this won't avoid initialization of pixels but might make it faster.

  2. The fastest way I can think of is to use Win32 API functions (this or this) to create a DIB, and the assign HBITMAP handle of that DIB to a Handle of your TBitmap object.

  3. Use memory-mapped files (once again requires calling API or alternatively there are some third-party libraries that can do that for you).

Alex T.
Thank you Alex, at the moment I try to use the memory blob and not a real bitmap at all. The moment however that I need to display the bitmap on screen, I need a bitmap (and incur the time penalty). 1 is substantially slower. 2 takes some time tweaking but until now does not give me the correct results. 3. is impossible because the images are not from file but solely in memory.
Ritsaert Hornstra
In this case you can try creating new bitmap using CreateBitmapIndirect API function ( http://msdn.microsoft.com/en-us/library/dd183486%28VS.85%29.aspx ). I think it will use your existing data in memory and won't reallocate them.
Alex T.
When using CreateBitmap or CreateBitmapIndirect I shave off some 40ms (from 150+140 to 250ms)!
Ritsaert Hornstra
40ms is probably what the call to PatBlt() took.
Alex T.
@Alex: noppes; patblt took 150ms, copying data took 140ms, calling createbitmap took 250ms (it copies the data on the background because it keeps working when you free the working memory). So it is slower but because you avoid one inefficiency it is faster and the best option so far.
Ritsaert Hornstra
Accepted: cannot find anything that is a faster way of doing this.
Ritsaert Hornstra
A: 

This link has some benchmarks that may interest you:

http://ksymeon.blogspot.com/2010/02/getdibits-vs-scanline-vs-pixels-in.html

Tom1952
Thank you for the answer. I saw this information when searching for an answer on Google. It only deals with accessing the bits and not creation of the (hopefully uninitialized) bitmap itself.
Ritsaert Hornstra