Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

Looking for fast "PutPixel" procedure

Posted on 1997-08-18
4
Medium Priority
?
1,177 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 400 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

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
This is an update to some code that someone else posted on Experts Exchange. It is an alternate approach, I think a little easier to use, & makes sure that things like the Task Bar will update.
This lesson discusses how to use a Mainform + Subforms in Microsoft Access to find and enter data for payments on orders. The sample data comes from a custom shop that builds and sells movable storage structures that are delivered to your property. …
Is your OST file inaccessible, Need to transfer OST file from one computer to another? Want to convert OST file to PST? If the answer to any of the above question is yes, then look no further. With the help of Stellar OST to PST Converter, you can e…

580 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