自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
答案 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支持的库:
这是实际的图书馆:
> 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];