iPad 上的 PDF 渲染问题
我有两个与在 iPad/iPhone 上处理 PDF 渲染相关的问题。
首先
在 iPad 上使用 CGPDF 函数渲染 PDF 页面时,我遇到了一些奇怪的问题。奇怪的是,因为在 iPhone 上一切都工作得很好,但在 iPad 上我收到了很多与 PDF 相关的错误消息,即如下所示
invalid stream length 9785; endstream not found.
FlateDecode: decoding error: incorrect header check.
invalid function: failed to read 765 bytes.
stack underflow: popping past mark.
missing or invalid arguments for color operator.
FlateDecode: decoding error: incorrect header check.
FlateDecode: decoding error.
<Error>: FT_Open_Face failed: error 2.
<Error>: FT_Open_Face failed: error 85.
encountered unexpected object type: 7.
missing or invalid object number.
invalid image `ColorSpace' value.
unexpected symbol `obj' while reading object.
invalid descendant font for Type0 font.
font `F28' not found in document.
<Error>: FT_Outline_Decompose failed: error 20.
font `R222' not found in document.
......以及许多其他消息。我知道这可能是 PDF 结构错误的问题,但我不明白为什么我只能在 iPad 上看到所有这些错误,而在 iPhone 上,与 iPad 相比,这些错误的数量很少,而且在大多数情况下,尽管页面显示正确,但报告的错误数量,但 iPad 上的情况并非如此。
iPhoneOS 3.2 和 3.1/4.0 中的 Quartz 实现有什么区别吗?是否有一些关于 iPhone/iPad 上可读的 PDF 格式的指南?
第二:
另一个问题是为不同的页面大小创建位图上下文。我需要为纵向和横向渲染相同的 PDF 页面。但是,虽然它适用于纵向(均在 iPhone 上),但不适用于 iPad 上的横向,并引发以下错误:
CGBitmapContextCreate: unsupported parameter combination: 8 integer bits/component; 32 bits/pixel; 3-component colorspace; kCGImageAlphaPremultipliedLast; 4095 bytes/row.
用于创建上下文的代码如下所示:
/// Calculate memory block size needed
int bytesPerRow = (int)((int)_pageSize.width * 4);
int dataSize = (int)(bytesPerRow * _pageSize.height);
/// Allocate memory; As noted in docs, on iOS 4 it can be NULL, but as mentioned
/// below: Do not pass NULL if you are running on earlier operating systems.
/// So don't pass NULL...
void *bitmapData = malloc(dataSize);
if(!bitmapData) {
/// Hm, out of memory?
return NULL;
}
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(bitmapData,
_pageSize.width,
_pageSize.height,
8, /* bits per component*/
bytesPerRow, /* bytes per row */
colorSpace,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
if(!context) {
/// Something is really wrong!
free(bitmapData);
bitmapData = NULL;
return NULL;
}
CGContextClipToRect(context, CGRectMake(0, 0, _pageSize.width, _pageSize.height));
/// Ask data source to render contents
[_dataSource renderPageAtIndex: pageIndex inContext: context];
/// Get bitmap image from context
CGImageRef image = CGBitmapContextCreateImage(context);
/// Free context AND previously allocated block of data
CGContextRelease(context);
free(bitmapData);
bitmapData = NULL;
/// Finish operation...
正如我所说,它在 iPhone 下工作正常,在 iPad 上适用于纵向iPad,它不适用于 iPad 上的横向。唯一的区别实际上是提供的当前页面大小。然而,这里的页面尺寸并不等于横向模式下的屏幕尺寸(1024x768),而是计算出适合屏幕宽度的尺寸,允许用户垂直滚动以查看完整页面。通常,iPad 上的页面大小为 1024x1403(取决于 PDF 格式)。
我不明白为什么上面的代码不适用于更大的页面大小。
有什么想法吗?谢谢。
I have two questions related to handling PDF rendering on iPad/iPhone.
First
I'm getting some strange issues when rendering PDF page with CGPDF functions on iPad. Strange, because everything works quite fine on iPhone, but on iPad I'm getting lots of error messages related to PDF, i.e. like below
invalid stream length 9785; endstream not found.
FlateDecode: decoding error: incorrect header check.
invalid function: failed to read 765 bytes.
stack underflow: popping past mark.
missing or invalid arguments for color operator.
FlateDecode: decoding error: incorrect header check.
FlateDecode: decoding error.
<Error>: FT_Open_Face failed: error 2.
<Error>: FT_Open_Face failed: error 85.
encountered unexpected object type: 7.
missing or invalid object number.
invalid image `ColorSpace' value.
unexpected symbol `obj' while reading object.
invalid descendant font for Type0 font.
font `F28' not found in document.
<Error>: FT_Outline_Decompose failed: error 20.
font `R222' not found in document.
...and many others. I understand that it's maybe a problem of wrong PDF structure, but I don't understand why I can see all those errors only on iPad while on iPhone there's just a small number of them compared to iPad and in most cases page is displayed correctly despite of reported errors, which, again, is not true on iPad.
Is there some difference in Quartz implementations in iPhoneOS 3.2 and 3.1/4.0? And are there some guidelines about PDF format readable on iPhone/iPad?
Second:
Another issue is with creating bitmap context for different page sizes. I need to render the same PDF page for portrait as well as landscape orientations. But while it works for portrait (both on iPhone), it does not for landscape on iPad, throwing following error:
CGBitmapContextCreate: unsupported parameter combination: 8 integer bits/component; 32 bits/pixel; 3-component colorspace; kCGImageAlphaPremultipliedLast; 4095 bytes/row.
The code used to create the context is like following:
/// Calculate memory block size needed
int bytesPerRow = (int)((int)_pageSize.width * 4);
int dataSize = (int)(bytesPerRow * _pageSize.height);
/// Allocate memory; As noted in docs, on iOS 4 it can be NULL, but as mentioned
/// below: Do not pass NULL if you are running on earlier operating systems.
/// So don't pass NULL...
void *bitmapData = malloc(dataSize);
if(!bitmapData) {
/// Hm, out of memory?
return NULL;
}
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(bitmapData,
_pageSize.width,
_pageSize.height,
8, /* bits per component*/
bytesPerRow, /* bytes per row */
colorSpace,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
if(!context) {
/// Something is really wrong!
free(bitmapData);
bitmapData = NULL;
return NULL;
}
CGContextClipToRect(context, CGRectMake(0, 0, _pageSize.width, _pageSize.height));
/// Ask data source to render contents
[_dataSource renderPageAtIndex: pageIndex inContext: context];
/// Get bitmap image from context
CGImageRef image = CGBitmapContextCreateImage(context);
/// Free context AND previously allocated block of data
CGContextRelease(context);
free(bitmapData);
bitmapData = NULL;
/// Finish operation...
As I said, it works fine under iPhone and works for portrait orientation on iPad, it does not for landscape on iPad. The only difference is really the current page size supplied. However, page size here is not equal to screen size in landscape mode (1024x768), but it's size calculated to fit screen width, allowing user to scroll vertically to see complete page. Typically, page size on iPad is 1024x1403 (depends on PDF format).
I don't understand why the code above does not work for bigger page sizes.
Any idea, please? Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
关于第二个问题,我刚刚遇到了类似的问题。事实上,警告表明您在使用 4 字节像素时每行分配 4095 字节,这表明您在相乘之前可能无法正确转换为整数。
对我来说,我能够通过做相当于解决这个
问题
With regards to the second problem, I was just having a similar issue. The fact that the warning indicates that you're allocating 4095 bytes per row when you're using 4 byte pixels indicates that you might not be converting to ints correctly before multiplying.
For me I was able to solve it by doing the equivalent of
to