【发布时间】:2015-05-07 08:09:45
【问题描述】:
我在使用 iOS 上的 Core Graphics PDF 功能将某些 PDF 渲染为图像时遇到问题。具体来说,我使用的是这个库提供的UIImage+PDF 类别:https://github.com/mindbrix/UIImage-PDF。相关方法有:
来自“UIImage+PDF.m”
+(UIImage *)imageWithPDFData:(NSData *)data atSize:(CGSize)size atPage:(NSUInteger)page
{
if(data == nil || CGSizeEqualToSize(size, CGSizeZero) || page == 0)
return nil;
UIImage *pdfImage = nil;
CGFloat screenScale = [self screenScale];
NSString *cacheFilename = [ self cacheFilenameForData:data atSize:size atScaleFactor:[self screenScale] atPage:page ];
if(_shouldCacheOnDisk && [[ NSFileManager defaultManager ] fileExistsAtPath:cacheFilename ])
{
pdfImage = [ UIImage imageWithCGImage:[[ UIImage imageWithContentsOfFile:cacheFilename ] CGImage ] scale:[self screenScale] orientation:UIImageOrientationUp ];
}
else
{
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(NULL, size.width * screenScale, size.height * screenScale, 8, 0, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst);
CGContextScaleCTM(ctx, screenScale, screenScale);
[PDFView renderIntoContext:ctx url:nil data:data size:size page:page];
CGImageRef image = CGBitmapContextCreateImage(ctx);
pdfImage = [[UIImage alloc] initWithCGImage:image scale:screenScale orientation:UIImageOrientationUp];
CGImageRelease(image);
CGContextRelease(ctx);
CGColorSpaceRelease(colorSpace);
if(_shouldCacheOnDisk && cacheFilename)
{
[ UIImagePNGRepresentation( pdfImage ) writeToFile:cacheFilename atomically:NO ];
}
}
return pdfImage;
}
并来自“PDFView.m”
+(void)renderIntoContext:(CGContextRef)ctx url:(NSURL *)resourceURL data:(NSData *)resourceData size:(CGSize)size page:(NSUInteger)page
{
if ( resourceURL || resourceData )
{
/*
* Reference: http://www.cocoanetics.com/2010/06/rendering-pdf-is-easier-than-you-thought/
*/
CGPDFDocumentRef pdf;
if( resourceURL )
{
pdf = CGPDFDocumentCreateWithURL( (__bridge CFURLRef) resourceURL );
}
else
{
CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)resourceData);
pdf = CGPDFDocumentCreateWithProvider(provider);
CGDataProviderRelease(provider);
}
CGPDFPageRef page1 = CGPDFDocumentGetPage( pdf, page );
CGRect mediaRect = CGPDFPageGetBoxRect( page1, kCGPDFCropBox );
CGContextScaleCTM( ctx, size.width / mediaRect.size.width, size.height / mediaRect.size.height );
CGContextTranslateCTM( ctx, -mediaRect.origin.x, -mediaRect.origin.y );
CGContextDrawPDFPage( ctx, page1 );
CGPDFDocumentRelease( pdf );
}
}
我得到的结果好坏参半。许多 PDF 似乎可以正确呈现。但是,有些存在一些严重的色彩准确性问题。下面是原文的一个例子:
还有糟糕的渲染:
如您所见,问题主要在于 RGB 中的绿色通道(CMYK 中的青色?)。所以我的假设是,这是一个色彩空间/色彩配置文件问题,呈现不佳的 PDF。一些搜索使我遇到了类似的问题:pdf images color space trouble ios。作者指出,他将问题归咎于 PDF 中缺少颜色配置文件,他的解决方案是要求他的设计师嵌入颜色配置文件。我不知道如何验证这是否是我的问题,并且该解决方案对我来说可能不可行,因为我无权访问原始文件或原始设计者。
如果有人可以就我如何在代码中处理这些 PDF 以纠正颜色问题(例如添加颜色配置文件、使用不同的颜色空间等)或我可以如何预- 在 iOS 设备上渲染之前在计算机上处理 PDF,我将不胜感激!
【问题讨论】:
-
我们确实需要查看示例 PDF 文件以确定问题所在。在我看来,它“最有可能”是由 CMYK->RGB 转换引起的,并且不太可能通过添加 OutputIntent 颜色配置文件来解决。尽管将颜色空间转换为 ICCBased 可能会起作用。不知道文件中的内容很难说。
-
感谢@KenS 的反馈。如果它有帮助,我在这里放了一个示例 PDF:dl.dropboxusercontent.com/u/18408411/sample.pdf
-
快速看了一下,“看起来”颜色都是用 CMYK 指定的,包括具有 CMYK 色调变换的 Separatio9n 颜色。转换 CMYK->RGB 的指定方法(在 PDF 参考中)非常粗糙,我相信这就是导致您的问题的原因。你没有说你要渲染成什么图像格式,如果你可以渲染成 CMYK 图像,那应该没问题。否则,如果您需要渲染为 RGB,您要么必须获得具有 RGB 颜色的 PDF,要么使用更好的东西来进行渲染。你考虑过 Ghostscript 还是 MuPDF(还有其他解决方案)
-
非常感谢@KenS。我使用的 UIImage+PDF 库使用 RGB 颜色空间呈现为 CGBitmapContext(内存位图格式)。如果我错了,请纠正我,但我的印象是,这是在 iOS 上使用 CoreGraphics 呈现 PDF 的唯一可行选项。我还没有查看其他库来进行渲染,因为这似乎会使过程变得非常复杂,但就像你一样,它可能是我唯一的选择之一。
-
我不想这么说,但我对 iOS 一无所知 :-( 如果它接受除 RGB 以外的任何东西,我会感到惊讶 :-) 如果您要接受任意格式的 PDF 文件,并且颜色保真度对您很重要,那么我认为您将不得不使用不同的库。
标签: ios objective-c pdf colors core-graphics