Reading values from file on disc into array

I have a binary file with a header block followed by a stream of 2-byte values. These need to be read into a two dimensional array of x and y values which are to be converted into a grey scale bitmap.  Currently I am using the  BlockRead procedure but this is very slow.  Can somebody point me to a better method. Please note that I am only a novice at delphi programming - but learning fast.  
barfbaggerAsked:
Who is Participating?
 
Bart_ThomasConnect With a Mentor Commented:
Normally speaking, you read imagedata into a 1 dimensional array.
Since the width and height are stored in the header, converting
into 2 dimensions isn't that difficult.

type
  TImageHeader = record
                   Width,Height: Cardinal;
                 end;

var
  F: TFileStream;
  ImageHeader: TImageHeader;
  ImageData: array of word;
  i,x,y,DataLength: Cardinal;
begin
  F := TFileStream.Create ('FileName.Ext', fmOpenRead);
  try
    F.Position := 0;
    F.Read(ImageHeader, SizeOf (TImageHeader));
    DataLength := (F.Size - F.Position) div SizeOf (WORD);
    SetLength (ImageData, DataLength);
    try
      F.Read (ImageData[0], DataLength);

      i := 0;
      y := 0;
      while y < ImageHeader.Height do
      begin
        x := 0;
        while x < ImageHeader.Width do
        begin
          // ImageData[i] is greyvalue at x,y

          inc (i);
          inc (x);
        end;
        inc (y);
      end;
    finally
      SetLength (ImageData, 0);
    end;
  finally
    F.Free;
  end;
end;
0
 
vadim_tiCommented:
there is no reason for blockread to be slow.

type
header = record
....
end;

arrayItem = record
....
end;

myArray = array [0..1] of arrayItem;

var
  f:file; h:header;
  p: ^myArray;
 

assignfile(f, filename);
reset(f, 1);
blockread(f, h, sizeof(header));

// now you know size of your array , lets say is arrSize
GetMem(p, arrSize * sizeof(arrayItem));
blockread(f, p^, arrSize * sizeof(arrayItem));
CloseFile(f);
// now you have in p reference to your array for processing
0
 
barfbaggerAuthor Commented:
Thanks,  I'll try this.
0
 
joncmoraConnect With a Mentor Commented:
I think the reason for BlockRead being slow is that you're using a very small buffer. Instead of reading 2 bytes at a time after reading the header, why not get 4KB or 8KB or higher for each BlockRead. Then loop through the buffer for your X,Y pair.

const
  HeaderSize = 512; {your header size here}

type
  TBuffer = array[1..8192] of Byte; {buffer size, experiment other sizes to get the fastest BlockRead performance}

procedure ReadMyImage;
var
  MyBufer: TBuffer;
  BytesRead: Integer;
  I: Integer;
  X, Y: Byte;
begin
  ...
  BlockRead(F, MyBuffer, SizeOf(MyBuffer), BytesRead);
  for I := 1 to (BytesRead div 2) do
  begin
    X := Buffer[(I*2) - 1];
    Y := Buffer[(I*2)];
    DoSomethingWithyourXY(X, Y);
  end;
  ...
end;



Or you can use TFileStream instead...
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.