AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi Bild scannen und als Tiff speichern
Thema durchsuchen
Ansicht
Themen-Optionen

Bild scannen und als Tiff speichern

Ein Thema von Kerberos · begonnen am 29. Dez 2005 · letzter Beitrag vom 3. Jan 2006
Antwort Antwort
Kerberos

Registriert seit: 2. Aug 2005
19 Beiträge
 
#1

Bild scannen und als Tiff speichern

  Alt 29. Dez 2005, 20:53
Wie der Titel schon verrät, möchte ich aus meiner Anwendung heraus Bilder einscannen und als Tiff-Datei speichern. Das Scannen klappt auch schon prima, bekomme das Bild als Bitmap. Nun ist die Frage, wie ich daraus eine Tiff mache... Habe mir die Definitionen für Tiff schon angesehen (also Header+IFD+Bilddaten=Tiff) und denke auch, das ichs soweit verstanden habe. Nun hänge ich irgendwie bei der Umsetzung...

Folgendes Ziel:

Es soll eine Datei erstellt werden, die mehrere Bilder enthält. Also folgender Aufbau ist geplant:

Header
--------------------------------
IFD
--------------------------------
IFD
--------------------------------
usw
--------------------------------
Bilddaten 1
--------------------------------
Bilddaten 2
--------------------------------
usw

zum setzen der Tags benutze ich die LibTiffDelphi-Komponente LibTiffDelphi

Bekomme es aber nicht hin, aus dem Bitmap ein Tiff zu erzeugen. Vielleicht hat sich ja schon wer mit der Tiff-Thematik befasst, und kann mir weiterhelfen?

mfg
Kerberos
  Mit Zitat antworten Zitat
Der_Unwissende

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

Re: Bild scannen und als Tiff speichern

  Alt 29. Dez 2005, 23:02
Hi,
ich habe mich mal etwas mit Tiff beschäftigt und die 6.0 Spezifikation implementiert (brauchte eine Komponente um auch mit 16-Bit Graustufen bzw. 48-Bit Farbe umzugehen). Diese Implementierung kann ich dir leider nicht zur Verfügung stellen, da ich keine Rechte an ihr habe (die hat mein Arbeitgeber).

Aber ich kann dir gerne bei Fragen weiter helfen. Müsstest dann natürlich etwas genauer sagen, woran es im Moment scheitert bzw. was du schon fertig hast.
An sich ist der von dir gezeigte Aufbau korrekt. Trotzdem gibt es ein paar Kleinigkeiten zu beachten, damit ein Tiff korrekt angezeigt wird. So benötigt IrfanView unbedingt eine gültige X- und YResolution, Photoshop brauchte eine PhotometricInterpretation (denke war das Feld). Also sollte ein Tiff mal von einem Programm nicht angezeigt werden, schau einfach mal, ob du alle Pflichtfelder gesetzt hast (und welche das Programm selbst setzt). Häufig scheitert es wirklich nur daran.

Da ich die LibTiff nicht wirklich kenne (die unterstützte keine 16-Bit Layer), weiß ich nicht was du da schon hast (oder eben nicht). Wenn du nichts all zu komplexes machst (also z.B. erstmal feste Byteorder, feste Pixelrate,...) dann kannst du ein einfaches Grundgerüst sehr leicht auch selbst erstellen.
Adobe hat eine ganz gute Doku/Spezifikation die sehr hilfreich ist.

Der Aufbau ist wirklich einfach, du startest mit einem Header, der enthält die ByteOrder (Little (II) oder Big Endian (MM)) benannt nach dem jeweiligen größten Vertreter (II = Intel, MM = Motorola). Dem folgt die Tiff-Identifikationsnummer 42 (oder war's Hex 42?) und dann der Offset zum ersten IFD (Tiff ist da sehr flexibel).
Auch der Aufbau eines IFDs ist an sich immer sehr einfach. Du sagst nur, wie viele Felder das IFD hat, dann kommen die Tags und zum Schluss der Offset zum nächsten IFD (0 wenn Letztes).
Ein Tag besteht wiederum aus mehreren Teilen.
Du hast erstmal eine Nummer, die das Tag identifiziert, dann kam der Datentyp, die Anzahl (Reihenfolge nachlesen) und zum Schluß der Wert. Sollte ein Wert (die Werte) zusammen (für den jeweiligen Datentypen) größer als 32 Bit sein, steht statt dem Wert ein Zeiger auf die Daten (das Datum).

Das war's eigentlich schon (sehr grob). Wenn du schon Tiffs erstellst, die nur nicht angezeigt werden, poste einfach eins und ich würde es mir anschauen. Falls du sonst irgendwelche fragen hast, vielleicht kann ich dir helfen (ist zwar schon wieder ein klein wenig her, aber auch nicht so ewig).

Gruß Der Unwissende
  Mit Zitat antworten Zitat
Kerberos

Registriert seit: 2. Aug 2005
19 Beiträge
 
#3

Re: Bild scannen und als Tiff speichern

  Alt 30. Dez 2005, 08:16
erstmal danke für deine schnelle Antwort...

Ich denke, das Hauptproblem besteht darin, das ich noch ziemlicher Delphi-Neuling bin

Also wie der Aufbau des Headers aussehen soll hab ich(denk ich mal) verstanden. Auch welche Tags ich benötige, denn das ist bei meiner Aufgabe vorgeschrieben

Ich brauche folgendes(vorgeschriebene Werte):

Anzahl der Tags
Image Width
Image Length
Compression(4=CCITT Group 4)
Photometric Interpretation(0)
Fill Order(1 oder 2)
Document Name
Strip Offsets
Orientation(1)
Rows per Strip(2**32-1)
Strip Byte Count
Xresolution(=>200)
Yresolution(=>200)
Resolution Unit(2=Zoll)
Page Number
Date Time
Next IFD Offset

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;
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)

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)

Bei Strip-Offset muss ja dder Zeiger auf die Bilddaten hin... wie ermittel ich den denn?

Und zu guter letzt: Wie Speicher ich denn die Bilddaten in die neue Datei? Einfaches kopieren kann ja nicht gehen wegen der Compression

Fragen über Fragen... Wie man sieht bin ich halt noch ziemlicher Delphi-Neuling. Sind sicherlich Probleme, die leicht zu lösen sind (bis auf das mit den Bilddaten) aber ich komm da irgendwie nicht mit klar. Aber man wächst ja an seinen Aufgaben
  Mit Zitat antworten Zitat
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
Kerberos

Registriert seit: 2. Aug 2005
19 Beiträge
 
#5

Re: Bild scannen und als Tiff speichern

  Alt 3. Jan 2006, 21:28
so, bin leider erst jetzt dazu gekommen... immer dieser Feiertagsstress...

hab die Umsetzung dank dir hinbekommen.


vielen dank!

Ging dann ja doch einfacher, als befürchtet. Tja, man sollte halt immer jemanden Fragen, der sich mit sowas auskennt..

Mfg
Kerberos
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:31 Uhr.
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