Posts mit dem Label validator werden angezeigt. Alle Posts anzeigen
Posts mit dem Label validator werden angezeigt. Alle Posts anzeigen

Montag, 26. Februar 2018

Valid TIFFs need love, too.

(english version below)

Über einen Kollegen haben wir ein interessantes TIFF erhalten. Es hatte alle Validierungen bestanden und zeigte keine strukturellen Fehler in tiffinfo/tiffdump, ließ sich aber trotzdem im Vorschaubetrachter des Workflowtools nicht anzeigen. Außerdem war es ca. dreimal so groß wie alle anderen Scans aus dem gleichen Vorgang. Er bat uns, das TIFF zu untersuchen.

Im Gegensatz zu ihm habe ich keine Probleme damit gehabt, das TIFF überhaupt zu öffnen; der Windows-Bildbetrachter, IrfanView, MS Paint, Paint.NET und XnViewMP stellten alle das Bild dar. Allerdings war es in der Horizontalen stark gestreckt, d.h. deutlich breiter als erwartet. Große Teile des Bildinhaltes (eine gescannte Zeitschriftenseite) fehlten, und der rechte Rand war nicht sichtbar. 

kaputte Anzeige des TIFFs

In tiffinfo sahen wir, dass das TIFF ein Grayscale-Image ist:
Bits/Sample: 8
Samples/Pixel: 1

Auffällig war, dass die Listeneinträge für StripByteCounts genau um Faktor 3 größer als die ImageWidth waren (4302 * 3 = 12906); das erklärte die Streckung des Bildes in X-Richtung. Man sah außerdem, dass die StripOffsets in Schritten von 12906 Bytes anwuchsen; vermutlich war der Viewer deswegen überhaupt in der Lage, irgendein Bild anzuzeigen. Die ImageLength stimmte mit der Anzahl der Einträge in StripByteCount überein (6020), deshalb gab es hier keine Verzerrung.
Image Width: 4302
Image Length: 6020
StripByteCounts (279) LONG (4) 6020<12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 ...> StripOffsets (273) LONG (4) 6020<8 12914 25820 38726 ...>

In Okteta konnten wir sehen, dass die Bilddaten für jedes Pixel dreimal identisch gespeichert waren. Das deckt sich der Aussage des Kollegen, dass das Bild ca. dreimal größer war als alle anderen Scans im gleichen Vorgang. Außerdem haben wir gesehen, dass das IFD0 am Dateiende stand und Hinweise auf Bearbeitungen mit IrfanView enthielt.

normales RGB-TIFF

defektes TIFF mit zwei Bytes redundanten Grayscale-Daten je Pixel


Nachdem wir das Problem verstanden hatten, haben wir Reparaturmöglichkeiten diskutiert:
- Man könnte die Redundanz der Pixel entfernen und die StripOffsets (und wahrscheinlich noch andere Offsets) anpassen. Das wäre wahrscheinlich die sauberere Lösung, müsste aber definitiv mit Softwareunterstützung getan werden.
- Man könnte die SamplesPerPixel auf "3" setzen, um die drei duplizierten Bytes je Pixel als RGB-Kanäle zu interpretieren und damit drei Bytes zu einem Pixel im Bild zusammenzufassen. Das haben wir getan, und es hat funktioniert; zumindest war das Bild anzeigbar, nicht gestaucht und nicht in ausgefallene Farben getaucht.

Zur Ursache des Fehlers gab es nun zwei Theorien:
- Es könnte einen Bitflip gegeben haben, bei dem SamplesPerPixel beschädigt wurde: der Weg von "00 11"B ("0 3" D) zu "00 01"B ("0 1" D) ist nicht weit und würde das Fehlerbild erklären.
- Es könnte einen Fehler bei der Konvertierung eines RGB-Scans von einer Grayscale-Vorlage gegeben haben, bei dem die überzähligen Bytes pro Pixel nicht entfernt wurden. Das SamplesPerPixel Tag wäre dabei korrekt und absichtlich gesetzt worden.

Als erstes haben wir nun also SamplesPerPixel im Hex-Editor auf "3" gesetzt, um den TIFF-Viewer anzuweisen, die Bilddaten als RGB-Bild zu interpretieren. Schon diese kleine Änderung bewirkte, dass sich das Bild fehlerfrei anzeigen ließ. Der Umstand, dass das Bild ungewöhnlich groß war (wir hatten erwartet, dass es ähnlich groß wäre wie die anderen Scans aus der gleichen Zeitschrift), blieb aber vorerst ungeklärt.

defektes Grayscale-TIFF, als RGB interpretiert


korrekte Anzeige des TIFFs

Wir erwägen, eine Plausibilitätsprüfung für diesen Fehlertyp in checkit_tiff zu implementieren, sofern man davon ausgeht, dass innerhalb eines Bildes alle Strips gleich lang sind. Dazu verwendet man die Formel: "StripByteCounts / SamplesPerPixel / RowsPerStrip = ImageWidth". Am einfachsten funktioniert das mit TIFFs, bei denen RowsPerStrip = 1 ist; andernfalls müssen zusätzlich komplexere Prüfungen durchgeführt werden, weil bei mehrzeiligen Strips, deren Bytelänge nicht ohne Rest ganzzahlig durch die Zeilenanzahl teilbar ist, kein Padding angefügt wird. Dadurch können Rows entstehen, die kürzer sind als die vorderen Rows eines Strips. 

Zusätzlich denkbare Plausibilitätsprüfungen wären:
- Die Höhe des Bildes ist genau so lang wie das Produkt aus RowsPerStrip und Anzahl der Strips: ImageLength = RowsPerStrip * StripOffsets.Count
- Jeder StripByteCount muss so groß sein wie die Differenz der dazugehörigen StripByteOffsets: StripByteCounts[0] = StripOffsets[1] - StripOffsets[0] (bzw. allgemeiner StripByteCounts[n] = StripOffsets[n+1] - StripOffsets[n])
- Jeder Strip muss gleich lang sein: StripByteCounts[0] = StripByteCounts[1] = StripByteCounts[2] = ... = StripByteCounts[n]

Diese Möglichkeiten haben wir im größeren Kreis diskutiert, was Andreas neugierig gemacht hat. Er hat also sein neues Tool zum Finden möglicher ehemaliger IFDs in TIFFs um einige weiche Suchkritierien erweitert und es genutzt, um IFDs aus früheren Dateiversionen zu finden. Außerdem hat er ein ganz neues Tool geschrieben, das eine TIFF-Datei und eine Adresse in Hex-Notation einliest und den Inhalt an dieser Adresse so interpretiert, als wäre dort ein IFD gespeichert. Auf diese Weise konnten wir insgesamt sechs frühere IFDs ermitteln, die auf ältere Versionen der Datei hinweisen, und den Inhalt dieser IFDs in Augenschein nehmen. Die Tools sind unter https://github.com/SLUB-digitalpreservation/fixit_tiff/tree/master/src/archeological_tools im Quellcode verfügbar; sie sind Teil des bekannten Tools fixit_tiff.

Pointer zum ursprünglichen IFD0, wie er in der ersten Version der Datei stand

Die Ausgabe möglicher IFD-Adressen sieht so aus:
# adress,weight,is_sorted,has_required_baseline
0x4a184b0,2,y,y
0x4a241aa,2,y,y
0x4a2fea4,2,y,y
0x4a3bbb0,2,y,y
0x4a478d0,2,y,y
0x4a535ea,2,y,y

Diese Adressen der IFDs haben wir mittels Hex-Editor als IFD0-Offset in die TIFF-Datei eingetragen und so in einer Art TIFF-Archäologie schrittweise die alten Versionen der Datei wieder hergestellt. Dabei bestätigte sich die Annahme, dass der Scan ursprünglich in RGB abgespeichert worden war. Danach wurde wohl eine fehlerhafte Grayscale-Konvertierung durchgeführt, bei der nur die Tags PhotometricInterpretation (min-is-black) und BitsPerSample (1) verändert wurden. Ob dabei auch die Bilddaten selbst verändert wurden, lässt sich nicht mehr genau rekonstruieren.

In der vermutlich ersten Version des IFD0 sieht man mit tiffinfo noch die Angaben zum RGB-Bild:
Photometric Interpretation: RGB color
Samples/Pixel: 3

Die späteren Fassungen dagegen enthalten die Werte:
Photometric Interpretation: min-is-black
Samples/Pixel: 1

Außerdem wurden noch einige weitere Versionen des TIFFs erzeugt, bei denen einige andere Tags verändert, hinzugefügt oder entfernt wurden (Make, Model und Software).

Der Fehler war überhaupt nur aufgefallen, weil es eine intellektuelle Prüfung gab und der Bearbeiterin der Anzeigefehler auffiel (und sie ihn dann auch gemeldet hat!). Weil außerdem die MD5-Summen erst am Ende der Bearbeitung generiert werden und damit zum Fehlerzeitpunkt noch keine Prüfsumme existierte, wäre der Fehler nicht durch einen Fixity-Mismatch aufgefallen. Die einzig saubere Lösung wird nun wohl sein, die Seite neu zu scannen. Trotzdem ist es aber sehr eindrucksvoll zu sehen, welche Möglichkeiten das TIF Format bietet, kaputte Dateien wiederherzustellen.

frühere Artikel zu diesem Thema (also available in English):



-------------------------------------------------------------------------------------------------------------------

english version

A few days ago, a colleague gave us an interesting TIFF. It had successfully completed all validation attempts and didn't show any signs of structural issues in tiffinfo/tiffdump. However, it was not possible to display the image in the preview of the workflow tool used. Also, it was about three times the size of the other scans in the same intellectual entity. Our colleague asked us to have a closer look at that TIFF, so we went at it.

In contrast to our colleague, I didn't have any problem in displaying the TIFF altogether; the  Windows Image Viewer, IrfanView, MS Paint, Paint.NET und XnViewMP all displayed the image correctly. However, it was significantly stretched horizontally, which means that it was a lot wider than expected. Large parts of the scanned newspaper page were missing, and the rightmost part of the image was not visible.

broken display of the TIFF

In tiffinfo, we saw that the TIFF is a grayscale image:
Bits/Sample: 8
Samples/Pixel: 1

Particularly striking was the fact that the list entries for StripByteCounts was exactly by faktor 3 larger than the ImageWidth (4302 * 3 = 12906), which explained the stretch we saw in the image. Also, you could see that the StripOffsets grew in steps of 12906 Bytes; presumeably that's why the viewer was able to display a picture in the first place, regardless of the final quality. The ImageLength matched up with the number of entries in StripByteCount (6020), which is why there was no stretch in vertical direction.
Image Width: 4302
Image Length: 6020
StripByteCounts (279) LONG (4) 6020<12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 12906 ...> StripOffsets (273) LONG (4) 6020<8 12914 25820 38726 ...>

We could see in Okteta that the image data for each pixel were saved identically three times in a row. That explains our colleagues information about the filesize being three times larger than the other files in that IE. Also, we noticed that the IFD0 was written to the end of the file and contained information about an editing step in IrfanView.

normal RGB-TIFF

defective TIFF with two Bytes of redundant grayscale data per pixel

After having understood the problem, we discussed possible ways to repair the file:
- We could remove the redundant pixels and adapt the StripOffsets (and quite possibly all other ofsets in that file). While this is the more proper solution, software support for this kind of work would be imperative.
- We could set SamplesPerPixel to"3" to interpret the three duplicate pixels each as three RGB channels, thus summarizing three Bytes into one pixel. We actually did that, and it worked like a charm; at least we could display the image without getting any stretching or funky colors.

Now we had two theories about the origin of this error:
- There might have been a bit flip that damaged SamplesPerPixel. It's not a long way to go from "00 11"B ("0 3" D) to "00 01"B ("0 1" D), and it would explain the error we're seing.
- There could have been an error during a conversion of an RGB scan that was made from an analog grayscale template, during which the unnecessary pixels have not been removed. During this conversion, the SamplesPerPixel tag would have been rightfully set to a new value.

In a first test we set SamplesPerPixel to "3" using a Hex editor in order to command the TIFF viewer to interpret the image data in an RGB fashion. This little change alone caused the image to be displayed without any errors. The puzzle, however, that the image was uncommonly large (we expected it to about ad big as the other scans from the same newspaper) remained unsolved.


defective grayscale TIFF, interpreted as RGB

TIFF displayed correctly

We contemplated implementing plausibility checks for this type of error in checkit_tiff, which would be easily feasible assuming that all Strips in an image are of the same length. The following formula could be used: "StripByteCounts / SamplesPerPixel / RowsPerStrip = ImageWidth". This works best for TIFFs with RowsPerStrip = 1 set; other TIFFs would have to undergo more complex checks, because multiline Strips with byte counts that cannot be divided by the row number without modulo may not contain any padding. Due to this, there may be Rows that are shorter that the previous Rows in the same Strip. 

Other possible plausibility checks include:
- The image height is exactly as large as the multiplication product of RowsPerStrip and number of Strips: ImageLength = RowsPerStrip * StripOffsets.Count
- Each StripByteCount must be equally large as the difference of the neighboring StripByteOffsets: StripByteCounts[0] = StripOffsets[1] - StripOffsets[0] (or more general StripByteCounts[n] = StripOffsets[n+1] - StripOffsets[n])
- Each Strip needs to be equally long: StripByteCounts[0] = StripByteCounts[1] = StripByteCounts[2] = ... = StripByteCounts[n]

We discussed these possibilities in a larger group, which made Andreas curious, so he sat down to enhance his tool for finding candidates for former IFDs in TIFFs by some soft search criteria. Furthermore, he created an entirely new tool reads a TIFF and interprets the contents at a given address in a way that ressembles the IFD structure. This way, we were able to identify six former IFDs that hint to older versions of this file and inspect these IFDs a little further. The tools are available at https://github.com/SLUB-digitalpreservation/fixit_tiff/tree/master/src/archeological_tools in source code, they are part of the established tool fixit_tiff.

Pointer to the original IFD0, just like it was stored in the 1st file version

The list of possible IFD addresses as given by our tools looks like this:
# adress,weight,is_sorted,has_required_baseline
0x4a184b0,2,y,y
0x4a241aa,2,y,y
0x4a2fea4,2,y,y
0x4a3bbb0,2,y,y
0x4a478d0,2,y,y
0x4a535ea,2,y,y

We inserted these IFD addresses into the file's IFD0 offset pointer using a Hex Editor. Step by step, using this method, we were able to recreate older versions of the file in an archaeology style of work. In the course of the work we could confirm that the scan was originally saved in RGB. Later, there must have been an error in a grayscale conversion where only the tags PhotometricInterpretation (min-is-black) and BitsPerSample (1) were changed. We were not able to find out if the image data had been altered as well.

Ttiffinfo shows these information from the preusmeable 1st IFD0 version of the RGB image:
Photometric Interpretation: RGB color
Samples/Pixel: 3

Later versions, however, contain the values:
Photometric Interpretation: min-is-black
Samples/Pixel: 1

Also, there have been later files versions where some other tags have been added, altered or deleted (Make, Model and Software).

The error was only even discovered because intellectual checks were in place and the human operator noticed the error in displaying the TIFF (and because she decided to inform our colleague of this oddity!). Also, because checksums are only generated after the processing workflow is completed, we wouldn't have noticed the error by a fixity mismatch. We simply didn't have any checksums yet to compare the image against. In the end, the only proper solution will be a rescan of that newspaper page. However, it's still impressive to see the possibilities that TIF offers to repair seemingly broken images.

former articles on this subject (also available in English):

Donnerstag, 9. Juni 2016

Formatidentifikation vs. Formatvalidierung - Wem glauben wir eigentlich?

Deutsch (english version below)


Wer in der Lage sein will, die Daten in seinem digitalen Langzeitarchiv auch in Zukunft noch durch Migrationen verfügbar zu halten, muss schon beim Ingest darauf achten, dass die eingelieferten Dateien auch den einschlägigen Standards und Spezifikationen entsprechen.

Bisher fährt man dafür einen zweistufigen Ansatz. Zuerst identifiziert man den Dateityp einer Datei (z. B. anhand der Dateiendung oder einer Signatur) mit einem Werkzeug wie DROID, dann prüft man sie mit einem Formatvalidator. Dieser Ansatz stellt den Anwender aber vor ein fundamentales Problem: was passiert, wenn eine Datei die Formatvalidierung nicht besteht? Wer hat Recht? Hat nicht gerade die Formatidentifizierung ergeben, dass man eine Datei eines bestimmten Formates vor sich hat? Warum widerspricht der Validator dann? Momentan speichert das Archivsystem das erkannte Format in den Metadaten ab, selbst wenn die Datei die Formatvalidierung nicht besteht.

Man kann also nur dann davon ausgehen, dass man z. B. eine TIFF-Datei vor sich hat, wenn der Aufbau der Datei auch der TIFF-Spezifikation entspricht. Ist das nicht der Fall, dann hat man auch kein TIFF vor sich, denn der innere Aufbau ist ja sehr eindeutig spezifiziert. Man hat also etwas vor sich, das nur ungefähr so aussieht wie eine TIFF-Datei, aber keine echte TIFF-Datei.

Eigentlich richtig wäre deshalb der restriktivere Ansatz. Die Formatidentifikation darf hier nur ein Hilfsmittel sein, um das richtige Validierungswerkzeug auszuwählen. Nur wenn die Validierung erfolgreich ist, darf auch das erkannte Dateiformat in den Metadaten festgehalten werden; die verbindliche Formatidentifikation findet also implizit bei der Formatvalidierung mit statt. Ist die Validierung nicht erfolgreich, dann könnte man noch das Formatidentifizierungswerkzeug befragen, ob evtl. eine ähnliche Signatur für einen anderen Dateityp hinterlegt ist, und dann die Validierung wiederholen. Ist das nicht der Fall, dann muss man von einem unbekannten Dateityp ausgehen und ggf. die Datei beim Ingest zurückweisen.

Zusatz für ganz Unerschrockene: viele Formate haben eingebettete Formate, Unterformate oder sind selbst Container für andere Formate. Genau genommen müsste man nicht nur das äußerste Format prüfen, sondern auch die korrekte Einbettung der Unterformate und deren eigene Validität. In das Langzeitarchiv dürften die Dateien nur dann aufgenommen werden, wenn auch alle ihre eingebetteten Dateien korrekt validiert werden können. Was das für TIFF (eingebettete ICC-Profile, XMP- & IPTC-Metadaten, ...), OpenOffice Dokumente (XML und Bilder in ZIP eingebettet), PDF (alle möglichen eingebetteten Dateiformate und Codeschnipsel, dazu Links zu externen Quellen), das Webarchivformat WARC (buchstäblich alle Formate, die auf Webseiten vorkommen können) und viele andere Formate bedeutet, mag sich jeder selbst in seinen Alpträumen von der Formathölle ausmalen. Klar ist: im Moment tun wir auch in Ermangelung geeigneter Werkzeuge viel zu wenig um sicherzustellen, dass nur valide Dateien in unsere Langzeitarchive gelangen.


Dienstag, 7. Juni 2016

Validating TIFFs with embedded color profiles

About ICC profile validation


In the last days we enhanced our baseline TIFF conformance checking tool "checkit_tiff" with support to validate TIFFs containing embedded ICC profiles.

There are two specifications of ICC profiles. The first and older one is from the year 2001 and available at http://www.color.org/ICC_Minor_Revision_for_Web.pdf. The second one (and current version) is  http://www.color.org/specification/ICC1v43_2010-12.pdf.

The ICC profile standards are very complex and do not really fit in the design of the checkit_tiff configuration files, so we decided to check only the headers of the embedded ICC profiles for now.

Because the differences between the headers of both standards are very marginal at first sight, this could be simple enough to additionally implement it in checkit_tiff.

For more detailed checks we would need a plugin system to delegate validation of embedded standards (as ICC, XMP and so on) to more highly specialized validators.

Ooops, our tool finds more broken TIFFs again


To test the validation, we ran checkit_tiff against some old tiffs from our digitization collection. As you can see in the following picture, the checkit_tiff tool detects a discrepancy between the size of the embedded ICC-profile as reported in TIFF-tag (34675) and the size reported by the ICC profile itself:





After some analysis we made an interesting observation. The given TIFF reports a size of 13691 bytes (in hex: 0x357b), but the ICC itself (tag "profile size") reports a size of 669051 bytes (in hex: 0xa357b). We thought we had a bug in our TIFF tag or ICC header decoding, but other tools (exiftool or tiffdump) also reported this difference.

As we saw in previous TIFFs, some TIFF implementations are wrong and often some information were missing because of off-by-one errors. In this case, it seems that the software "Omniscan 12.8 Build2476" does not correctly fill the Tiff-tag 34675 for ICC-profile, leaving out the most significant byte (here: '0xa').

We need your help


Anyway. Writing a conformance checker is a tough job and sometimes we introduce bugs in this kind of software as well. Therefore, please have a look at the code of checkit_tiff, test it and send us bug reports if you find any bugs.
The code can be found on https://github.com/SLUB-digitalpreservation/checkit_tiff.

Here are some open questions about ICC profiles that we have encountered:


  • We found some TIFFs which reported ICC version 4.2.0, but on http://www.color.org we only found versions 4.3.0 and 2.4.0. Could you help us to find out the differences in the headers for the different versions?



  • The meaning of the field "preferred CMM type" is unclear. We assume that the list of allowed strings is part of the document http://www.color.org/registry/signature/TagRegistry-2016-05.pdf. But we have also found a TIFF where the string 'Lino' is set for this ICC header field. Are we interpreting the document in a wrong way, or has the tag been set to an incorrect value?


Montag, 2. Mai 2016

Problemfälle TIFF und Wünsche an TI-A Initiative

Problemfälle TIFF


Auf der Tagung "Archivierung von Unterlagen aus digitalen Systemen" (AUdS), die diesmal an der FH Potsdam stattfand, wurde ich gebeten einen Vortrag zu den bisher in meiner Arbeit gefundenen, problematischen TIFFs zu halten.

Die Folien sind mittlerweile beim Staatsarchiv St. Gallen zu finden (eigentlich sollte an der FH Potsdam auch eine Vortragsaufzeichnung verfügbar sein, konnte ich aber leider noch nicht finden):

http://www.staatsarchiv.sg.ch/home/auds/20/_jcr_content/Par/downloadlist_1/DownloadListPar/download_3.ocFile/ROMEYKE_Folien_AUdS_2016.pdf 

Ich verzichte hier auf eine nochmalige Auflistung aller Problemfälle und verweise auf obige Folien. Dennoch möchte ich auf ein paar Probleme eingehen:

Die meisten Probleme waren auf fehlerhafte Softwareimplementierungen zurückzuführen. Insbesondere das Tag DateTime (306) war eine Quell stetiger Freude.
Laut Spezifikation soll dort ein String der Form YYYY:MM:DD hh:mm:ss\0
stehen. Stattdessen wurde localtime() verwendet, das Datum in dt. Angabe geschrieben oder falsche Trennzeichen benutzt.

Ein anderes Problem mit TIFF sind manchmal vorhandene, sich widersprechende Informationen. Ein Problem bei der Farbkodierung ist in den Folien genannt. Ein anderes besteht in den privaten TIFF-Tags für EXIF-- und ICC-Daten.

Zwar steht in der Spezifikation, daß der Bereich der privaten Tags im Zweifel nicht ausgewertet werden solle, in der  Praxis ist dies aber oft nicht gelöst.So hatte zB. Gimp (aber auch andere Programme, wie Photoshop) ein TIFF stets im tiefsten Schwarz angezeigt. Ursache war ein verkorkstes ICC-Profil, wurde dies gelöscht, wurde der Bildinhalt sichtbar.

Ausblick in Bezug auf die TI-A Initiative


Seit über einem Jahr sind die Macher des im Rahmen von Preforma von der EU geförderten TIFF-Validators "DPFManager" unterwegs und mobilisieren für eine Archiv-TIFF Spezifikation. Unter http://www.ti-a.org kann man sich an der Diskussion beteiligen. Ich hätte mir einen etwas offeneren Beteiligungsprozess gewünscht, das ist aber eine andere Baustelle.

Da im Rahmen der TI-A Initiative mit ein paar Unzulänglichkeiten von TIFF aufgeräumt werden soll, würde ich mir ff. Punkte wünschen, die beibehalten bzw. beachtet werden sollten:

  1. Die Reihenfolge der Tags, als auch die Offsets an gerade Adressen tragen erheblich zur Robustheit von TIFF bei. Diese Eigenschaften sollten nicht, wie von einigen Beitragenden vorgeschlagen, aufgeweicht werden. Im Gegenteil, diese "Einschränkungen" ermöglichen es, durch Bitfehler zerstörte TIFFs leichter zu reparieren.
  2. Es muss ausgeschlossen sein, daß PhotometricInterpretation (262) auf 0 oder 1 gesetzt ist und das Tag Colormap (320) vorhanden ist. Ev. sollte über eine Vorrangsregelung bei Widersprüchen nachgedacht werden.
  3. Ein weiterer Punkt, der vor allem in sogenannten Wang-TIFFs auftrat sollte klar in Spezifikation geklärt sein: Bisher ist es so, daß es zu jedem in einem IFD vorkommenden Tag ua. ein count-Feld gibt, welches die Anzahl der Werte des entsprechenden Typs des Tags bestimmt. Bei Wang-TIFFs existierten Tags, aber das count-Feld wurde auf 0 gesetzt. Ich würde mir wünschen, daß hier die Regelung greift, wenn Tag vorhanden, dann count > 0.

Als Vorschlag für die privaten Tags hätte ich noch, daß bei der Vergabe von privaten Tags ab zwei zusammengehörenden Arten diese nur noch über ein zugehöriges privates IFD-Tag referenziert werden dürfen. Es ist eine Unsitte, daß in TIFFs private Tags zB. DateTimeOriginal (36867) von Exif im IFD0 direkt referenziert werden. Zum einen macht dies die Extraktion und Validierung aufwendiger, zum anderen verkleinert dies den Adressraum der für private Tags genutzt werden kann. Wenn Exif-Daten ausschliesslich über das Exif-IFD (34665) referenziert wird, ist das sauberer.

Als letzten Wunsch erbitte ich mir, daß (mit Zucker drauf), keine Datenkompression erlaubt wird. Andernfalls sollten wir uns lieber mehr Zeit nehmen und dann TI-A so entwickeln, daß es wie FFV1 (Version 3) Mechanismen mitbringt, die Kompression und Robustheit gleichermaßen erlauben (zB. crc32 gesicherte Slices und Header).

Das waren meine 2¢   ;)

PS.: Wer mithelfen mag, den von uns entwickelten freien TIFF Validator "checkit_tiff" zu verbessern, hier der Link: https://github.com/SLUB-digitalpreservation/checkit_tiff

Montag, 20. Juli 2015

Konfigurierbarer TIFF-Validator in Arbeit…

Die bestehenden TIFF - Validatoren/Extraktoren, wie JHove und Co. sind zwar ganz nett, allerdings ist es schwierig unsere Policy abzufragen, sprich, welche Tags mit welchen Werten erlauben wir, welche sind Pflicht.

Dies war die Geburtsstunde für einen konfigurierbaren Validator. Die Regeln werden in einer einfachen Abfragesprache formuliert, die der Validator übersetzt und danach das TIFF entsprechend auswertet.

Es liegt noch etliche Arbeit vor uns, und einiges an Funktionalität fehlt noch. Dennoch möchten wir Euch auf das Tool hinweisen, damit ihr uns vlt. schon frühzeitig Rückmeldungen geben könnt.

Den Quellcode gibt es hier: https://github.com/SLUB-digitalpreservation/fixit_tiff/tree/master/checkit, der Code steht unter der gleichen Lizenz, wie der der LibTIFF (sh. http://www.libtiff.org/)

Hier ein Beispiel für eine einfache Abfrage:

# tag; required; values
#
# works as whitelist
# * tag: any tag number in TIFF
# * required: mandatory | optional | depends( $tag.$value ) 
# * values: range($start, $end) | logical_or( $a, …) | only($a) |any

# This defines a sample config for baseline tiffs
# Remember, because it works as whitelist for each required tag we need an
# entry here

#####
# Required Baseline Tags
#####

# 256 0100 ImageWidth The number of columns in the image, i.e., the number of pixels per row.
256; mandatory; range(1, 4294967295)

# 257 0101 ImageLength The number of rows of pixels in the image.
257; mandatory; range(1, 4294967295)

# 258 0102 BitsPerSample Number of bits per component.
##########################258; mandatory; logical_or(8,16)
# Bitonal is optional, grey & RGB is mandatory. If 262 AND 258 exist, then the values need to be in the specified range.
258; depends(262.2); only(8,8,8)
258; depends(258.any); logical_or(4, 8)

# 259 0103 Compression Compression scheme used on the image data 
### (1 means no compression)
259; mandatory; only(1)

# 262 0106 PhotometricInterpretation The color space of the image data.
### 2 means RGB, 0 and 1 means bilevel or grayscale, 0 is unusual, 3 is Palette Color (FORBIDDEN), 4 is Transparency Mask (FORBIDDEN)
262; mandatory; range(0, 2)

# 273 0111 StripOffsets For each strip, the byte offset of that strip.
273; mandatory; any

# 277 0115 SamplesPerPixel The number of components per pixel.
### if RGB then 3 else 1
### Even though Baseline TIFF allows for SamplesPerPixel>3, we do NOT allow this for long term archival.
277; depends(262.2); only(3)
277; depends(262.1); only(1)
277; depends(262.0); only(1)

# 278 0116 RowsPerStrip The number of rows per strip.
278; mandatory; range(1, 4294967295)

# 279 0117 StripByteCounts For each strip, the number of bytes in the strip after compression.
279; mandatory; range(1, 4294967295)

# 282 011A XResolution The number of pixels per ResolutionUnit in the ImageWidth direction.
282; mandatory; range(300, 1200)

# 283 011B YResolution The number of pixels per ResolutionUnit in the ImageLength direction.
283; mandatory; range(300, 1200)

# 296 0128 ResolutionUnit The unit of measurement for XResolution and YResolution. 1 = No absolute unit of measurement. 2 = Inch. 3 = Centimeter. Default: 2
296; mandatory; only(2)