【问题标题】:Extracting thumbnail image from CGPDFPageRef从 CGPDFPageRef 中提取缩略图
【发布时间】:2011-04-06 05:49:01
【问题描述】:

我正在尝试为 CGPDFDocument 创建缩略图。
在 Quartz Programming Guide 的 PDF Document Parsing 部分,有如下代码:

CGPDFDictionaryRef d;
CGPDFStreamRef stream; // represents a sequence of bytes
d = CGPDFPageGetDictionary(page);
// check for thumbnail data
if (CGPDFDictionaryGetStream (d, “Thumb”, &stream)){
    // get the data if it exists
    data = CGPDFStreamCopyData (stream, &format);

下一步是使用data 创建图像。
Sugar 在这里回答了从 PDF 中提取图像的类似问题: Extracting images from a PDF

我正在尝试使用他的答案中列出的 decodeValuesFromImageDictionary()getImageRef() 函数来创建一个 UIImage 来表示我的缩略图。

我的问题是我获得的图像颜色和尺寸错误,除非我将CGImageCreate() 函数的 CGColorSpaceRef 参数设置为CGColorSpaceCreateDeviceGray(),在这种情况下我得到缩略图的(正确)灰度表示这当然不是我想要的。
我通过检查缩略图流字典知道图像格式是 CGPDFDataFormatRaw 并且 ColorSpace 是 DeviceRGB。我也知道有两个过滤器(ASCII85Decode 和 FlateDecode)应用于图像,尽管我不确定这是否有任何意义。

非常感谢任何关于为什么会发生这种情况以及如何解决它的建议或见解!

【问题讨论】:

    标签: iphone image thumbnails quartz-graphics cgpdfdocument


    【解决方案1】:

    您指定的链接提供的代码中的mona m包含注释行:

    //      cgColorSpace = colorSpaceFromPDFArray(colorSpaceArray);
    

    没有分析 colorSpaceArray 并获得准确的颜色空间,而是将 CGColorSpaceCreateDeviceRGB 分配给 cgColorSpace 变量,这是错误的。

    这是一个缺失方法的实现,我在网上找到的。

    CGColorSpaceRef colorSpaceFromPDFArray(CGPDFArrayRef colorSpaceArray){
    CGColorSpaceRef       cgColorSpace = NULL, alternateColorSpace = NULL;
    CGPDFStreamRef        stream;
    const char            *colorSpaceName = NULL, *alternateColorSpaceName = NULL;
    CGPDFInteger        numberOfComponents;
    CGPDFDictionaryRef    dict;
    bool                retrieved;
    CGFloat                *range;
    CGPDFArrayRef        rangeArray;
    
    if (CGPDFArrayGetName(colorSpaceArray, 0, &colorSpaceName)) {
        if (strcmp(colorSpaceName, "ICCBased") == 0) {
            if (CGPDFArrayGetStream(colorSpaceArray, 1, &stream)) {
                dict = CGPDFStreamGetDictionary(stream);
    
                // First obtain the alternate color space if present
                if (CGPDFDictionaryGetName(dict, "Alternate",  &alternateColorSpaceName)) {
                    if (strcmp(alternateColorSpaceName, "DeviceRGB") == 0) {
                        alternateColorSpace = CGColorSpaceCreateDeviceRGB();
                    } else if (strcmp(alternateColorSpaceName, "DeviceGray") == 
                               0) {
                        alternateColorSpace = CGColorSpaceCreateDeviceGray();
                    } else if (strcmp(alternateColorSpaceName, "DeviceCMYK") == 
                               0) {
                        alternateColorSpace = CGColorSpaceCreateDeviceCMYK();
                    }
                }
    
                // Obtain the preferential color space
                CGPDFDataFormat        dataFormat;
                CFDataRef            colorSpaceDataPtr = 
                CGPDFStreamCopyData(stream, &dataFormat);
    
                if (dataFormat == CGPDFDataFormatRaw) {
                    CGDataProviderRef    profile = 
                    CGDataProviderCreateWithCFData(colorSpaceDataPtr);
    
                    retrieved = CGPDFDictionaryGetInteger(dict, "N", 
                                                          &numberOfComponents);
    
                    // Deduce an alternate color space if we don't have one 
                    //already
                    if (alternateColorSpace == NULL) {
                        switch (numberOfComponents) {
                            case 1:
                                alternateColorSpace = CGColorSpaceCreateDeviceGray();
                                break;
                            case 3:
                                alternateColorSpace = CGColorSpaceCreateDeviceRGB();
                                break;
                            case 4:
                                alternateColorSpace = CGColorSpaceCreateDeviceCMYK();
                                break;
                            default:
                                break;
                        }
                    }
    
                    range = malloc(numberOfComponents * 2 * sizeof(CGFloat));
                    if (!CGPDFDictionaryGetArray(dict, "Range", &rangeArray)) {
                        for (int i = 0; i < numberOfComponents * 2; i += 2) {
                            range[i] = (i % 2 == 0) ? 0.0 : 1.0;
                        }
                    } else {
                        size_t count = CGPDFArrayGetCount(rangeArray);
                        for (int i = 0; i < count; i++) {
                            (void)CGPDFArrayGetNumber(rangeArray, i, &range[i]);
                        }
    
                    }
    
    
                    cgColorSpace = CGColorSpaceCreateICCBased(numberOfComponents, range, profile, 
                                               alternateColorSpace);
                    CGDataProviderRelease(profile);
                    free(range);
                    if (cgColorSpace) {
                        // Since we have a preferential color space, we no 
                        //longer need the hang on to the alternate color space
                        CGColorSpaceRelease(alternateColorSpace);
                    } else {
                        cgColorSpace = alternateColorSpace;
                    }
    
                } else if (dataFormat == CGPDFDataFormatJPEGEncoded) {
                    //
                } else if (dataFormat == CGPDFDataFormatJPEG2000) {
                    //
                }
            }
        } else if (strcmp(colorSpaceName, "Indexed") == 0) {
            CGColorSpaceRef baseSpace;
            CGPDFArrayRef    base = NULL;
            CGPDFInteger    highValue = 0;
            CGPDFStreamRef    stream = NULL;
            CGPDFStringRef    string;
            const unsigned char *chars;
            const char        *namedColorSpaceName;
    
            if (CGPDFArrayGetArray(colorSpaceArray, 1, &base)) {
                baseSpace = colorSpaceFromPDFArray(base);
            } else if (CGPDFArrayGetName(colorSpaceArray, 1, 
                                         &namedColorSpaceName)) {
                if (strcmp(namedColorSpaceName, "DeviceRGB") == 0) {
                    baseSpace = CGColorSpaceCreateDeviceRGB();
                } else if (strcmp(namedColorSpaceName, "DeviceGray") == 0) {
                    baseSpace = CGColorSpaceCreateDeviceGray();
                } else if (strcmp(namedColorSpaceName, "DeviceCMYK") == 0) {
                    baseSpace = CGColorSpaceCreateDeviceCMYK();
                }
            }
    
            retrieved = CGPDFArrayGetInteger(colorSpaceArray, 2, &highValue);
    
            if (CGPDFArrayGetStream(colorSpaceArray, 3, &stream)) {
                chars = CFDataGetBytePtr(CGPDFStreamCopyData(stream, NULL));
            } else if (CGPDFArrayGetString(colorSpaceArray, 3, &string)) {
                chars = CGPDFStringGetBytePtr(string);
            } else {
    
                // TODO: Raise some error state?
            }
    
            cgColorSpace = CGColorSpaceCreateIndexed(baseSpace, highValue, 
                                                     chars);
        }
    }
    
    return (CGColorSpaceRef)CFMakeCollectable(cgColorSpace);
    

    }

    但不幸的是,最后我在图像上出现了一些灰点。

    【讨论】:

      猜你喜欢
      • 2012-05-08
      • 1970-01-01
      • 2014-01-22
      • 2013-09-13
      • 1970-01-01
      • 2015-10-17
      • 2011-07-20
      • 2011-08-23
      • 2018-07-25
      相关资源
      最近更新 更多