2

CGPDFDocumentのサムネイル画像を作成しようとしています。
QuartzプログラミングガイドのPDFドキュメント解析セクションには、次のコードがあります。

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してイメージを作成することです。
シュガーはここでPDFから画像を抽出するという同様の質問に答えます:PDFから画像を抽出 する

decodeValuesFromImageDictionary()彼の回答に記載されている関数とgetImageRef()関数を使用して、サムネイルを表すUIImageを作成 しようとしています。

CGImageCreate()私の問題は、関数のCGColorSpaceRef引数をに設定した場合を除いて、取得した画像の色と寸法が間違っていることCGColorSpaceCreateDeviceGray()です。この場合、サムネイルの(正しい)グレースケール表現が得られますが、これはもちろん私が望むものではありません。
サムネイルストリームディクショナリを調べると、画像形式はCGPDFDataFormatRawであり、ColorSpaceはDeviceRGBであることがわかります。また、2つのフィルター(ASCII85DecodeとFlateDecode)が画像に適用されていることも知っていますが、これが重要かどうかはわかりません。

これが発生する理由とそれを修正するために何をすべきかについての提案や洞察は大歓迎です!

4

1 に答える 1

0

指定したリンクによって提供されるコードのmonamには、コメント行が含まれています。

//      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);

}

しかし、残念ながら、最後に画像に灰色の点がいくつか表示されます。

于 2010-09-09T18:56:44.517 に答える