Home How to use TStream to fill a matrix of integers
Reply: 1

How to use TStream to fill a matrix of integers

RobertFrank
1#
RobertFrank Published in 2017-09-13 02:21:37Z

I'm trying to read a PGM binary file (http://netpbm.sourceforge.net/doc/pgm.html) to fill a 0-based 2D matrix of integers (16-bit grayscale values).

The file may be 50 megs, so I'm trying to fill a buffer in one call.

I've never done anything with Streams before, but the Google results on Delphi streams going back 20 years and are a cluttered mess in which I couldn't find my way.

I've managed to lock up Delphi (first time in 15 years!) while running some code that uses pointers and buffers (and probably is based on my misunderstanding of an antiquated approach.)

Here's my pseudo code, doing it integer by integer. Is there a way to do the read and fill of the matrix with a single Stream call? (Assuming the file was created on the same machine, so byte-sex is the same.)

    type 
      TMatrix: Array of Array of Integer;

    procedure ReadMatrix( const AFileName: String;
                          const AStartingByte: Integer;         
                          const AMaxRow: Integer;
                          const AMaxCol: Integer;
                          const AMatrix: TMatrix)
    begin
      SetLength(AMatrix, aMaxRow, aMaxCol);
      Open(AFileName);
      Seek(AStartingByte);
      for Row := 0 to aMaxCol do
        for Col := 0 to aMaxCol do
          AMatrix[Row, Col] := ReadWord
    end;

And, no, this isn't a homework assignment! :-)

RobertFrank
2#
RobertFrank Reply to 2017-09-16 16:21:57Z

As already stated, you cannot read 2D dynamic array in a single operation, because its memory is non continuous. But every 1D subarray can be filled.

I also changed array element type to 16-bit. If you really need matrix of Integer (it is 32 bit), then you have to read 16-bit data and assign elements to Integers one-by-one

 type 
      TMatrix = Array of Array of Word;  

 procedure ReadMatrix( const AFileName: String;
                          const AStartingByte: Integer;         
                          const AMaxRow: Integer;
                          const AMaxCol: Integer;
                          const AMatrix: TMatrix)
var
  FS: TFileStream;
  Row: Integer;   
begin
   SetLength(AMatrix, aMaxRow, aMaxCol);
   FS := TFileStream.Create(AFileName, fmOpenRead);
   try
      FS.Position := AStartingByte;
      for Row := 0 to aMaxRow - 1 do
         FS.Read(AMatrix[Row, 0], SizeOf(Word) * aMaxCol);
   finally
      FS.Free;
   end;
end;
You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.315715 second(s) , Gzip On .

© 2016 Powered by cudou.com design MATCHINFO