Solved

Looking for fast "PutPixel" procedure

Posted on 1997-08-18
4
1,105 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
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

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

708 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

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now