[poppler] Color Management

Hal V. Engel hvengel at astound.net
Thu Feb 26 15:29:11 PST 2009


I have been using the Color Management patches that Koji Otani posted to this 
list in Dec since that time.  And after these were merged into git trunk I 
have been using git head.  These are a significant step forward and I would 
like to thank Koji for his hard work and Albert for taking the time to review 
the patch set and getting it committed.  This is a significant step forward 
although it will take more work to get this in a fully working condition.

One issue is how display profiles are currently selected (or actually not 
selected is more correct).

In a follow up note on Dec. 14 James Cloos wrote:

"I've only tested with a few alternate display profiles.  Nothing broke,
but I havn't been able to tell that a different profile was in use."

The reason that James didn't notice different display profiles making a 
difference is that the current code does not correctly pick up changes to the 
display profile settings in X11 and it does not use the X11 _ICC_PROFILE atom.  

In addition there are other issues with the code related to locating profiles 
as well.  

Having had a look at the code let me make some comments related to these 
issues. 

1. Where to look for profiles on a *nix system.

As early as May 2004 OpenICC had a proposal to use /usr/share/color/icc and 
~/.color/icc for system and user ICC profile directories.  This later became a 
formal standards proposal and that has been through a number of revisions.  
This link

 http://www.oyranos.com/wiki/index.php?title=OpenIccDirectoryProposal

has the latest version of the proposed standard which is an extension of the 
widely used XDG base directory specification.  This standard may be subject to 
more revisions but it is considered the working standard for where ICC 
profiles should be located on *nix machines and is now fairly stable.

2. X11 display profiles.

X11 has had a _ICC_PROFILE atom for some time now.  This is based on a draft 
specification that came out of the OpenICC group in 2005 which can be found 
here:

http://www.burtonini.com/computing/x-icc-profiles-spec-0.1.html

This draft had issues with some multi monitor setups and was later revised but 
I can't find the revisions on-line right now.  But I do have a copy of a note 
to the OpenICC list that summarizes those changes.

"Remove: ?Currently there is only one atom defined.
and: ? ? ?The _ICC_PROFILE atom is set on the root window for each screen.


And add:

The atom name for the first screen in a root window is _ICC_Profile. 

For root windows spanning more than one screen, as typical in Xinerama 
multihead configurations, a atom for each screen is added holding the 
appropriate ICC profile. All screens in a root window starting from 
number one use _ICC_Profile as atom name extended with an underscore plus 
the screen number, e.g. _ICC_Profile_1 .

followed by your text:

The atoms are of type XA_CARDINAL with 8-bit elements. The value of the 
atoms should be a literal ICC profile, that applications can read and 
parse directly." 

I know the updated specification was published somewhere but I can locate it 
at this time.

So how is this used?

Here is a snippet of code that shows how this might be done using GTK+ (I 
think this was pulled out of the GIMP code base around 6-2005):

static cmsHPROFILE *
get_screen_profile (GdkScreen *screen)
{
       Display *dpy;
       Atom icc_atom, type;
       int format;
       gulong nitems;
       gulong bytes_after;
       guchar *str;
       int result;
       cmsHPROFILE *profile;

       g_return_val_if_fail (screen != NULL, NULL);

       dpy = GDK_DISPLAY_XDISPLAY (gdk_screen_get_display (screen));
       icc_atom = gdk_x11_get_xatom_by_name_for_display gdk_screen_get_display 
(screen), "_ICC_PROFILE");

       result = XGetWindowProperty (dpy, GDK_WINDOW_XID 	
				    (gdk_screen_get_root_window (screen)),
                                    icc_atom, 0, G_MAXLONG,
                                    False, XA_CARDINAL, &type, &format, 
				    &nitems, &bytes_after, (guchar **)&str);

       if (nitems) {
               profile = cmsOpenProfileFromMem(str, nitems);
               XFree (str);
               return profile;
       } else {
               g_printerr("No profile, not correcting\n");
               return NULL;
       }
} 

For those using the Qt widget set I found this piece of untested but plausible 
code (this was posted to the kde-core-devel list by Lubos Lunak):

static cmsHPROFILE *
get_screen_profile (int screen)
{
       Display *dpy;
       Atom icc_atom, type;
       int format;
       long nitems;
       long bytes_after;
       unsigned char *str;
       int result;
       cmsHPROFILE *profile = NULL;

       static Atom icc_atom = XInternAtom( qt_xdisplay(), "_ICC_PROFILE", 
False );

       if ( XGetWindowProperty ( qt_xdisplay(), qt_xrootwin( screen ), 
                                              icc_atom, 0, INT_MAX, False,
                                              XA_CARDINAL, &type, &format, 
                                             &nitems, &bytes_after, 
                                              (unsigned char **)&str)) {
	if( nitems ) {
               profile = cmsOpenProfileFromMem(str, nitems);
               XFree (str);
               return profile;
       } else {
               kdDebug() << "No profile, not correcting" << endl;
               return NULL;
       }
}

Using the X11 _ICC_PROFILE atom(s) will fix the issue that James was seeing.  
But the code also needs to be updated to search for profiles in the correct 
locations.  In addition it should allow user programs to override using the 
_ICC_PROFILE X11 atom. 

Hal
 




More information about the poppler mailing list