Question

I m trying to change color space for image objects of a pdf file, but first problem is that I cannot find ICC color profile inside pdf metadata.

All I have in Metadata is one array with 2 components:

ColorSpace :
    Name value: ICCBased
    Stream value (null) 

And when I get the Stream parsed into a dictionary:

Color Space Name ICCBased
  Filter :
    Name value: FlateDecode
  Length :
   integer value: 389757 
  N :
   integer value: 4 
  Range :
   ARRAY with value:
    integer value: 0 
    integer value: 1 
    integer value: 0 
    integer value: 1 
    integer value: 0 
    integer value: 1 
    integer value: 0 
    integer value: 1 

But I am unable to find in metadata the ICC profile data used on the color space of the image, the one you can see with acrobat:

enter image description here

By the way, if you are interested on how to get metadata form pdf file with coreGraphics here I put some code:

...

CGPDFDocumentRef pdfDocument = CGPDFDocumentCreateWithURL(pdfURL);

CGPDFPageRef page = CGPDFDocumentGetPage(pdfDocument, pageNumber);

CGPDFContentStreamRef contentStream =

CGPDFContentStreamCreateWithPage(page); CGPDFOperatorTableRef

operatorTable = CGPDFOperatorTableCreate();

CGPDFOperatorTableSetCallback(operatorTable, "Do", &op_Do);

CGPDFScannerRef contentStreamScanner =

CGPDFScannerCreate(contentStream, operatorTable, NULL);

CGPDFScannerScan(contentStreamScanner);

....

And then on the callback:

static void op_Do(CGPDFScannerRef s, void *info) {

CGPDFObjectRef imageObject = CGPDFContentStreamGetResource(cs, "XObject", imageLabel);

CGPDFStreamRef xObjectStream;

if (CGPDFObjectGetValue(imageObject, kCGPDFObjectTypeStream, &xObjectStream)) {

    CGPDFDictionaryRef xObjectDictionary = CGPDFStreamGetDictionary(xObjectStream);

    const char *subtype;

    CGPDFDictionaryGetName(xObjectDictionary, "Subtype", &subtype);

    if (strcmp(subtype, "Image") == 0) {

        NSString *imageID = [NSString stringWithCString: imageLabel encoding: NSASCIIStringEncoding];

        CGPDFDictionaryApplyFunction(xObjectDictionary, ListDictionaryObjects, NULL);

if (CGPDFDictionaryGetName(xObjectDictionary, "ColorSpace", &colorSpaceName)){

            fprintf(stdout,"Color Space Name %s\n", colorSpaceName);

}else{

            //Getting Color space array
            CGPDFArrayRef objectArray;

            CGPDFDictionaryGetArray(xObjectDictionary, "ColorSpace", &objectArray);
            //getting each array position             
            CGPDFStreamRef colorsSpaceStream;

            CGPDFArrayGetName(objectArray, 0, &colorSpaceName);

            fprintf(stdout,"Color Space Name %s\n", colorSpaceName);

            CGPDFArrayGetStream(objectArray, 1, &colorsSpaceStream);

            CGPDFDictionaryRef dictionary = CGPDFStreamGetDictionary(colorsSpaceStream);

            CGPDFDictionaryApplyFunction(dictionary, ListDictionaryObjectsLow, NULL);

}

...

And finally in ListDictionaryObjects functions I go through dictionary objects:

void ListDictionaryObjects (const char *key, CGPDFObjectRef object, void *info) { fprintf(stdout, "%s :\n", key);

CGPDFObjectType type = CGPDFObjectGetType(object);
switch (type) {
    case kCGPDFObjectTypeDictionary: {
        CGPDFDictionaryRef objectDictionary;
        if (CGPDFObjectGetValue(object, kCGPDFObjectTypeDictionary, &objectDictionary)) {
            fprintf(stdout," Dictionary value with: %zd elements\n", CGPDFDictionaryGetCount(objectDictionary));
            CGPDFDictionaryApplyFunction(objectDictionary, ListDictionaryObjectsLow, NULL);
        }
    }
        break;
    case kCGPDFObjectTypeInteger: {
        CGPDFInteger objectInteger;
        if (CGPDFObjectGetValue(object, kCGPDFObjectTypeInteger, &objectInteger)) {
           fprintf(stdout," integer value: %ld \n", (long int)objectInteger);
        }

    }
    break;
    case kCGPDFObjectTypeReal:{
        CGPDFReal objectReal;
        if (CGPDFObjectGetValue(object, kCGPDFObjectTypeReal, &objectReal)){
            fprintf(stdout," real value: %5.2f\n", objectReal);
        }
    } ...
Was it helpful?

Solution

Assigning a new color profile (i.e. without altering values in the object) to all objects of a certain color space can be done by creating a Quartz Filter with ColorSync Utility.

A technical note from the Mac Developer Library from 2005 about "ColorSync on Mac OS X" stated:

Quartz filters are currently available only through the various Mac OS X system-built utilities and applications. However, a new set of API's will be forthcoming.

But I could not find any other mention to Quartz Filters in Apple's documentation for developers.

I know this is not terribly helpful, but maybe it gives you a hint of were to look.

Edit: See this answer to "Apply a Quartz filter while saving PDF under Mac OS X 10.6.3"

OTHER TIPS

What you're seeing is described in the PDF specification: http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf

Look for section 8.6.5.5 which defines ICC-based color spaces - the data that you are looking for is contained in the stream you paste at the top of your message. It's not readily recognisable because it has been Flate encoded (ZIP encoded).

The question is what exactly you want to accomplish? If you just want to throw away this ICC based color space and create a new one, you don't need to find this data, just create a new color space object and make the image refer to your new object.

To change the existing ICC profile (which would be a bad idea in general), you'd have to decompress the stream data, adjust what you want to adjust and recompress it again.

These are followed steps:

1- Create your Quartz filter with ColorSync utility and save it as .qfilter file

2- apply this filter to your pdf file with this code:

PDFDocument *pdf = [[PDFDocument alloc]initWithURL:[NSURL fileURLWithPath:@"_pdfURL_"]];

NSDictionary *dict = [[NSDictionary alloc]initWithObjectsAndKeys:[QuartzFilter quartzFilterWithURL:[NSURL fileURLWithPath:@"_myFilter.qfilter_"]], @"QuartzFilter", nil]; 

[pdf writeToFile:@"_pdfFilePath_" withOptions:dict];
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top