2017-09-13 1 views
0

Ich versuche, eine PGM-Binärdatei (http://netpbm.sourceforge.net/doc/pgm.html) zu lesen, um eine 0-basierte 2D-Matrix von ganzen Zahlen (16-Bit-Graustufen) zu füllen.Verwendung von TStream zum Füllen einer Matrix von Ganzzahlen

Die Datei kann 50 MB sein, also versuche ich einen Puffer in einem Anruf zu füllen.

Ich habe noch nie etwas mit Streams gemacht, aber die Google-Ergebnisse auf Delphi-Streams reichen 20 Jahre zurück und sind ein Chaos, in dem ich mich nicht zurechtfinden konnte.

Ich habe es geschafft, Delphi einzusperren (zum ersten Mal in 15 Jahren!), Während einige Code ausgeführt wird, der Zeiger und Puffer verwendet (auf meinem Missverständnis besteht aus einem veralteten Ansatz und wahrscheinlich basiert.)

mein Pseudo Hier Code, ganzzahlig nach Ganzzahl. Gibt es eine Möglichkeit, die Matrix mit einem einzigen Stream-Aufruf zu lesen und zu füllen? (Vorausgesetzt, die Datei wurde auf der gleiche Maschine erstellt, so Byte-Sex ist das gleiche.)

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; 

Und, nein, das ist keine Hausaufgabe! :-)

+0

Um Ihre Frage zu vergeben, werden Sie nicht in der Lage sein, fülle 2D-Array von Ganzzahlen mit einzelnen oder doppelten (abhängig vom 'Maxval'-Wert) Byte-Pixelintensitätswerten in" einem Aufruf ". Aber warum dieses Intermediate Array? Möchtest du lieber einen 'TGraphic' Nachkommen und Datenspeicher erstellen, z. als ein flacher Byte-Puffer (und Index-Pixel in Scanline-Art)? – Victoria

+0

Warum brauchen Sie das in einem Anruf? Das wäre möglich, aber nicht für ein dynamisches 2D-Array. Sie könnten ein dynamisches 1d-Array verwenden und anschließend Ihre eigene Indexierung durchführen. –

Antwort

2

Wie bereits erwähnt, können Sie dynamische 2D-Arrays nicht in einer einzigen Operation lesen, da der Speicher nicht kontinuierlich ist. Aber jedes 1D-Unterfeld kann gefüllt werden.

Ich änderte auch Array-Elementtyp auf 16-Bit. Wenn Sie wirklich Matrix von Integer müssen (es ist 32-Bit), dann müssen Sie 16-Bit-Daten lesen und Elemente Ganze Zahlen 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; 
+1

Entsprechend dieser Formatspezifikation können Pixelintensitätswerte auch ein einzelnes Byte sein (aber das ist ein Fehler einer Frage, wie gefragt). – Victoria

+1

@Victoria Ich hoffe, dass Autor Header analysiert (zumindest verwendet er 'AStartingByte') – MBo

+0

Danke MBo für den Code und sowohl Sie und Victoria für die Köpfe auf meine Verwendung. Ich benutze Option -4, so dass Intensitäten immer ein Wort sein werden. Ich schätze wirklich Ihre Beiträge hier. – RobertFrank

Verwandte Themen