2016-10-08 1 views
5

В ответах на этот вопрос: c++ decode CCITT encoded images in pdfsМожно ли использовать libtiff для декодирования данных, кодированных CCITT, когда длина неизвестна?

Указывается, что libtiff может использоваться для декодирования изображений, закодированных CCITT. Конечно, мы должны добавить заголовок TIFF, чтобы поток CCITT в действительный файл TIFF.

Однако некоторые изображения в файлах PDF являются встроенными изображениями, а их длины не заданы, хотя указаны их ширина, высота и глубина бит. Ожидается, что программа, читающая PDF, будет декодировать поток CCITT, читать (ширину * высоту * глубина) бит декодированных данных, и где бы он ни находился после того, как данные были прочитаны, это конец встроенного изображения. Затем он должен перейти к следующей команде маркировки следующей страницы и т. Д.

Это создает проблему. Каталог файлов изображений TIFF должен указывать, сколько байтов содержится в каждой полосе данных изображения, но мы не будем знать, сколько байтов кодированных данных действительно принадлежит изображению, пока мы его не расшифровали, но мы не можем декодировать изображение без использования libtiff ...

Есть ли способ использовать libtiff здесь или нам нужен специальный код фильтра CCITT?

+1

Почему вы не можете использовать свойство 'Length' в потоке? (['Length' является обязательным свойством для потока] (http://www.printmyfolders.com/understanding-pdf), он всегда должен присутствовать.) – Phillip

+1

Опубликовать образец файла, чтобы мы могли видеть, что вы работаете с. – BitBank

+0

@Phillip Не для встроенных объектов изображения, которые отображаются непосредственно в описании страницы. – Brian

ответ

4

Строго говоря (Можно ли использовать LibTIFF? ...), да. Это связано с некоторыми взломами, но не слишком много.

Факт: данные будут состоять из одной полосы, так как нет никакой информации о смещении, поэтому наше единственное смещение равно нулю. Нам просто нужно прочитать полосу.

Фактически: эти данные представляют собой сжатие матричной матрицы глубин W * H 1 бит.

Шаг 1: оцените максимально возможную длину сжатого потока. Это составляет около 15% от W * H, т. Е. С W = 1000 и H = 1000 вы получаете 150000 байт. Это значение всегда будет больше, чем фактическое значение. Если мы получим более точную оценку благодаря расположению правильного тега конечного изображения EI, это еще лучше, но не обязательно.

Шаг 2: постройте «виртуальный» файл TIF. Это будет состоять из заголовка формы 49 49 2a 00 AA BB CC DD, где 0xDDCCBBAA - расчетная длина плюс 8; за которым следует наш оценочный поток данных; за которым следует каталог TIFF.

Шаг 3: каталог TIFF всегда будет иметь одинаковую структуру; некоторые значения в нем являются смещениями и тривиально зависят от позиции IFD 0xDDCCBBAA. Цитирование из TIFF6 спецификации (обратите внимание, что порядок байт обратная - Motorola, не 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” 

В вышеприведенном 0xDDCCBBAA на самом деле 0014 и все остальные смещения следуют.

Я провел несколько тестов с использованием однополосного изображения TIFFG4, которое я создал с помощью ImageMagick и tiffcp 'ed в 1-полосный формат CCITT. Заголовок там немного отличается (я не вижу теги Software и Datetime, которые, по словам спецификации, должны быть там). В противном случае он проверяет.

У нас теперь есть поврежденный Изображение TIFF с одной накладной полосой, и оно находится в памяти.

Использование TIFFClientOpen, мы можем access it as if it was a disk image.

Попытка прочитать первую полосу теперь будет приводить к ошибке и программа закрывается:

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

Используя TIFFSetErrorHandler и TIFFSetErrorHandlerExt мы создали сами, чтобы перехватить эту ошибку, и разобрать его, таким образом, восстанавливая 143151 информации, а не прерывания.

Мы должны поставить обратные вызовы TIFFClientOpen, но все они очень легко:

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 

обработки действительно неловко и запутанная, но и для возможности, он может быть сделан.

Я провел тесты на языке C, извлекая вручную поток CCITT из встроенного образа BI/ID/EI PDF, который я нашел в Интернете, и прочитал его, как описано выше.

Если у меня был верный способ определения правильного EI - я выкопал a message by Tilman Hausherr, объяснив взломам, чтобы признать действительные операторы PDF, следуя за EI, чтобы сделать это, что заставляет меня думать, что, вероятно, нет многие лучшие методы - я всегда мог оценить правильное смещение и напрямую создавать корректный и читаемый файл TIFF из PDF, даже не затрагивая libtiff.

Смежные вопросы