Need Help on Imaging Problem...

I have a CCD camera sending data to my PC. I managed to aquire the data and put it into an array. The image is grayscale, thus the array is of type byte.

I need to display the image on the screen close to real time. This is my source code:

var imageBuffer: array[0..249,0..249] of byte;
    arrayPtr: Pointer;
begin
     arrayPtr:= addr(imageBuffer);
     Image.Picture.Bitmap.Width := 250;
     Image.Picture.Bitmap.Height := 250;
     MakePalette; // My grayscale palette

     { Fill up imageBuffer }
     SetBitmapBits(Image.Picture.Bitmap.Handle, sizeof(imageBuffer),ArrayPtr);
     Image.Refresh;

My problem is that the image is only half filled!! I read the help files and found that the SetBitmapBits takes in an array of words, not bytes. how do i solve this problem?

I have gone through all the previously asked questions and I have found 2 answers which partially help my problem.

This first one is entitled "Bitmap Palette" asked by tier and answered by javiertb (Question #294 date: 05/08). I have a very similar code to tier. How did tier manage to use the arary of bytes?

The second mail is entitled "Displaying bitmaps from memory" asked by Thales and answered by Sperling (Question #387 Date: 04/23). Should I incorporate this method to my solution?

I need some guidance. I am not sure how much this question is worth, but if you feel that it is too low, i'll be happy to increase it. :)

Kind regards
keith
LVL 1
keithcslAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

keithcslAuthor Commented:
Edited text of question
magic_wizardCommented:
This may be a stupid answer, so I let it go only as a comment.
Isn't it possible to actually convert those bytes to word's on
the fly?
If that works, well...
Good luck anyway.
(Maybe I just didn't understand your problem fully)

Morten Brendefur.
brendefu@online.no
mirek071497Commented:
Image can contain planes.
Why Diversity in Tech Matters

Kesha Williams, certified professional and software developer, explores the imbalance of diversity in the world of technology -- especially when it comes to hiring women. She showcases ways she's making a difference through the Colors of STEM program.

keithcslAuthor Commented:
i have tried using an array of type word. first of all, this change managed to fill the image. but when i tried filling the buffer with values 0 to 255, i did not get the gradient fill i expected. i got 8 strips of gradient fill instead of 1 single strip (top to bottom). i would expect this because 0 - 255 is $0000 - $00FF. i don't know how to map the byte to a word.

the second problem is my palette. i still cannot produce a grayscale image.

i would be most grateful if magic_wizard or mirek or anyone would like to see my source code.
keithcslAuthor Commented:
This is my source code (i managed to reach this far with the help of my russian friend, anatoly):

var
  Form1: TForm1;
   hPal: HPalette;
implementation

{$R *.DFM}

procedure TForm1.MakePalette;
var
  LogicalPalette: PLogPalette;
  ColorIndex : LongInt;
begin
GetMem(LogicalPalette, (SizeOf(TLogPalette) + SizeOf(TPaletteEntry)*256));
GetSystemPaletteEntries(Canvas.Handle, 0, 256, LogicalPalette^.palPalEntry[0]);
with LogicalPalette^ do
  begin
  palVersion := $300;
  palNumEntries := 256;
  {$R-}
  for ColorIndex := 10 to 245 do
    with palPalEntry[ColorIndex] do
      begin
      peRed := 255 - (ColorIndex-10);
      peGreen := 255 - (ColorIndex-10);
      peBlue := 255 - (ColorIndex-10);
      peFlags := PC_NOCOLLAPSE;
      end;
  end;
  {$R+}
DeleteObject(hPal); // Prevent Memory leakage by deleting old palette
hPal := CreatePalette(LogicalPalette^);
FreeMem(LogicalPalette, (SizeOf(TLogPalette) + SizeOf(TPaletteEntry)*256));
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  ImageBuffer : array[0..254,0..254] of word;
  I,J,N : Integer;
  ArrayPtr : Pointer;
begin
  Image.Picture.Bitmap.Width := High(ImageBuffer)-1;
  Image.Picture.Bitmap.Height := High(ImageBuffer[1])-1;
  ArrayPtr := @imageBuffer;
  MakePalette;
  SelectPalette(Image.Canvas.Handle,hPal,FALSE);
  RealizePalette(Image.Canvas.Handle);
  Image.Picture.Bitmap.Palette := hPal;

  for n:= 1 to 25 do begin
            for i:= Low(ImageBuffer) to High(ImageBuffer) do begin
                  for j:= Low(ImageBuffer[1]) to High(ImageBuffer[1]) do begin
                        ImageBuffer[i,j]:= j;
                  end;
        end;

  SetBitmapBits(Image.Picture.Bitmap.Handle,SizeOf(imageBuffer),ArrayPtr);
  Image.Refresh;
  end;
end;

mirek071497Commented:
Sorry.  You cant do this in this way.
Tell me what you'r program need show and i write code for you.
keithcslAuthor Commented:
This is the specifications of my program:

poll the printer port for video data. i get the video 1 frame at a time and display the image on the screen. 1 frame is 250x250.  this means my array is 62500 bytes long. the code is like this:

  for i := 0 to rowSize do
    for j := 0 to colSize do
      imageBuffer[i,j] := GetDataFromPort(PortAddress); // puts a byte into the array

then, all i need to do is to display this grayscale image on the screen.

if you need more information, please ask. lastly, i would like to thank you, mirek, in advance for helping me out.
keithcslAuthor Commented:
This is the specifications of my program:

poll the printer port for video data. i get the video 1 frame at a time and display the image on the screen. 1 frame is 250x250.  this means my array is 62500 bytes long. the code is like this:

  for i := 0 to rowSize do
    for j := 0 to colSize do
      imageBuffer[i,j] := GetDataFromPort(PortAddress); // puts a byte into the array

then, all i need to do is to display this grayscale image on the screen.

if you need more information, please ask. lastly, i would like to thank you, mirek, in advance for helping me out.
mirek071497Commented:
Her is example of this problem.

unit1;

interface

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

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

type
  TForm2 = class(TForm)
    Button2: TButton;
    PaintBox2: TPaintBox;
    Label2: TLabel;
    procedure Button2Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    ByteBits : array[0..YSize-1,0..XSize-1] of byte;
    ByteInfo : PBitmapInfo;
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.DFM}

var
  MyPal       : HPalette;
  MyLPal      : PLogPalette;

procedure TForm2.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]:=i;   { here is filling byte array }

  GetMem(MyLPal, (SizeOf(TLogPalette) + SizeOf(TPaletteEntry)*256));
  MyLPal^.PalVersion := $0300;
  MyLPal^.palNumEntries:=256;
  for i:=0 to 255 do
  begin
    MyLPal^.palPalEntry[i].peRed   := i;
    MyLPal^.palPalEntry[i].peGreen := i;
    MyLPal^.palPalEntry[i].peBlue  := i;
    MyLPal^.palPalEntry[i].peFlags := 0;
  end;
  MyPal := CreatePalette(MyLPal^);
  FreeMem(MyLPal, (SizeOf(TLogPalette) + SizeOf(TPaletteEntry)*256));

  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 := i;
    ByteInfo^.BmiColors[i].rgbGreen := i;
    ByteInfo^.BmiColors[i].rgbBlue := i;
    ByteInfo^.BmiColors[i].rgbReserved := 0;
  end;
end;

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

procedure TForm2.Button2Click(Sender: TObject);
var
  Bmp     : HBitmap;
  NewDC   : HDC;
  T1      : TDateTime;
begin
  T1:=Now;
  PaintBox2.Repaint;
  NewDC := CreateCompatibleDC( PaintBox2.Canvas.Handle );
  DeleteObject(SelectPalette( NewDC,MyPal,false));
  RealizePalette( NewDC );
  Bmp := CreateCompatibleBitmap( PaintBox2.Canvas.Handle, XSize, YSize );
  SetDIBits( NewDC, Bmp, 0, YSize, @ByteBits, ByteInfo^, DIB_RGB_Colors );
  SelectObject( NewDC, Bmp );
  BitBlt( PaintBox2.Canvas.Handle, 0, 0, XSize, YSize, NewDC, 0, 0, SrcCopy );
  DeleteObject( Bmp );
  DeleteDC( NewDC );
  Label2.Caption := 'Time=' + FormatFloat('#.000',(Now-t1)*100000);   { time is 0 add loop for testing }
end;

end.


You don't need use Palette if You work on display than have more then 256 colors (for example HighColor)

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
keithcslAuthor Commented:
Fantastic Results!!!

Thank you so much for your help, mirek. The code is excellent! I think this question is worth more than 100 points. Well, I have only 82 points left on me and I think you deserve it all.

Very Statisfied,
keith
keithcslAuthor Commented:
Hei, how come the points did not get through to you? I will enquire on this...
mirek071497Commented:
I don't need more point's
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.