Solved

Looking for fast "PutPixel" procedure

Posted on 1997-08-18
4
1,151 Views
Last Modified: 2012-06-27
I am looking for an efficient way to set pixels in a bitmap or on a canvas (Delphi 2.) Executing Bitmap.Canvas.Pixels[x,y]:=clBlack" is very slow - it does about 60,000 pixels/second on my 166Mhz Pentium. In my application, I do about 22 extended arithmetic operations per pixel (including sqrt/sin/cos), and even then the Pixels property takes 8 times longer to execute than my code. In the past under DOS, the time to "PutPixel" was a tiny fraction of the calculation time. I cannot construct the image I am building using any other method such as lines, etc.

I thought that creating a bitmap in memory would be faster than plotting directly to the canvas, but it isn't. An outline of my code is:

    Bitmap := TBitMap.Create;
    Bitmap.Height := Image1.Height;
    Bitmap.Width := Image1.Width;
    { Do calculations and call this approx 40,000 times: }
        Bitmap.Canvas.Pixels[x,y] := clBlack;
    Image1.Picture.Graphic := Bitmap;

I have tried various options such as "IgnorePalette := True", but it makes no difference.

Does anybody know of a way of getting to the bitmap in memory? I am sure I could write code to "twiddle bits" there much faster than the Pixels property. Or is there any other way?
0
Comment
Question by:numbercrunch
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
4 Comments
 
LVL 1

Expert Comment

by:millerw
ID: 1341698
Most of the newsgroups say that on screen images are the fastest and that by doing it off screen, your procedures will be about 3 times slower than an onscreen edit.  They also recommend using a function called CreateDIBSection to create your bitmap and to edit it by pointer to each bit.  I've never done it, but that is what they recommend.  If you want to see the discussion, goto Alta Vista and search the UseNet for: fast delphi bitmap

Good Luck,
Scott
0
 

Expert Comment

by:DaveJ080797
ID: 1341699
I reckon you've got no chance. I've done a lot of personal
research into this - I tried all dos ways of putting pixels
(Int 10h, Mem) Etc, and using the ASM command,
eving setting up an array directly in segA000. Your only hope
is with a bitmap of some description.

0
 
LVL 3

Accepted Solution

by:
mirek071497 earned 100 total points
ID: 1341700
You can use Memory Image of Bitmap and then use SetDIBits function to apply changes.
This is example of this.

unit Unit1;
{$R-}

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, StdCtrls, Buttons, ExtCtrls;

const
 XSize = 4*63; { must be devided by 4 !!!}
 YSize = 250;

type
  TForm1 = class(TForm)
    BitBtn1: TBitBtn;
    PaintBox1: TPaintBox;
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
  private
    ByteInfo : PBitmapInfo;
    ByteBits : array[0..YSize-1,0..XSize-1] of byte;
  public {}
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var
 i,j : longint;
begin
 for j:=0 to YSize-1 do
   for i:=0 to XSize-1 do
     ByteBits[j,i]:=Random(255); { here is filling byte array }

 { Create BitmapInfoHeader for 256 color bitmap }
 GetMem( ByteInfo, SizeOf(TBitmapInfoHeader) + 256*SizeOf(TRGBQuad) );
 ByteInfo^.BmiHeader.biSize := SizeOf(TBitmapInfoHeader);
 ByteInfo^.BmiHeader.biWidth := XSize;
 ByteInfo^.BmiHeader.biHeight := YSize;
 ByteInfo^.BmiHeader.biPlanes := 1;
 ByteInfo^.BmiHeader.biBitCount := 8; { 256 color }
 ByteInfo^.BmiHeader.biCompression := BI_RGB;
 ByteInfo^.BmiHeader.biSizeImage := 0;
 ByteInfo^.BmiHeader.biXPelsPerMeter:= 1000;
 ByteInfo^.BmiHeader.biYPelsPerMeter:= 1000;
 ByteInfo^.BmiHeader.biClrUsed:= 0;
 ByteInfo^.BmiHeader.biClrImportant:= 0;
 for i:=0   to 255 do
 begin
   ByteInfo^.BmiColors[i].rgbRed := Random(255);
   ByteInfo^.BmiColors[i].rgbGreen := Random(255);
   ByteInfo^.BmiColors[i].rgbBlue := Random(255);
   ByteInfo^.BmiColors[i].rgbReserved := 0;
 end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FreeMem( ByteInfo, SizeOf(TBitmapInfoHeader) + 256*SizeOf(TRGBQuad) );
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
var
 Bmp : HBitmap;
 NewDC : HDC;
 T1 : TDateTime;
 i,j,k : integer;
 Count : integer;
begin
 T1:=Now;
 NewDC := CreateCompatibleDC( PaintBox1.Canvas.Handle );
 Bmp := CreateCompatibleBitmap( PaintBox1.Canvas.Handle, XSize, YSize );
 SelectObject( NewDC, Bmp );
 Count := 50;
 for i:=1 to Count do
 begin
   SetDIBits( NewDC, Bmp, 0, YSize, @ByteBits, ByteInfo^, DIB_RGB_Colors );
   BitBlt( PaintBox1.Canvas.Handle, 0, 0, XSize, YSize, NewDC, 0, 0, SrcCopy );
   for j:=0 to YSize-1 do
   for k:=0 to XSize-1 do
   begin
     ByteBits[j,k] := ByteBits[j,k+1];
   end;
 end;
 DeleteObject( Bmp );
 DeleteDC( NewDC );
 Label1.Caption := 'Time=' + FormatFloat('#.000',(Now-t1)*100000*1000/(Count*YSize*XSize))+
                   'ms for one pixel''s read+write';
end;

end.


If You need modify existing  bitmap then of course you can use GetDIBits and then this example.

Mirek.
0
 

Author Comment

by:numbercrunch
ID: 1341701
Thank you Mirek!! I have not yet tried this code, but at last I
have a working example to build from! I will let you know what
success I have.
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
In this video we outline the Physical Segments view of NetCrunch network monitor. By following this brief how-to video, you will be able to learn how NetCrunch visualizes your network, how granular is the information collected, as well as where to f…
NetCrunch network monitor is a highly extensive platform for network monitoring and alert generation. In this video you'll see a live demo of NetCrunch with most notable features explained in a walk-through manner. You'll also get to know the philos…

717 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question