Einzelnen Beitrag anzeigen

Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#4

Re: Bild scannen und als Tiff speichern

  Alt 30. Dez 2005, 09:00
Zitat von Kerberos:
Habe mir als erstes ein Record gebastelt für den Header:

Delphi-Quellcode:
type IMGHeader=record
  Sequenz:smallint; //Hex 4949 für little-endian Format
  Kennzeichen:smallint; //Hex 002A für TIFF mit Nummer 42
  Zeiger:Pointer; //Zeiger aufs erste IFD
  end;
Nun ja, den Zeiger solltest du nicht extra als Pointer abspeichern. Zwar entspricht das was du speicherst in gewisser Weise einem Pointer, aber du kannst es auch gleich als Cardinal/Integer Speichern. Es ist nur der Wert der Adresse. Arbeitest du mit einem Stream (was ich dir empfehlen würde), so musst du eh die Adresse als Integer angeben.

Zitat von Kerberos:
Das zu speichernde Bild hab ich als TBitmap vorliegen.

Als nächstes möchte ich die Ausgabe-Datei erstellen:

1. Problem: wie speicher ich den Header in ner neuen Datei ab?(stream oder wie mach ichs am geschicktesten?)
2. Problem: woher weiss ich denn, wo die IFD's dann beginnen sollen? (für Zeiger aufs erste)
zu 1.
Ja, benutz einfach einen Stream. Am einfachsten beginnt dein Abspeichern mit dem Teil, der bei dir nun ja, statisch sein könnte. Wenn du einfach fest Little Endian wählst und (zu 2.) dein IFD immer direkt hinter dem Header starten lässt, dann ist der Header immer gleich und du musst dir über den keine Gedanken machen.

Zitat von Kerberos:
Dann muss ich ja das (erste) IFD speichern...
wie mache ich denn das? Die Werte für die Tags kann ich zum Teil ja aus dem Bitmap ermitteln (Length, Width, Resolution)
Die restlichen Werte muss ich dann einfach so setzten? Wie ermittel ich denn die Strips? (Byte Count)
Ja, einen großen Teil deiner Tags kannst du auslesen. Wenn du erstmal nur ein Bild pro Tiff benutzt, ist der nächste IFD Offset 0, DateTime kannst du natürlich leicht selbst ermitteln (format beachten!), PageNumber wäre auch deine Sache.
RowsPerStrip und Strip Byte Count sind Abhängig von einander (in gewisser Weise), dazu gehören natürlich auch die StripOffsets. Auch hier würde ich an deiner Stelle erstmal zu der einfachsten Lösung greifen: 1 Strip => 1 StripOffset, RowsPerStrip = Bitmap.Height, StripByteCount = Bitmap.Width * Bitmap.Height * BytePerPixel. BytePerPixel wäre also für 24 Bit RGBs einfach 3, für 8 Bit Graustufen 1 Byte.
Bist du dir mit deiner PhotometricInterpretation 0 sicher? Waren dass nicht Schwarz-Weiß Bilder? Müsste ich aber selbst erst nachgucken, glaube mal du hast da Recht. Oh, du benutzt Kompression, dass ändert natürlich ein wenig was an den StripByteCount.
Du müsstest dann natürlich alle Bits der Bitmap (also nur die die Bildinformation enthalten) aus der Bitmap kopieren. Diese packst du dann nach CCITT 4 und die größe dieser gepackten Bytes ist dann dein StripByteCount.
Was das Packen angeht, so musst du dir einfach mal den Algorithmus anschauen (ich kenn den jetzt nicht). Dann kopierst du einfach die Bilddaten aus dem Bitmap (z.B. in ein Array) und packst diese. Zurückspeichern kannst du das erstmal in ein Array und dieses in den Stream schreiben oder wenn möglich auch gleich das Ergebnis in den Stream schreiben. Da solltest du gucken, was für dich einfacher und übersichtlicher ist (nachbessern geht immer).

Ja, das wäre es dann schon. Du kannst dazu ganz einfach vorgehen, du weißt ja schon wie groß dein Tiff wird (feste Anzahl von IFD-Entrys). Jedes Entry hat hier auch eine feste Größe, also ich meine hier, jeder Wert lässt sich durch 32-Bit darstellen. Einzige Ausnahme sind natürlich die eigentlichen Bilddaten. Aber hier hast du einen Zeiger (StripByteOffsets) auf diese Daten. D.h. du kannst sehr einfach den Header und das IFD hintereinander weg schreiben und die Bilddaten fest direkt hinter das erste IFD legen (der Offset zeigt dann natürlich auf diese Stelle!)

Ist natürlich noch kein perfekter Weg, aber ich denke für deine Zwecke reicht das doch erstmal?
  Mit Zitat antworten Zitat