CGPDF - 使用FlateDecode过滤器保存图像

时间:2012-05-01 17:41:47

标签: iphone objective-c c pdf cgpdf

我正在为工作编写PDF解析器,我们正在使用Core Graphics读取所有带回调的数据,然后将其写入Lib Haru,因为我们的客户端需要写出“真实”注释和CG不能这样做。

好吧,我已经到了获取图像的位置(并将它们保存到文件中,以确保我在开始绘制它之前就已经完成了)并且我遇到了一个问题。我从资源字典中获取所有Image XObjects,然后尝试使用此代码保存它们

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];                

NSData *imageFileData = (NSData *)CGPDFStreamCopyData(objectStream, CGPDFDataFormatRaw);

NSString *fileName = [NSString stringWithFormat:@"%@/%s.png", documentsDir, name];
[imageFileData writeToFile:fileName atomically:YES];

其中objectStream使用CGPDFDictionaryGetStream来提取XObject。好吧,当Filter是“DCTDecode”时,它工作正常,但只要Filter是“FlateDecode”,保存的图像就会损坏而不会打开。

我在this post中读到CGPDFStreamCopyData可以使用FlateDecode解码文本(一直到评论中帖子的底部),但CGPDFDataFormats中只有3种数据格式,但它们都不起作用。

我相信我也遇到了使用FlatDecode编码的文本问题。有没有人对如何解码这个有任何建议?当然,CGPDF有一些处理这个的东西,因为它几乎出现在我试图打开的每个pdf中(虽然我无法找到它)。

编辑:我在一些地方读过我可以使用zlib解压缩它,所以我尝试了这个代码,我能够找到关于如何做到这一点:

            NSData* uncompressedImageData;
            if ([imageFileData length] == 0) 
                uncompressedImageData = imageFileData;
            else
            {                
                z_stream strm;
                strm.zalloc = Z_NULL; 
                strm.zfree = Z_NULL; 
                strm.opaque = Z_NULL; 
                strm.total_out = 0; 
                strm.next_in=(Bytef*)[imageFileData bytes]; 
                strm.avail_in = [imageFileData length];

                // Compresssion Levels: // Z_NO_COMPRESSION // Z_BEST_SPEED // Z_BEST_COMPRESSION // Z_DEFAULT_COMPRESSION
                if (deflateInit(&strm, Z_DEFAULT_COMPRESSION) != Z_OK) 
                    uncompressedImageData = nil;

                NSMutableData *compressed = [NSMutableData dataWithLength:16384]; // 16K chuncks for expansion
                do 
                {
                    if (strm.total_out >= [compressed length]) 
                        [compressed increaseLengthBy: 16384];

                    strm.next_out = [compressed mutableBytes] + strm.total_out; strm.avail_out = [compressed length] - strm.total_out;
                    deflate(&strm, Z_FINISH);
                } 
                while (strm.avail_out == 0);

                deflateEnd(&strm);
                [compressed setLength: strm.total_out]; 

                uncompressedImageData = [NSData dataWithData: compressed]; 
            }

            if(uncompressedImageData != nil)
                [uncompressedImageData writeToFile:fileName atomically:YES];

当我运行它时,代码没有抛出任何异常,但结果图像仍然不可读。

1 个答案:

答案 0 :(得分:2)

您对CGPDFStreamCopyData的使用似乎表明您在那里存在误解:您没有设置所需的格式,该函数将其设置为它在流中遇到的格式。典型的用途是:

CGPDFDataFormat format;
CGPDFStreamCopyData(objectStream, &format);
if (format == CGPDFDataFormatRaw) {
    //handle raw data...
} else if (format == CGPDFDataFormatJPEGEncoded) {
    //handle jpeg data...
} else if (format == CGPDFDataFormatJPEG2000) {
    //handle jpeg 2000 data
}

PDF标准根本不支持PNG图像,因此您永远不会从图像数据流中获取有效的PNG文件。选项包括JPEG,JPEG2K和原始图像(有关详细信息,请参阅规范)。

Quartz透明地处理zlib压缩,因此你永远不会自己获得zlib压缩数据。