iOS Objective-C - 渲染JBIG2图像格式

时间:2014-01-06 09:39:12

标签: ios objective-c jbig2

自PDF规范1.4以来,PDF格式支持JBIG2图像。因此,所有PDF阅读器应用程序都可以读取JBIG2图像。我可以确认包含JBIG2图像的PDF在iPhone和iPhone上正确呈现ipad公司

我想要做的是从Objective-C渲染(或转换为PNG)JBIG2图像,而不必在PDF中。 JBIG2图像以普通图像对象的形式存储在PDF文件中,采用自己的JBIG2原始格式(不进行任何类型的转换),因此很明显iOS中的某处有一个JBIG2解码器库,否则无法对其进行解码。 / p>

那么如何在iOS上渲染JBIG2图像而不将该图像放在PDF包装器中呢?它与PDF图像对象中存在的数据完全相同,因此它将使用完全相同的解码器。

在JBIG2图像周围添加一个小小的PDF包装器只是为了能够将其渲染出来,这将浪费大量资源。这个JBIG2解码器必须存在于iOS中的某个地方,那么如何使用它呢?

更新

如果JBIG2解码器在iOS本身不可用,则表示PDF阅读器正在使用自己的...在这种情况下,应该可以将解码器从开源PDF阅读器中删除。

以下是包含JBIG2和原始JIBG2的示例PDF:http://www.filedropper.com/jbig2samples

1 个答案:

答案 0 :(得分:9)

首先,你说本机iOS(和Mac OS)框架支持嵌入在PDF数据流中的JBIG2图像 - 实际上它是Core Graphics的一部分。

在iOS中读取图片的公共API是ImageIO。它通过添加通用图像文件读写功能扩展了Core Graphics。它创建CGImage个对象,可以在CGContext中使用它们进行解压缩和渲染。可悲的是,它无法读取jbig2图像文件。

另一方面,可以呈现包含JBIG2图像的PDF 。这似乎可以通过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

在运行Instruments时在预览中显示PDF,显示实现JBIG2支持的库:

Instruments analyzing Preview.app

这是实际的图书馆:

> 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上。

这给我们留下了一个如何使用iOS原生JBIG2解压缩的选项:你必须将JBIG2文件包装成一个最小的PDF。我不认为运行时开销是相关的。

添加以说明评论:用于从PDF创建图像的代码。这假定PDF包含一个页面,其中包含72 dpi中无边界的JBIG2图像。

// 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];