2016-10-08 9 views
5

In den Antworten auf diese Frage: c++ decode CCITT encoded images in pdfsIst es möglich, libtiff zu verwenden, um CCITT-codierte Daten zu dekodieren, wenn die Länge nicht bekannt ist?

Es kann, dass libtiff darauf hingewiesen werden CCITT codierten Bilder zu dekodieren. Natürlich müssen wir einen TIFF-Header voranstellen, damit der CCITT-Stream in eine gültige TIFF-Datei umgewandelt wird.

Einige Bilder in PDF-Dateien sind Inline-Bilder und ihre Längen sind nicht angegeben, obwohl ihre Breite, Höhe und Bittiefe gegeben sind. Es wird erwartet, dass das Programm, das die PDF liest, den CCITT-Strom decodiert, Bits (Breite * Höhe * Tiefe) von decodierten Daten liest und wo auch immer es nach dem Lesen der Daten ist, das ist das Ende des Inline-Bildes. Dann sollte es zum nächsten Seitenmarkierungsbefehl gehen, und so weiter.

Dies wirft ein Problem auf. Ein TIFF-Bilddateiverzeichnis muss angeben, wie viele Bytes es in jedem Streifen der Bilddaten gibt, aber wir wissen nicht, wie viele Bytes der kodierten Daten tatsächlich zu dem Bild gehören, bis wir es entschlüsselt haben, aber wir können es nicht decodiere das Bild ohne Verwendung von libtiff ...

Gibt es eine Möglichkeit, libtiff hier zu verwenden, oder benötigen wir einen benutzerdefinierten CCITT-Filtercode?

+1

Warum können Sie die Eigenschaft 'Length' des Streams nicht verwenden? ([Länge ist eine obligatorische Eigenschaft für einen Stream] (http://www.printmyfolders.com/understanding-pdf), sollte es immer vorhanden sein.) – Phillip

+1

Posten Sie eine Beispieldatei, damit wir sehen können, was Sie arbeiten mit. – BitBank

+0

@Phillip Nicht für eingebettete Bildobjekte, die direkt in einer Seitenbeschreibung angezeigt werden. – Brian

Antwort

4

Streng genommen (Ist es möglich, libtiff zu verwenden ...?), ja. Es beinhaltet etwas Hacking, aber nicht zu viel.

Fakt: die Daten werden aus einem Streifen bestehen, da es keine Offset-Informationen gibt, so dass unser einziger Offset Null ist. Wir müssen nur den Streifen einlesen.

Fakt: Diese Daten sind die Komprimierung einer W * H 1-Bit tiefen Pixelmatrix.

Schritt 1: Schätzung der maximal möglichen Länge des komprimierten Datenstroms. Dies ergibt ungefähr 15% von W * H, d.h. mit W = 1000 und H = 1000 erhält man 150000 Bytes. Dieser Wert ist immer mehr als der tatsächliche Wert. Wenn wir eine bessere Schätzung haben, weil wir das richtige EI-End-Image-Tag gefunden haben, ist das noch besser, aber nicht notwendig.

Schritt 2: Erstellen Sie eine "virtuelle" TIF-Datei. Dies wird aus einem Header der Form 49 49 2a 00 AA BB CC DD bestehen, wobei 0xDDCCBBAA die geschätzte Länge plus 8 ist; gefolgt von unserem geschätzten Datenstrom; gefolgt von einem TIFF-Verzeichnis.

Schritt 3: Das TIFF-Verzeichnis wird immer die gleiche Struktur haben; einige Werte darin sind Offsets und hängen trivial von der IFD-Position 0xDDCCBBAA ab. Zitiert aus den TIFF6 Spezifikationen (beachten Sie, dass Byte-Reihenfolge umgekehrt wird - Motorola, nicht Intel-Endian):

TIFF 6.0 Specification Final—June 3, 1992       20 

Putting it all together (along with a couple of less-important fields that are discussed 
later), a sample bilevel image file might contain the following fields 

A Sample Bilevel TIFF File 

Offset Description Value 
(hex) (numeric values are expressed in hexadecimal notation) 
Header: 
0000 Byte Order  4D4D 
0002 42    002A 
0004 1st IFD offset 00000014 
IFD: 
0014 Number of Directory Entries 000C 
0016 NewSubfileType    00FE 0004 00000001 00000000 
0022 ImageWidth     0100 0004 00000001 000007D0 
002E ImageLength     0101 0004 00000001 00000BB8 
003A Compression     0103 0003 00000001 8005 0000 
0046 PhotometricInterpretation 0106 0003 00000001 0001 0000 
0052 StripOffsets    0111 0004 000000BC 000000B6(*1) 
005E RowsPerStrip    0116 0004 00000001 00000010 
006A StripByteCounts    0117 0003 000000BC 000003A6(*2) 
0076 XResolution     011A 0005 00000001 00000696(*3) 
0082 YResolution     011B 0005 00000001 0000069E(*4) 
008E Software     0131 0002 0000000E 000006A6(*5) 
009A DateTime     0132 0002 00000014 000006B6(*6) 
00A6 Next IFD offset    00000000 
Values longer than 4 bytes: 
(*1) StripOffsets Offset0  00000008 
(*2) StripByteCounts Count0 
(*3) XResolution 0000012C 00000001 
(*4) YResolution 0000012C 00000001 
(*5) Software “PageMaker 4.0” 
(*6) DateTime “1988:02:18 13:59:59” 

Im obigen 0xDDCCBBAA tatsächlich 0014 ist und alle anderen Offsets folgen.

Ich habe einige Tests mit einem Single-Strip-TIFFG4-Bild, das ich mit ImageMagick erstellt und tiffcp 'ed to 1-strip CCITT-Format gemacht. Der Header dort ist etwas anders (Ich sehe nicht die Software und Datetime Tags, die die Spezifikation sagen sollte dort sein). Sonst überprüft es.

Wir haben jetzt ein beschädigtes TIFF-Bild mit einem überlangen Streifen, und es ist im Speicher.

Mit TIFFClientOpen können wir access it as if it was a disk image.

den ersten Streifen zu lesen Versuch führt nun zu einem Fehler und das Programm Abbruch:

TIFFFillStrip: Read error on strip 0; got 143151 bytes, expected 762826. 

Durch die Verwendung von TIFFSetErrorHandler und TIFFSetErrorHandlerExt wir uns einrichten diesen Fehler abzufangen und analysieren sie, um dadurch die 143151 erholt Information, anstatt abzubrechen.

Wir müssen die Rückrufe TIFFClientOpen, aber sie sind alle sehr einfach liefern:

TIFFReadWriteProc readproc(h, *ptr, n) // copy n bytes from FakeBuffer+pos into ptr, update pos to pos + n, ignore h. 
TIFFReadWriteProc writeproc   // Throw an error. We don't write 
TIFFSeekProc seekproc     // update pos appropriately 
TIFFCloseProc closeproc    // do nothing 
TIFFSizeProc sizeproc     // return total buffer size 
TIFFMapFileProc mapproc    // Set to NULL 
TIFFUnmapFileProc unmapproc   // Set to NULL 

Die Verarbeitung ist in der Tat schwierig und verworren, aber wie für Machbarkeit, es kann erfolgen.

Ich habe Tests in C-Sprache ausgeführt, den CCITT-Stream von Hand aus einem BI/ID/EI-PDF, das ich online gefunden habe, extrahiert und wie oben beschrieben gelesen.

Wenn ich eine sichere Methode zur Identifizierung der richtigen EI hatte - ich habe a message by Tilman Hausherr ausgebaggert, einen Hack zu erklären, gültige PDF-Operatoren zu folgen, die dem EI folgen, um dies zu tun, was mich denken lässt, dass es wahrscheinlich nicht ist viele bessere Methoden - ich konnte immer den korrekten Offset schätzen und direkt aus dem PDF eine korrekte und lesbare TIFF-Datei erzeugen, ohne überhaupt libtiff zu verwenden.

Verwandte Themen