?
Solved

Looking for fast "PutPixel" procedure

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

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

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 Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Monitoring a network: how to monitor network services and why? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the philosophy behind service monitoring and why a handshake validation is critical in network monitoring. Software utilized …
In this video, Percona Solution Engineer Rick Golba discuss how (and why) you implement high availability in a database environment. To discuss how Percona Consulting can help with your design and architecture needs for your database and infrastr…
Suggested Courses
Course of the Month15 days, 2 hours left to enroll

771 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