Reading & writing ICC profiles

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
sanderton

Reading & writing ICC profiles

Post by sanderton »

I need a way of writing the ICC profile to a ICM file. I did find a posting, here
http://studio.imagemagick.org/discussio ... dac61f4db6
with C++ code that I adapted as follows.

Code: Select all

Magick::Blob blobICC;
blobICC = m_pIMImage->iccColorProfile();
if ( blobICC.length() > 0 )
{
  Magick::Image ICCProfile( blobICC );
  ICCProfile.magick( "ICC" );
  ICCProfile.write( (LPCTSTR) csICMFileName );
}
But the magick() function throws an exception: "Unrecognized image format: "ICC:""

Then I tried this test:

Code: Select all

Magick::Image ICCProfile_test;
ICCProfile_test.read( "C:\\lcms\\profiles\\sRGB.icm" );
ICCProfile_test.magick( "ICC" );
ICCProfile_test.write( "C:\\testing\\sRGB_test.icm" );
but I'm getting an unhandled exception, Magick::ErrorMissingDelegate.
I do have this DLL, CORE_lcms_.dll; is this the LCMS delegate library?

I guess I've basically got two questions:
1) Is "ICC" a valid argument for the magick() function?
2) Is CORE_lcms_.dll the LCMS delegate library?

If anyone can help with these questions I'd be really grateful.
Thanks,
sanderton
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Post by magick »

Your code worked fine for us with ImageMagick 6.2.8-7, the current release. LCMS is the delegate library required to deal with color profiles.
sanderton

ICC profile needed META delegate module

Post by sanderton »

Well, after debugging further into the code, I found that it was actually looking for the META delegate module: IM_MOD_DB_meta_.dll.
When I copied this into my exe folder the test code worked (2nd block of code). I am able to view the new ICM file with "ICC Profile Inspector" (available from the ICC website.)

I'm still trying to get the 1st block of code to work; but now the problem is that the new ICM file that I create is empty. When I debug into WriteImage() the magick_info structure contains these values

Code: Select all

name:           "ICM"
description:    "ICC Color Profile"
module:         "META"
decoder:        ReadMETAImage(const _ImageInfo *, _ExceptionInfo *)
encoder:        WriteMETAImage(const _ImageInfo *, _Image *)
Then, when I debug into WriteMETAImage() I end up returning at this line of code:

Code: Select all

  if (image->profiles == (void *) NULL)
    return(MagickFalse);
but I wonder if I should really get down to this code block further down the function:

Code: Select all

  if ((LocaleCompare(image_info->magick,"ICC") == 0) ||
      (LocaleCompare(image_info->magick,"ICM") == 0))
    {
      /*
        Write ICM image.
      */
      profile=GetImageProfile(image,"icc");
      if (profile == (StringInfo *) NULL)
        ThrowWriterException(CoderError,"NoColorProfileIsAvailable");
      status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
      if (status == MagickFalse)
        return(status);
      (void) WriteBlob(image,profile->length,profile->datum);
      CloseBlob(image);
      return(MagickTrue);
    }
Is there something else I need to do to get passed the line that checks whether the profile is NULL?

Thanks for your input, I really appreciate it.
sanderton
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Post by magick »

You can add a color profile, for example, to an image with iccColorProfile(). Once a profile is associated with an image, it should write using the method you posted.
sanderton

writing ICC blob to ICM file

Post by sanderton »

Thanks Magick! It works now.

Here's the updated code block (for anyone who's interested); it extracts an embedded ICC profile from an image and then writes it to a .icm file:

Code: Select all

Magick::Blob blobICC;
blobICC = m_pIMImage->iccColorProfile();
if ( blobICC.length() > 0 )
{
  /***** THIS CODE WORKS! *****/
  Magick::Image ICCProfile;
  ICCProfile.profile( "ICC", blobICC );
  ICCProfile.write( "C:\\testing\\ICCProfile.icm" );
}
I don't understand why the original code wouldn't work (theoretically that is). The working code above uses the profile() function, while I'd originally thought that calling iccColorProfile() would work. The following lines throw an exception:

Code: Select all

{
  /***** THIS CODE DOES NOT WORK! *****/
  Magick::Image ICCProfile;
  ICCProfile.magick( "ICC" );
  ICCProfile.iccColorProfile( blobICC );
  ICCProfile.write( "C:\\testing\\ICCProfile.icm" );
}
Cheers,
sanderton
Post Reply