iOS Objective-C - Визуализация формата изображения JBIG2
Изображения JBIG2 поддерживаются в форматах PDF с момента спецификации PDF 1.4. Поэтому все приложения для чтения PDF могут читать изображения JBIG2. Я могу подтвердить, что PDF, содержащий изображения JBIG2, правильно отображается на iPhone и iPad.
Я хочу сделать (или преобразовать в PNG) изображение JBIG2 из Objective-C, не помещая его в PDF-файл. Изображения JBIG2 хранятся в файлах PDF точно так же, как обычный объект изображения, в своем собственном необработанном формате JBIG2 (без преобразования любого вида), поэтому очевидно, что где-то в iOS есть библиотека декодера JBIG2, иначе их невозможно было бы декодировать.
Итак, как я могу отобразить изображение JBIG2 на iOS, если оно не находится в оболочке PDF? Это точно те же данные, которые существуют внутри этого объекта изображения PDF, поэтому он будет использовать точно такой же декодер.
Было бы огромной тратой ресурсов на то, чтобы добавить крошечную маленькую PDF-оболочку вокруг изображения JBIG2 просто для того, чтобы можно было ее визуализировать. Этот декодер JBIG2 должен существовать где-то уже в iOS, так как его использовать?
ОБНОВИТЬ
Если декодер JBIG2 изначально недоступен в iOS, это означает, что программы чтения PDF используют свои собственные... в этом случае должна быть возможность вырвать декодер из программы чтения PDF с открытым исходным кодом.
Вот пример PDF, содержащий JBIG2s и необработанные JIBG2s: http://www.filedropper.com/jbig2samples
1 ответ
Прежде всего, вы правы в том, что встроенные платформы iOS (и Mac OS) поддерживают изображения JBIG2, встроенные в потоки данных PDF - фактически это часть Core Graphics.
Общедоступным API для чтения изображений в iOS является ImageIO. Он расширяет Core Graphics, добавляя общие функции чтения и записи файлов изображений. Это создает CGImage
объекты, которые могут быть использованы в CGContext
s для распаковки и рендеринга. К сожалению, он не может читать файлы изображений jbig2.
С другой стороны, PDF, содержащий изображения JBIG2, может быть отображен. Это кажется возможным благодаря Core Graphics, добавляющей пользовательские фильтры в CGImage, которые используются только при рендеринге PDF:
> cd /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/System/Library/Frameworks
> nm -arch armv7 ./CoreGraphics.framework/CoreGraphics | grep jbig2
000f4f6c t _jbig2_create_state
00081e68 t _jbig2_filter_finalize
00081e44 t _jbig2_filter_refill
00081e24 t _jbig2_filter_rewind
000f500c t _jbig2_read_bytes
000f4fc0 t _jbig2_release_state
000f5064 t _jbig2_rewind
0013b78c b _jbig2_vtable
00081d9c t _pdf_source_create_jbig2_filter
001247f0 s _pdf_source_create_jbig2_filter.callbacks
Отображение PDF в Preview во время работы Instruments показывает библиотеку, в которой реализована поддержка JBIG2:
Вот фактическая библиотека:
> nm -arch armv7 ./CoreGraphics.framework/Resources/libJBIG2.dylib | c++filt
...
00001f68 unsigned short JBIG2Bitmap::JBIG2Bitmap(unsigned int, JBIG2Bitmap*)
00007adc unsigned short JBIG2Stream::readGenericBitmap(int, int, int, int, int, int, JBIG2Bitmap*, int*, int*, int)
...
Эта библиотека, кажется, включает в себя некоторый код xpdf-3, но в основном это частная реализация Apple. Для этой библиотеки нет заголовков, поэтому ее следует рассматривать как частную, особенно в iOS.
В результате у нас остается только один вариант использования собственной декомпрессии JBIG2 для iOS: вы должны обернуть файлы JBIG2 в минимальный PDF. Я не думаю, что накладные расходы актуальны.
Дополнение для иллюстрации комментария: Код для создания изображения из PDF. Это предполагает, что PDF состоит из одной страницы, которая содержит изображение JBIG2 без полей в 72 dpi.
// create PDF document
CGPDFDocumentRef document = CGPDFDocumentCreateWithURL((__bridge CFURLRef)[NSURL fileURLWithPath:path]);
// get the first page
CGPDFPageRef page = CGPDFDocumentGetPage(document, 1);
// create a bitmap context
CGSize size = CGPDFPageGetBoxRect(page, kCGPDFMediaBox).size;
UIGraphicsBeginImageContextWithOptions(size, YES, 1);
// flip the context
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0, mediaBox.size.height);
CGContextScaleCTM(UIGraphicsGetCurrentContext(), 1, -1);
// draw the page into the bitmap context
CGContextDrawPDFPage(UIGraphicsGetCurrentContext(), page);
CGPDFDocumentRelease(document);
// get the image from the context
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// save image as PNG file
[UIImagePNGRepresentation(image) writeToFile:somePath atomically:YES];