2010-08-31 19 views
2

Je tente de créer des images miniatures pour un document CGPDF.
Dans la section Document PDF Parsing du Guide de programmation Quartz, il y a le code suivant:Extraction de l'image miniature de 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); 

L'étape suivante serait d'utiliser data pour créer l'image.
sucre répond à la même question d'extraire des images de PDF ici: Extracting images from a PDF

Je cherche à utiliser les fonctions decodeValuesFromImageDictionary() et getImageRef() figurant dans sa réponse à créer un UIImage pour représenter ma vignette.

Mon problème est que l'image que j'obtiens a mal les couleurs et les dimensions mal, sauf quand je mets l'argument CGColorSpaceRef de la fonction CGImageCreate() à CGColorSpaceCreateDeviceGray(), dans ce cas, je reçois le (correct) représentation demi-teinte de la miniature qui bien sûr Ce n'est pas ce que je veux.
Je sais d'après l'examen du dictionnaire de flux de vignettes que le format d'image est CGPDFDataFormatRaw et que ColorSpace est DeviceRGB. Je sais aussi que deux filtres (ASCII85Decode et FlateDecode) sont appliqués à l'image, même si je ne suis pas sûr que ce soit significatif.

Toute suggestion ou idée sur la raison pour laquelle cela se produit et sur ce qu'il faut faire pour y remédier est grandement appréciée!

Répondre

0

mona m code fourni par lien que vous avez spécifié contient commenté la ligne:

//  cgColorSpace = colorSpaceFromPDFArray(colorSpaceArray); 

Au lieu d'analyser colorSpaceArray et obtenir l'espace précis des couleurs un CGColorSpaceCreateDeviceRGB est affecté à la variable cgColorSpace ce qui est faux.

Voici une implémentation de la méthode manquante, je l'ai trouvée sur internet.

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

}

Mais malheureusement, je reçois des points gris sur l'image à la fin.