2016-10-08 16 views
5

Trong câu trả lời cho câu hỏi này: c++ decode CCITT encoded images in pdfsCó thể sử dụng libtiff để giải mã dữ liệu được mã hóa CCITT khi độ dài không được biết?

Điều này được chỉ ra rằng libtiff có thể được sử dụng để giải mã hình ảnh được mã hóa CCITT. Tất nhiên, chúng ta phải thêm một tiêu đề TIFF để làm cho luồng CCITT thành một tệp TIFF hợp lệ.

Tuy nhiên, một số hình ảnh trong tệp PDF là hình ảnh nội dòng và độ dài của chúng không được đưa ra, mặc dù chiều rộng, chiều cao và chiều sâu bit được đưa ra. Chương trình đọc PDF dự kiến ​​sẽ giải mã dòng CCITT, đọc (chiều rộng * chiều cao * chiều sâu) bit của dữ liệu được giải mã, và bất cứ nơi nào sau khi dữ liệu được đọc, đó là phần cuối của hình ảnh nội tuyến. Sau đó, nó nên đi đến lệnh đánh dấu trang tiếp theo, v.v.

Điều này đặt ra sự cố. Thư mục tệp hình ảnh TIFF phải chỉ định số byte có trong mỗi dải dữ liệu hình ảnh, nhưng chúng tôi sẽ không biết có bao nhiêu byte dữ liệu được mã hóa thực sự thuộc về hình ảnh cho đến khi chúng tôi giải mã nó. giải mã hình ảnh mà không sử dụng libtiff ...

Có cách nào để sử dụng libtiff tại đây hay chúng ta cần mã bộ lọc CCITT tùy chỉnh?

+1

Tại sao bạn không thể sử dụng thuộc tính 'Chiều dài' của luồng? (['Độ dài' là thuộc tính bắt buộc đối với luồng] (http://www.printmyfolders.com/understanding-pdf), nó phải luôn có mặt.) – Phillip

+1

Đăng tệp mẫu để chúng tôi có thể xem bạn đang làm việc gì với. – BitBank

+0

@Phillip Không dành cho các đối tượng hình ảnh nội tuyến, xuất hiện trực tiếp bên trong mô tả trang. – Brian

Trả lời

4

Nói đúng cách (Có thể sử dụng libtiff ...?), . Nó liên quan đến một số hack, nhưng không quá nhiều.

Sự thật: dữ liệu sẽ bao gồm một dải, vì không có bất kỳ thông tin bù đắp nào, do đó, chênh lệch duy nhất của chúng tôi bằng 0. Chúng tôi chỉ cần đọc dải đó.

Sự thật: dữ liệu này là nén của ma trận điểm ảnh sâu 1 bit W * H.

Bước 1: ước tính độ dài tối đa có thể có của luồng nén. Điều này xuất hiện vào khoảng 15% W * H, tức là với W = 1000 và H = 1000 bạn nhận được 150000 byte. Giá trị này sẽ luôn là nhiều hơn so với giá trị thực tế. Nếu chúng tôi có ước tính tốt hơn nhờ có vị trí thẻ hình ảnh cuối EI thích hợp, điều đó thậm chí còn tốt hơn nhưng không cần thiết.

Bước 2: tạo tệp TIF "ảo". Điều này sẽ được tạo thành từ tiêu đề của biểu mẫu 49 49 2a 00 AA BB CC DD, trong đó 0xDDCCBBAA là chiều dài ước tính cộng 8; tiếp theo là luồng dữ liệu ước tính của chúng tôi; tiếp theo là một thư mục TIFF.

Bước 3: thư mục TIFF sẽ luôn có cùng cấu trúc; một số giá trị trong đó là bù trừ và phụ thuộc trivially từ vị trí IFD 0xDDCCBBAA. Trích dẫn từ thông số kỹ thuật TIFF6 (lưu ý rằng thứ tự byte được đảo ngược - Motorola, không 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” 

Ở phía trên, 0xDDCCBBAA thực sự là 0014 và tất cả các offsets khác làm theo.

Tôi đã thực hiện một số thử nghiệm bằng một hình ảnh TIFFG4 dải đơn mà tôi đã tạo bằng định dạng CCITT 1Một hình ảnh và định dạng 1Magick và tiffcp '. Tiêu đề có hơi khác (tôi không thấy thẻ Phần mềm và Thẻ ngày giờ mà thông số nói nên có ở đó). Nếu không nó sẽ kiểm tra.

Hiện tại, chúng tôi có một ảnh bị hư hỏng TIFF với một dải quá dài và nó nằm trong bộ nhớ.

Sử dụng TIFFClientOpen, chúng tôi có thể access it as if it was a disk image.

Cố gắng đọc các dải đầu tiên bây giờ sẽ dẫn đến một lỗi và hủy chương trình:

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

Bằng cách sử dụng TIFFSetErrorHandlerTIFFSetErrorHandlerExt chúng tôi thiết lập chính mình để ngăn chặn lỗi này, và phân tích nó, qua đó khôi phục 143151 thông tin, thay vì hủy bỏ.

Chúng ta cần phải cung cấp các callbacks để TIFFClientOpen, nhưng tất cả họ đều rất dễ dàng:

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 

Việc xử lý thực sự là vụng về và phức tạp, nhưng đối với tính khả thi, nó thể được thực hiện.

Tôi đã chạy thử nghiệm bằng ngôn ngữ C, trích xuất thủ công luồng CCITT từ một tệp BI/ID/EI PDF nội tuyến tôi tìm thấy trực tuyến và đọc nó như mô tả ở trên.

Nếu tôi có cách chắc chắn để xác định EI chính xác - tôi đã nạo vét a message by Tilman Hausherr giải thích một hack để nhận ra các nhà khai thác PDF hợp lệ theo EI để làm như vậy. nhiều phương pháp tốt hơn - tôi luôn có thể ước tính độ lệch chính xác và trực tiếp tạo ra một tệp TIFF chính xác và có thể đọc được từ tệp PDF mà không hề liên quan đến libtiff.

Các vấn đề liên quan