Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Binärbild einlesen (https://www.delphipraxis.net/157244-binaerbild-einlesen.html)

alleinherrscher 4. Jan 2011 21:03

Delphi-Version: 2005

Binärbild einlesen
 
Hi@all!

Unser Tunnelmikroskop an der Uni liefert Höhendaten einer Probe in Binärform.
Ich weiß, dass in der Datei 550x550 Zahlen stehen müssen, also insgesamt 302500.

Die Datei ist 605000 Byte groß. Daher müsste eine Zahl 16 Bit einnehmen. Bei den Zahlen handelt es sich um einen Integertyp.

Ich lese die Datei per Filestream ein und möchte dann ein 550x550 Pixel großes Bild mit den farblich kenntlich gemachten Höheninformationen erstellen.

Mein bisheriger Ansatz:
Delphi-Quellcode:
procedure ReadFile(filename:string);
var fs:TFileStream;
    buf: smallint;//array[0..3] of Byte;
    i:cardinal;
begin
fs:=TFilestream.Create(filename,fmopenread);
fs.Position:=0;
i:=0;
while fs.Position<fs.Size do
  begin
   inc(i);
   fs.read(Buf,2);
   form1.Image1.Canvas.Pixels[i mod 550,i div 550]:=Buf;
  end;
freeandnil(fs);
end;
Jetzt meine Frage: Wenn ich die Datei im Hexeditor ansehe, stehe ich, dass die ersten 2 Byte nur aus Nullen bestehen, also 0000 0000 0000 0000
Lasse ich mir allerdings den ersten eingelesenen Wert in meinem Delphi Programm ausgeben (mit inttostr(Buf)) steht dort der Wert 4352.

Kann mir jemand erklären, was ich falsch mache? Hat Delphi ein spezielles Integerformat oder so?

Grüße,
Michael

mkinzler 4. Jan 2011 21:10

AW: Binärbild einlesen
 
Und was steht im 3. und 4.? Ich tippe mal mal auf Big Endian -> Swap()

alleinherrscher 4. Jan 2011 21:13

AW: Binärbild einlesen
 
Geht weiter mit:

0001 0001 0001 0001

Big Endian? Swap?

//edit gerade mal gelesen, was Big Endian ist...aber müsste das nicht egal sein, bei 0000 0000 0000 0000 ?

mkinzler 4. Jan 2011 21:15

AW: Binärbild einlesen
 
Ich vermutete, dass die Datei im Big Endian Format ist, Intel verwendet aber Littel Endian, so dass die Bytes vertauscht sind
http://de.wikipedia.org/wiki/Byte-Reihenfolge
Mit Swap() kann man diese Tauschen

Neutral General 4. Jan 2011 21:40

AW: Binärbild einlesen
 
Nur ne kleine Anmerkung am Rande. Ich würde statt SmallInt vielleicht lieber den Datentyp "Word" benutzen. Vorzeichen brauchst du wohl eher nicht und die verwirren im Zweifelsfall nur.(bzw. könnte denke ich auch wirklich Probleme geben)

Aphton 5. Jan 2011 00:17

AW: Binärbild einlesen
 
Probier mal folgendes und sag bescheid, obs geklappt hat:

Delphi-Quellcode:
procedure ReadFile(filename:string);
var fs:  TFileStream;
    bmp: TBitmap;
    p:   PWord;
    x:   Integer;
    y:   Integer;
begin
  bmp := TBitmap.Create;
  try
    bmp.PixelFormat := pf16bit;
    bmp.Width := 550;
    Bmp.Height := 550;
    fs := TFileStream.Create( filename, fmOpenRead );
    try
      for y := 0 to bmp.Height - 1 do
      begin
        p := bmp.ScanLine[y];
        for x := 0 to bmp.Width - 1 do
        begin
          fs.Read( p^, 2 );
          inc( p );
        end;
      end;
      form1.Image1.Picture.Bitmap.Assign( bmp );
    finally
      fs.Free;
    end;
  finally
    bmp.Free;
  end;
end;

Assarbad 5. Jan 2011 00:51

AW: Binärbild einlesen
 
Zitat:

Zitat von alleinherrscher (Beitrag 1072282)
//edit gerade mal gelesen, was Big Endian ist...aber müsste das nicht egal sein, bei 0000 0000 0000 0000 ?

Ja, bei diesem Wert ja, egal ob eine Vierergruppe 2 Byte oder 1 Nibble darstellen soll.

Was sind denn das für Höhendaten? Hättest du mal ein Histogramm von der Verteilung der Werte? Wobei mich auch noch interessieren würde, wie die Verteilung bei HiByte und LoByte aussieht ...

Immerhin kann es 16bit Ganzzahl, 16bit Festkommazahl oder 16bit Gleitkommazahl sein ... die Bedeutung der "Höhe" und ggf. die Längeneinheit könnte u.U. helfen das Rätsel zu lösen.

Aphton 5. Jan 2011 01:04

AW: Binärbild einlesen
 
Du könntest sogar mal die Datei hier hochladen!

sx2008 5. Jan 2011 01:19

AW: Binärbild einlesen
 
Die richtige Vorgehensweise wäre so:
1.) ein 2-dimensionales Array der Grösse 550 * 550 anlegen
Delphi-Quellcode:
type
  TTunnelDataArray = array[0..549, 0..549] of SmallInt;
var
  tunneldata : TTunnelDataArray;
2.) die Datei auf einen Rutsch auf das Array einlesen einlesen
2b.) ggf. eine Korrektur der Byteorder für jedes Arrayelement vornehmen
die nachträgliche Korrektur ist wesentlich schneller und einfacher als wenn man dies direkt beim Einlesen vornehmen würde.
3.) ein Bitmap mit 24 Bit Farbtiefe mit entsprechende Grösse anlegen
4.) eine Zuordnung zwischen Höhenwert und Farbe vornehmen
Der Höhenwert kann theoretisch zwischen -32768 bis +32767 bzw. zwischen 0 bis 65535 schwanken
In der Praxis gibt es aber einen Minimal und einen Maximalwert.
Der Minimal- und Maximalwert muss über 2 verschachtelte Schleifen, die jeden Wert des Array prüfen, ermittelt werden
4b.) bei bekannten Minimal- und Maximalwerten muss versucht werden diese möglichst sinnvoll auf das vorhandene Farbspektrum umzusetzen ("color mapping").
Dies ist der entscheidende und wichtiste Schritt der ganzen Aufgabe.
Und es ist genau das gleiche Problem, dass sich auch beim Zeichnen der Mandelbrot-Menge stellt.
Man kann z.B. die Höhenwerte gleichmässig auf ein Regenbogenspektrum verteilen.
Problem dabei: kleine Höhenunterschiede bleiben unsichtbar, weil das menschl. Auge Farben die eng zusammenliegen schlecht unterscheiden kann.
Oder man wählt z.B. 32 feste Farben aus und wendet die Modulo-Operation an:
Delphi-Quellcode:
hoehenwert := tunneldata[x,y];
farbe := FarbenArray[hoehenwert mod 32];
Welche Art des color mapping besser ist hängt vom Objekt unter dem Tunnelmikroskop ab.

5.) mit einer 2-fachen Schleife füllt man das Bitmap für jedes Pixel.
Man beginnt dabei zuerst das Bitmap über das Property Pixels[] zu füllen.
Dies ist aber sehr langsam.
Daher sollte man in einem nächsten Schritt den Vorgang über das Property Scanline beschleunigen.
Als unerfahrener Delphiprogrammierer sollte man nicht sofort mit Scanline beginnen sondern zuerst mit der langsamen Methode sicherstellen, dass das color mapping richtig funktioniert!

Thom 5. Jan 2011 01:25

AW: Binärbild einlesen
 
Ups - Gedankenfehler...


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:39 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz