自 PDF 规范 1.4 起,PDF 就支持 JBIG2 图像。因此所有 PDF 阅读器应用程序都可以读取 JBIG2 图像。我可以确认包含 JBIG2 图像的 PDF 在 iPhone 和 iPad 上正确呈现。
我想做的是渲染(或转换为 PNG)来自 Objective-C 的 JBIG2 图像,而不必将其放在 PDF 中。 JBIG2 图像以其自己的 JBIG2 原始格式(无任何类型的转换)存储在 PDF 文件中,就像普通图像对象一样,因此很明显在 iOS 中某处有一个 JBIG2 解码器库,否则这些无法解码。
那么,如果 JBIG2 图像不在 PDF 包装器中,我该如何在 iOS 上渲染该图像?它与该 PDF 图像对象中存在的数据完全相同,因此它将使用完全相同的解码器。
在 JBIG2 图像周围添加一个很小的 PDF 包装器只是为了能够渲染它,这将是一种巨大的资源浪费。这个JBIG2解码器一定已经存在于iOS的某处,那么如何使用呢?
更新
如果 JBIG2 解码器在 iOS 中不可用,那么这意味着 PDF 阅读器正在使用他们自己的...在这种情况下,应该可以从开源 PDF 阅读器中删除解码器。
这是一个包含 JBIG2 和原始 JIBG2 的示例 PDF:http://www.filedropper.com/jbig2samples
最佳答案
首先,您是对的,原生 iOS(和 Mac OS)框架确实支持嵌入在 PDF 数据流中的 JBIG2 图像——实际上它是 Core Graphics 的一部分。
在 iOS 中读取图像的公共(public) API 是 ImageIO .它通过添加通用图像文件读写功能扩展了 Core Graphics。它创建可在 CGContext
中用于解压缩和渲染的 CGImage
对象。很遗憾,它无法读取 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 的私有(private)实现。这个库没有 header ,因此它被认为是私有(private)的,尤其是在 iOS 上。
关于如何使用 iOS 原生 JBIG2 解压缩,我们只剩下一个选择:您必须将 JBIG2 文件打包成最小的 PDF。我不认为运行时开销是相关的。
Addition 说明注释:从 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];
关于iOS Objective-C - 渲染 JBIG2 图像格式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20946957/