2010-08-31 3 views
2

Я пытаюсь создать уменьшенные изображения для CGPDFDocument.
В PDF документ с анализом разделе Руководства по программированию Quartz, есть следующий код:Извлечение уменьшенного изображения из CGPDFPageRef

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 здесь: Extracting images from a PDF

Я пытающегося использовать decodeValuesFromImageDictionary() и getImageRef() функции, перечисленные в своем ответе, чтобы создать UIImage представлять свою миниатюру.

Моя проблема заключается в том, что изображение я получаю имеет неправильные цвета и неправильные размеры, за исключением, когда я установил аргумент CGColorSpaceRef функции CGImageCreate() к CGColorSpaceCreateDeviceGray(), в этом случае я получаю (правильное) полутоновое представление эскиза, который, конечно, не то, что я хочу.
Я знаю, что проверял словарь потока миниатюр, что формат изображения - CGPDFDataFormatRaw, а ColorSpace - это DeviceRGB. Я также знаю, что к изображению применяются два фильтра (ASCII85Decode и FlateDecode), хотя я не уверен, что это имеет какое-либо значение.

Любые предложения или соображения относительно того, почему это происходит, и что делать, чтобы исправить это очень признательно!

ответ

0

мона м в коде, предоставленный по ссылке, указанные содержат комментировали строку:

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

}

Но, к сожалению, я получаю некоторые серые точки на изображении в конце.

Смежные вопросы