Embedded ICC colour profiles and conversion to sRGB

4,669 views
Skip to first unread message

Electric Art

unread,
Jul 23, 2013, 1:57:28 AM7/23/13
to resour...@googlegroups.com
Hi all,

I've been reading through a whole host of posts regarding ICC profiles and conversion with Resourcespace, and from what I can gather, it should be possible to do what we need with Resourcespace as it stands, but unfortunately I can't seem to work out how to do it. As I understand it, Resourcespace should, with the right configuration, use the embedded profile of an image file (JPEG, TIFF, PSD, e.t.c) and then be able to convert the preview/thumbnail e.t.c. to sRGB. It then strips the profile or there is no profile in the resulting image (in some ways not ideal, but not a huge problem as the browser should assume sRGB for untagged images). Unfortunately I cannot get this to work. We use a few different ICC colour spaces for our files (some are sRGB, some AdobeRGB, some DCam3) and so it doesn't work for us to try and hard-code a particular profile as the source profile - hence we want to be able to use the embedded profile. Is this actually possible?

I've tried a number of different combinations, and here are my current settings;

Resourcespace config.php settings;

<code>
# ICC Color Management Features (Experimental)
# Note that ImageMagick must be installed and configured with LCMS support
# for this to work

# Enable extraction and use of ICC profiles from original images
$icc_extraction = true;
$imagemagick_preserve_profiles=false;

# target color profile for preview generation
# the file must be located in the /iccprofiles folder
# this target preview will be used for the conversion
# but will not be embedded
$icc_preview_profile = 'sRGB_IEC61966-2-1_black_scaled.icc';

# additional options for profile conversion during preview generation
$icc_preview_options = '-intent relative -black-point-compensation';
</code>

Imagemagick version (built with lcms and lcms is installed);

<code>
$ convert -version
Version: ImageMagick 6.8.6-5 2013-07-17 Q16 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2013 ImageMagick Studio LLC
Features: DPC HDRI
Delegates: autotrace bzlib djvu fftw fontconfig freetype gslib jng jp2 jpeg lcms lqr lzma openexr pango png ps rsvg tiff wmf x xml zlib
</code>

ICC profiles for sRGB exist;

<code>
profiles$ ls -al
-rw-r--r--  1 root root 3048 Jul 17 16:11 sRGB_IEC61966-2-1_black_scaled.icc
-rw-r--r--  1 root root 3052 Jul 17 16:11 sRGB_IEC61966-2-1_no_black_scaling.icc
</code>

I've attached an example file (ColourTest_RGB_DCam3_tagged.jpg). When it is opened in Photoshop or another colour managed application (and use the embedded profile), you can see it is quite saturated. The Resourcespace preview in comparison is dull and washed out. In fact, the Resourcespace preview matches the conversion of the same file (ColourTest_RGB_DCam3_tagged) saved untagged, which means to me that it is stripping or ignoring the embedded profile. You can see the Resourcespace conversion and original in Photoshop side by side in the attached file 'resourcespace_photoshop.jpg' where Resourcespace is on the left.

Any help on this matter would be greatly appreciated. If anyone can guide me to a working configuration that would be amazing. Others seem to have this working, so perhaps it is an Imagemagick version issue? What version of Imagemagick are people using successfully for this? Unfortunately it is not an option for us to use Graphicsmagick, as we need PSB compatbility which Graphicsmagick does not have...

Also, and perhaps this is a related issue, when attempting to extract the profile from large PSD and PSB files, Resourcespace will generate several copies (maybe 40 or so) of the extracted .icc profile, and does not delete them after preview generation. Curiously this only seems to happen with PSD and PSB formats, and only of a certain size (of which I am yet to determine). Perhaps related to a php timeout setting? Or something else?

Again, any help would be greatly appreciated!

Thanks so much,
kind regards,
Tristan.
ColourTest_RGB_DCam3_tagged.jpg
resourcespace_photoshop.jpg
Resourcespace_Excess_ICC_Profiles.jpg

Jeff Harmon

unread,
Jul 23, 2013, 2:17:16 AM7/23/13
to resour...@googlegroups.com, resour...@googlegroups.com
This was broken between r4443 and 4607. Are you running a version between these revisions?

Jeff

--
Jeff Harmon
Chief Executive Officer
Colorhythm LLC

Main Office:  +1 415-399-9921
Mobile:  +1 510-710-9590

--
ResourceSpace: Open Source Digital Asset Management
http://www.resourcespace.org
---
You received this message because you are subscribed to the Google Groups "ResourceSpace" group.
To unsubscribe from this group and stop receiving emails from it, send an email to resourcespac...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 
<ColourTest_RGB_DCam3_tagged.jpg>
<resourcespace_photoshop.jpg>
<Resourcespace_Excess_ICC_Profiles.jpg>

Electric Art

unread,
Jul 23, 2013, 2:34:16 AM7/23/13
to resour...@googlegroups.com
I just realised that Google stripped the profile from my tagged image! Here is a zipped copy instead.


ColourTest_RGB_DCam3_tagged.jpg.zip

Electric Art

unread,
Jul 23, 2013, 2:36:04 AM7/23/13
to resour...@googlegroups.com
Hi Jeff,

Thanks for the reply.

I'm running Build 4641.

kind regards,
Tristan.

Electric Art

unread,
Jul 23, 2013, 2:39:12 AM7/23/13
to resour...@googlegroups.com
Hi Jeff,

It is also probably worth mentioning that we are using Staticsync to generate previews.


kind regards,
Tristan.

On Tuesday, July 23, 2013 4:17:16 PM UTC+10, Jeff Harmon wrote:

Electric Art

unread,
Jul 23, 2013, 9:02:14 PM7/23/13
to resour...@googlegroups.com
It appears that the multiple ICC extraction issue with larger files is an ImageMagick bug. I can reproduce the bug on a large PSD or PSB file with the command;

convert PSD_RGB_Test.psd icc:PSD_RGB_Test.icc

As for the conversion issue, I'm not sure if this is an Imagemagick issue or a Resourcespace one?

Jeff Harmon

unread,
Jul 23, 2013, 9:39:22 PM7/23/13
to ResourceSpace
Upgrade ImageMagick to 6.8.6-6.  They fixed an ICC profile bug related to JPEGs that might help us here:



--

Electric Art

unread,
Jul 23, 2013, 10:50:16 PM7/23/13
to resour...@googlegroups.com
Hey Jeff,

Thanks! Building now.

So I've done a bit more research regarding the multiple ICC issue. Turns out this is normal behaviour for ImageMagick with multi-layered PSD and PSB files. So it comes back to how ResourceSpace handles PSDs and PSBs. A while back I started a thread about trying to make preview generation of PSD and PSB files faster and more reliable by introducing [0] to the ImageMagick convert command when importing PSD and PSBs. By adding the [0], we can tell ImageMagick to extract the first layer from the PSB/PSD, and provided it has been saved using the 'Maximize Compatibility' option when saving, that first layer will be the composite (flattened) image. It saves ImageMagick having to try and flatten the file (takes longer). If files are not saved with 'Maximize Compatibility' they will not generate a preview properly anyway if the first layer it finds is anything but a pixel layer. The other added benefit of adding [0], which I just discovered, is that it stops ImageMagick generating the excess ICC profiles.

Here is the original thread;

https://groups.google.com/forum/#!searchin/resourcespace/imagemagick$20psb/resourcespace/7TeilX4kvds/bmg2H13M9asJ

And here is how I had previously implemented it;

Add to preview_preprocessing.php

/* ----------------------------------------
        Try PhotoshopCompositeExtract
   ----------------------------------------
*/
# Note: to work, Photoshop files must be saved with 'Maximise Compatibility' on. For PSB support, ImageMagick must be installed.
if ($extension=="psb" && !isset($newfile))
        {
        global $photoshop_composite_extract;
        if ($photoshop_composite_extract)
                {
                if ($convert_fullpath!=false)
                        {
                        $psbcommand = "$convert_fullpath ".escapeshellarg($file. '[0]') . ' '. escapeshellarg($target);
                        run_command($psbcommand);
                        }
                if (file_exists($target))
                        {
                        #if the file contains an image, use it; if it's blank, it needs to be erased because it will cause an error in ffmpeg_processing.php
                        if (filesize_unlimited($target)>0){$newfile = $target;}else{unlink($target);}
                        }
                }
        }



Then add in config.php

$photoshop_composite_extract=true;


My only concern with this implementation is that I'm not sure if it includes or bypasses any of the colour management code implemented for ResourceSpace? Ideally I'd like to keep that functionality while introducing the addition of the [0] fix for the ICC profiles... Can anyone who is more familiar with the code tell me if this is the case? Honestly I kludged my way through this as I am not a programmer of any description!

Thanks for all your help so far.



Reference for ImageMagick and PSD/PSB saving with [0]

http://www.rubblewebs.co.uk/imagemagick/psd.php

Reference for 'Maximise compatibility' for PSD and PSB files;

Jeff Harmon

unread,
Jul 23, 2013, 11:15:40 PM7/23/13
to ResourceSpace
What's wrong with setting:
$photoshop_thumb_extract=true;

for PSDs?  Did I miss that you tried that?

I can easily add support for PSBs for this if this works for you.

Jeff

Electric Art

unread,
Jul 23, 2013, 11:20:43 PM7/23/13
to resour...@googlegroups.com
Hi Jeff,

Unfortunately whilst it works it isn't quite fit for purpose - it works, but will only extract a tiny thumbnail - maybe 128px at best?

Tristan.

Electric Art

unread,
Jul 23, 2013, 11:24:44 PM7/23/13
to resour...@googlegroups.com
Hi Jeff,

Also just tried building ImageMagick 6.8.6-6 with no luck. I thought that it might be that I was building with lcms2 instead of lcms (it defaults to building with lcms2 if you have it installed), so I explicitly added '--with-lcms2=no' '--with-lcms=yes' to my configure, however it still didn't work. :(

I tried building the following versions of ImageMagick, all with the same results unfortunately;

6.7.7-10
6.7.9-10
6.8.6-5
6.8.6-6

I'm starting to run out of ideas unfortunately!


Tristan.

On Wednesday, July 24, 2013 1:15:40 PM UTC+10, Jeff Harmon wrote:

Jeff Harmon

unread,
Jul 23, 2013, 11:31:59 PM7/23/13
to ResourceSpace
I'm seeing perfectly color managed previews EXCEPT the large thumbs!  Hmm.

Also, are you running a Mac server?  qlpreview might do the trick for you.

Jeff

Jeff Harmon

unread,
Jul 23, 2013, 11:34:26 PM7/23/13
to ResourceSpace
The problem with qlpreview though is that it doesn't handle alpha channels well...

Still testing.

Jeff

Jeff Harmon

unread,
Jul 23, 2013, 11:34:56 PM7/23/13
to ResourceSpace
That's true, sorry.  I thought it did better!  (As it does with InDesign).

Jeff

Jeff Harmon

unread,
Jul 23, 2013, 11:42:57 PM7/23/13
to ResourceSpace
Tristan, it seems that THM and COL images are not color managed, but my PRE preview actually looks correct for the DCam test JPEG you sent.

Do you have a DCam-tagged image that is larger than 850px? Please zip and send.  Sorry, I know this is not exactly the PSD/PSB train still...

Jeff

Jeff Harmon

unread,
Jul 23, 2013, 11:49:29 PM7/23/13
to ResourceSpace
Wait... do you have
$imagemagick_preserve_profiles=true;

Or false?  It should be true, my friend.

Jeff

Electric Art

unread,
Jul 23, 2013, 11:51:25 PM7/23/13
to resour...@googlegroups.com
Interesting? I'm starting to wonder if format is an issue possibly? I've been using tagged TIFF files in my testing.

Here's a zipped JPEG at a higher resolution for your testing.

Thanks so much.

Tristan.
ColourTest_RGB_DCam3_tagged.jpg.zip

Electric Art

unread,
Jul 23, 2013, 11:53:28 PM7/23/13
to resour...@googlegroups.com
Also, forgot to say, I'm using Ubuntu Server;

Distributor ID:    Ubuntu
Description:    Ubuntu 12.04.2 LTS
Release:    12.04
Codename:    precise

Tristan.

Electric Art

unread,
Jul 23, 2013, 11:55:49 PM7/23/13
to resour...@googlegroups.com
Hey Jeff,

I've tried both - same result unfortunately...

Tristan.

Electric Art

unread,
Jul 23, 2013, 11:58:09 PM7/23/13
to resour...@googlegroups.com
Hey Jeff,

What version of ImageMagick are you using? Or are you using GraphicsMagick?

Tristan.

Jeff Harmon

unread,
Jul 24, 2013, 12:01:56 AM7/24/13
to ResourceSpace
That new file looks color managed and great throughout!  So, that means the algorithm is passing the original through unmanaged when it's smaller.  I see this indicator, aside from the visual facts:

# If using imagemagick, should colour profiles be preserved? (for larger sizes only - above 'scr')

As well as the logic of it.  The way ResourceSpace tries to intelligently handle making previews in the most efficient manner actually circumnavigates the ICC code in image_processing in some instances!

This is too hard for a quick, free fix, unfortunately. Someone might fix it voluntarily, but I know that we will take a little time to get to it ourselves.

Jeff


Jeff Harmon

unread,
Jul 24, 2013, 12:03:02 AM7/24/13
to ResourceSpace
IM 6.8.5-5 Q16 with LCMS.

Jeff

Jeff Harmon

unread,
Jul 24, 2013, 12:14:44 AM7/24/13
to ResourceSpace
I wrote the original author of the code and implored upon him to revisit it in light of this new information.  The fellow got a new job that is very demanding, so we may not get his attention for some time!  Fingers crossed.

Best,
Jeff

Electric Art

unread,
Jul 24, 2013, 12:17:13 AM7/24/13
to resour...@googlegroups.com
Hey Jeff,

My understanding is though that the setting;


# If using imagemagick, should colour profiles be preserved? (for larger sizes only - above 'scr')
$imagemagick_preserve_profiles=true;

Is about preserving the original profile with the file for download, rather than converting it, which it should do for 'scr' and smaller sizes, or if set to 'false', all should be converted to the profile specified - in my case - sRGB_IEC61966-2-1_black_scaled.icc

Hence this setting;


# target color profile for preview generation
# the file must be located in the /iccprofiles folder
# this target preview will be used for the conversion
# but will not be embedded
$icc_preview_profile = 'sRGB_IEC61966-2-1_black_scaled.icc';

There is no point as I would understand it to have a 'target profile', if you're not converting anything? It would just be a matter of stripping the profile - which at the moment, is all that seems to happen.

As I understand it, for 'scr' sizes and below, OR, all sizes if $imagemagick_preserve_profiles=false; then ResourceSpace should be converting to the target profile of sRGB_IEC61966-2-1_black_scaled.icc, and the resulting file either has no icc profile, or ResourceSpace actively strips it away to save space...?

Is this wrong? I'm certain that's what I ascertained from the other discussions, and I'm almost certain we had this working in our previous install of ResourceSpace...

Tristan.

Jeff Harmon

unread,
Jul 24, 2013, 12:35:24 AM7/24/13
to resour...@googlegroups.com, resour...@googlegroups.com
I'm describing what's happening here, not what should be happening. I get perfect previews for the larger file, and THMs and COLs are bad for the other, smaller one. That makes me suspect that smaller files are circumnavigating the ICC conversion code.  Are you seeing different results from me?

Your understanding of the roles of those parameters may be correct; I wasn't trying to overreach in my conclusions. I was proposing that that comment in config indicates a possible fork in the road consonant with the behavior I am seeing. 

Jeff

--
Jeff Harmon
Chief Executive Officer
Colorhythm LLC

Main Office:  +1 415-399-9921
Mobile:  +1 510-710-9590

Electric Art

unread,
Jul 24, 2013, 1:54:19 AM7/24/13
to resour...@googlegroups.com
Hi Jeff,

Sorry, I just wasn't sure if I had it completely wrong and was trying to do something that couldn't be done! I was getting a bit confused and was thinking out loud, sorry - I didn't meant to sound unappreciative at all. You're most likely right about the comment in the config. Thank you so much for all your responses.

I'm not sure I'm seeing the same as you? Are you saying that your SCR preview appears correct for you? What size is COL? I'm not sure I have this?

With

$imagemagick_preserve_profiles=true;

THM = unmanaged (washed-out, no profile)
SCR = unmanaged (washed-out, no profile)
LPR = managed --> DCam3 profile preserved

With

$imagemagick_preserve_profiles=false;

THM = unmanaged (washed-out, no profile)
SCR = unmanaged (washed-out, no profile)
LPR = unmanaged (washed-out, no profile)


I do actually want;

$imagemagick_preserve_profiles=false;

As I want all previews converted to sRGB, and only the original to have the profile embedded. The previews are for display and possibly for inclusion in presentation material, so having them as sRGB is ideal.


Thanks so much for all your help with this! I guess I may have to revert to an older version of ResourceSpace to get this working for us in the meantime.

thanks again,

Tristan.

Electric Art

unread,
Jul 24, 2013, 1:55:14 AM7/24/13
to resour...@googlegroups.com
Fingers crossed indeed! Thanks so much Jeff!

Electric Art

unread,
Jul 24, 2013, 2:00:25 AM7/24/13
to resour...@googlegroups.com
Hey Jeff,

What do you think about my code for PSB handling? I think I would need to edit it slightly to handle PSDs as well. It fixes the problem with multiple ICCs being extracted from PSDs/PSBs, which in our setup, will be added via Staticsync in the next run - very problematic when we've got thousands of PSDs and PSBs - all those extra files will get very annoying very quickly! :)

Do you know if the code I have written bypasses the ICC code? Do you know how I might modify it to ensure it doesn't bypass it?

thanks,
Tristan.
icc_profiles_staticsync.jpg

Jeff Harmon

unread,
Jul 24, 2013, 2:20:30 AM7/24/13
to resour...@googlegroups.com, resour...@googlegroups.com
All good!

I was reporting that the larger image worked perfectly, and the smaller image had bad COL and THMs, with the preserve profiles set to true. You too?

Jeff

--
Jeff Harmon
Chief Executive Officer
Colorhythm LLC

Main Office:  +1 415-399-9921
Mobile:  +1 510-710-9590

Electric Art

unread,
Jul 24, 2013, 2:50:25 AM7/24/13
to resour...@googlegroups.com
Hi Jeff,

No sorry, for me with preserve profiles set to true I get bad COL, THM - as well as bad SCR/Preview. Larger image (which is download only and not previewed in any way) has the correct profile embedded - that part is correct behaviour I believe, but unfortunately not what I need.

With preserve profiles set to false I get bad everything! :)

Tristan.

Electric Art

unread,
Jul 24, 2013, 4:23:01 AM7/24/13
to resour...@googlegroups.com
Hey Jeff,

I'm very happy to say that I've fixed this issue and all my test so far reproduce the expected behaviour!

Here is the code that I used;

                                # EXPERIMENTAL CODE TO USE EXISTING ICC PROFILE IF PRESENT
                                global $icc_extraction, $icc_preview_profile, $icc_preview_options, $ffmpeg_supported_extensions;
                                if($imagemagick_preserve_profiles && $id!="thm" && $id!="col" && $id!="pre" && $id!="scr"){
                                        // Preserve embedded source profile for larger sizes.
                                        $profile="-profile \"*\" -colorspace ".$imagemagick_colorspace;
                                } else {
                                        // Preserve embedded source profile then convert to sRGB. Strip sRGB profile from resulting file to save space.
                                        $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
                                        $profile  = "$icc_preview_options -profile $targetprofile +profile \"*\" ";
                                }

This code replaces lines 891 to 915 on the current SVN build of 4659.

The behaviour for my code is as below;

With;

$imagemagick_preserve_profiles=false;

The embedded profile (if there is one) is preserved and used to convert to the destination profile (as specified by $icc_preview_profile in config.php) for all sizes. The profile is then stripped from the resulting file.

With;

$imagemagick_preserve_profiles=true;

The embedded profile (if there is one) is preserved and retained for images larger than SCR (screen sized preview)
The embedded profile (if there is one) is preserved and used to convert to the destination profile (as specified by $icc_preview_profile in config.php) for THM (Thumbnail), SCR (Screen preview) and COL (Collection Thumbnail). The profile is then stripped from the resulting file.


$icc_extraction = true; ----> This configuration option is depreciated and removed as it is actually not necessary for colour management by ImageMagick. This also helps to make the code less complicated as all code for ICC extraction is removed.


This code also fixes the multiple ICC extraction issue, as the extraction code is removed (as it is not needed for correct operation). It also should increase the speed of preview generation, as in the cleanup of code I have removed unnecessary colour space conversions that were going on.

It is also likely possible that the $imagemagick_colorspace can also be removed, as by default, ImageMagick assumes non-linear sRGB (which, for all use cases I can think likely for ResourceSpace is the best choice). By removing this option, it could be potentially easier for configuration, as this would not need to be set explicitly depending upon which version of ImageMagick is installed (and would stop people from running into the dreaded 'dark previews' problem without having any additional configuration. I have to do some more testing, but my guess is that this option and the code referencing it can likely be removed altogether.


Please let me know if you get a chance to test. For me, it fixes all issues I was having, both with colour management and the multiple ICC issue. I have focused my testing on TIFF, JPEG, PSD and PSB files though - please let me know if this causes any problems for you for InDesign files or such.

Thanks again for all your help!

If this does test ok, how would one go about trying to get it integrated into the ResourceSpace code?

Tristan.

Electric Art

unread,
Jul 24, 2013, 4:47:54 AM7/24/13
to resour...@googlegroups.com
Hey Jeff,

I've modified the code a bit more - here's the new code;


    # EXPERIMENTAL CODE TO USE EXISTING ICC PROFILE IF PRESENT
    global $icc_extraction, $icc_preview_profile, $icc_preview_options, $ffmpeg_supported_extensions;
    if($imagemagick_preserve_profiles && $id!="thm" && $id!="col" && $id!="pre" && $id!="scr"){
        // Preserve embedded source profile for larger sizes.
            $profile="";

        } else {
            // Preserve embedded source profile then convert to sRGB. Strip sRGB profile from resulting file to save space.
            $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
            $profile  = "$icc_preview_options -profile $targetprofile +profile \"*\" ";
       }


The new code removes the reference to $imagemagick_colorspace as this is not required. Default behaviour from ImageMagick is to assume a non-linear tonal response curve - which is what we want. Reference here;

http://www.imagemagick.org/script/color-management.php

I can confirm that this works fine with both ImageMagick versions before 6.7.6-4 as well as ImageMagick version 6.7.6-4 and newer. GraphicsMagick currently untested, but I'm thinking it will work.

My next step will be to re-write the code to allow an option to preserve profiles for previews that have been converted to sRGB, so that if people are happy for the extra space (4k per image) to be taken up to ensure good colour management policies are enforced, they will have the option to do so.

Let me know what you think.

Tristan.

Electric Art

unread,
Jul 24, 2013, 5:50:14 AM7/24/13
to resour...@googlegroups.com
Hi again,

So I've done some more research and testing, and I may need to revisit this code to make it more backward-compatible. It seems that this code will work perfectly with versions of ImageMagick newer than 6.7.1-0. Versions after 6.7.1-0 assume a non-linear tonal response curve for untagged images. Versions before 6.7.1-0 assume a linear tonal response curve for untagged images, which will result in incorrect previews for *untagged* images only. Tagged images will still convert correctly.

My reference for this is here;

http://www.imagemagick.org/discourse-server/viewtopic.php?t=19033&p=74114

I'll look to re-writing the code to make it more backward compatible and post an update as soon as I can.

Tristan.

Jeff Harmon

unread,
Jul 24, 2013, 8:11:02 PM7/24/13
to ResourceSpace
When you run the +profile command, that removes all profiles, not just ICC.


I believe we need +profile "profile name" or +profile icc

We have tested this with CMYK, Lab, RGB of different flavors, and it appears to work!  We'll commit to base once we hear from you and have tested this even more thoroughly.

I agree with you about enhancements.  For one, the ability to retain the embedded sRGB profile in previews.  That might work better in some conditions.  (It's also a precursor to #2 below)

Secondly, if you want a true soft proofing platform, we need two other major additions that are quite achievable:

1)  Be able to set in config the profiles to be assumed for untagged imagery in different colorspaces.  This would act similarly to the workspaces concept in Adobe products.

2)  Allow the creation of previews WITHOUT color conversion, and with retention of the original, embedded ICC profile.  With such an advancement, we could support soft proofing of Adobe RGB and other non-sRGB spaces in the browser (for Firefox with full color management on and Safari, at least).  This enhancement would require fully color managed browsers to work properly, but for those of us who are imaging professionals would offer true soft proofing.

If you're game, we could develop this together!  Rock on!!

Jeff

Electric Art

unread,
Jul 25, 2013, 6:21:55 AM7/25/13
to resour...@googlegroups.com
Hey Jeff,

I've been working on this a fair bit and almost have a solution ready to test. I won't get a chance to work on it again till next week, but will post what I have then. I've almost got all the functionality required working, just having some trouble with assigning profiles to untagged images. But almost there!

Tristan.

Electric Art

unread,
Jul 25, 2013, 7:07:00 AM7/25/13
to resour...@googlegroups.com
The part of the code I can't seem to get to work is this;

(in image_processing.php)

// Assign profile for untagged CMYK images
if (!$icc_profile && $colourspace="CMYK" && $untagged_cmyk_profile){
        $untagged_cmyk_profile = dirname(__FILE__) . '/../iccprofiles/' . $untagged_cmyk_profile;
        $assign_profile=run_command($convert_fullpath.' '.escapeshellarg($path).' -set profile $untagged_cmyk_profile '.escapeshellarg($path));
    }


Where;

$untagged_cmyk_profile = 'ISOcoated_v2_300_bas.ICC';

In my config.php

I don't think that part of the code is working properly but I can't seem to figure out why. It might be something fairly obvious as I'm no PHP coder. If anything sticks out to you, please let me know!

According to the ImageMagick documentation, this is how assigning a profile should work;

$ convert image.psd -set profile ISOcoated_v2_eci.icc image-icc.psd

This works for me on the command line, but when I try to do it in image_processing.php, I can't seem to get it to work... Any ideas?

Reference here - http://www.imagemagick.org/script/command-line-options.php#set

I also tried this (with no luck);

// Assign profile for untagged CMYK images
if (!$icc_profile && $colourspace="CMYK"){
                $mogrify_fullpath = get_utility_path("im-mogrify");
                $target_profile = dirname(__FILE__) . '/../iccprofiles/' . $untagged_cmyk_profile;
                $assign_profile=run_command($mogrify_fullpath.' -set profile $target_profile '.escapeshellarg($path));
        }


Any help on this would be greatly appreciated! Thanks!

Tristan.

Søren Grønning Iversen

unread,
Jul 25, 2013, 10:51:32 AM7/25/13
to resour...@googlegroups.com
Have you tried changing:

$colourspace="CMYK"

to:

$colourspace=="CMYK"

$colourspace="CMYK" would assign the value "CMYK" to the variable $colourspace, whereas $colourspace=="CMYK" in context of the 'if' statement would check if the value of $colourspace is actually equal to "CMYK" . . . Basically, it seems that no comparison is made.

Best regards,

Søren G.

Jeff Harmon

unread,
Jul 25, 2013, 12:49:20 PM7/25/13
to resour...@googlegroups.com, resour...@googlegroups.com
How are you getting the color space?  Identify?  ExifTool?

xmp:colormode is very reliable. We need to support Lab color, for sure.

Also, for profiles, Adobe offers some to bundle in software, and LCMS and the ICC themselves also offer profiles free to use. 

Jeff

--
Jeff Harmon
Chief Executive Officer
Colorhythm LLC

Main Office:  +1 415-399-9921
Mobile:  +1 510-710-9590

Jeff Harmon

unread,
Jul 25, 2013, 12:50:25 PM7/25/13
to resour...@googlegroups.com
Also, ExifTool can embed and remove ICC profiles and may be significantly faster. 


--
Jeff Harmon
Chief Executive Officer
Colorhythm LLC

Main Office:  +1 415-399-9921
Mobile:  +1 510-710-9590

Electric Art

unread,
Jul 30, 2013, 4:08:05 AM7/30/13
to resour...@googlegroups.com
Hi Søren,

Thanks so much for that - I missed that one!

Tristan.
...

Electric Art

unread,
Jul 30, 2013, 4:12:38 AM7/30/13
to resour...@googlegroups.com
Hi Jeff,

I've almost finished the new code. I've done some preliminary testing (which looks promising) and I will have something to post soon.

My only issue with it now is that the behaviour of the new code will modify the original file to tag it with a profile if it is untagged. This is maybe not a big issue, however if you are using Staticsync (as we are), it means that the original resource is modified when the ICC profile is added. This of course only happens with untagged files (which for us, is only a handful). Ideally I'd like to not affect the original resource, and I'm looking into how to do this, and I think it involves some more coding work in preview_preprocessing.php - hopefully I'll have some time to look at this but unfortunately I'm quickly running out of time for this at the moment!

I'll make another post tomorrow (fingers-crossed) with my new code.

Tristan.

Jeff Harmon

unread,
Jul 30, 2013, 12:07:05 PM7/30/13
to resour...@googlegroups.com, resour...@googlegroups.com
You would be breaking a cardinal rule. In RS, we never - other than hashing its filename - edit the original file. We always copy it first. Try to avoid editing the original at all costs.  Perhaps you can tag the image as its piped through memory? That would probably be too RAM intensive. This will take some thinking!  Maybe we can figure it out if you're out of time. 

Thanks so much for your work!!!!

Jeff

--
Jeff Harmon
Chief Executive Officer
Colorhythm LLC

Main Office:  +1 415-399-9921
Mobile:  +1 510-710-9590

Electric Art

unread,
Jul 30, 2013, 10:37:53 PM7/30/13
to resour...@googlegroups.com
Hey Jeff,

Yep I thought as much. I'm not too sure where or how to attempt to make a copy of the file. There seems to be lots of places and ways to do it in the code and frankly I'm a little bit lost in it all. The easiest solution I could come up with is that Exiftool automatically creates a backup, and I think I could change my code to restore the backup of the original file after the previews had been generated? That's probably a bit backwards and not so ideal as the original file is still changed, but then restored.

Well, here's what I have so far anyway. Maybe this could give you some ideas. In digging around in the code in preview_preprocessing.php, I've noticed there are some other changes that would need to be made to make sure colour management is effective system wide, however this code for image_processing.php is a start;

/* ----------------------------------------
    Colour Management section.
    Requires Exiftool and ImageMagick
    (GraphicsMagick is compatible however
    all functions may not work correctly)
   ----------------------------------------
*/

// Check if colour management is enabled
global $colour_management
if($colour_management){
   
global $imagemagick_path, $exiftool_path, $untagged_rgb_profile, $untagged_cmyk_profile, $untagged_lab_profile, $untagged_gray_profile, $tonal_response_curve, $tonal_response_curve_compatibility, $tonal_response_curve_compatibility_options, $preserve_source_profiles, $preserve_target_profiles, $preserve_source_profiles_large_only, $icc_preview_profile, $icc_preview_options, $ffmpeg_supported_extensions;
   
/* ----------------------------------------
    This section determines information about
    the file including colour mode and if it
    has an ICC profile or not
   ----------------------------------------
*/

// Locate Exiftool
$exiftool_fullpath = get_utility_path("exiftool");
if ($exiftool_fullpath==false){
    // Exiftool not found, exit
    exit("Could not find Exiftool utility at location '$exiftool_path'.");
    } else {
        // Determine ICC profile of image (if exist) using Exiftool
        $icc_profile=run_command($exiftool_fullpath.' -profiledescription '.escapeshellarg($file));
    }

// Locate ImageMagick
$convert_fullpath = get_utility_path("im-convert");
if ($convert_fullpath==false){
    // ImageMagick not found, exit
    exit("Could not find ImageMagick 'convert' utility at location '$imagemagick_path'.");
    } else {
        // Determine colour mode of image
        $colourspace=run_command($convert_fullpath.' '.escapeshellarg($file).' -print "%[colorspace]\n" null:');
    }
   
/* ----------------------------------------
    This section determines the appropriate
    setting for ImageMagick/GraphicsMagick
    for handling of tonal response curves
   ----------------------------------------
*/
   
// If GraphicsMagick or Imagemagick v6.7.6-3 or earlier is being used, set appropriate colourspace option.
// In each case, the setting will tell ImageMagick or GraphicsMagick to assume a non-linear (sRGB) tonal response curve when converting.
if ($tonal_response_curve_compatibility){
        // Set 'RGB' for compatibility for GraphicsMagick or ImageMagick v6.7.6-3 or earlier
        $tonal_response_curve_compatibility_options="RGB";
        } else {
            // Set 'sRGB' for ImageMagick v6.7.6-4 or newer
            $tonal_response_curve_compatibility_options="sRGB";
    }
   
/* ----------------------------------------
    This section handles assigning ICC profiles
    to untagged images. Profiles are assigned
    dependent upon colour mode and the profiles
    defined in config.php
   ----------------------------------------
*/
   
// Assign profile for untagged RGB images
if (!$icc_profile && $colourspace=="sRGB" && (isset($untagged_rgb_profile))){
        $target_rgb_profile = dirname(__FILE__) . '/../iccprofiles/' . $untagged_rgb_profile;
        $assign_profile=run_command($exiftool_fullpath.' "-icc_profile<='.$target_rgb_profile.'" '.escapeshellarg($file));
        if (file_exists($file.'_original')){
            $delete_exif_backup=run_command($exiftool_fullpath.' -delete_original! '.escapeshellarg($file));
        }
    }
   
// Assign profile for untagged RGB images (Compatibility for GraphicsMagick or ImageMagick v6.7.6-3 or earlier)
if (!$icc_profile && $tonal_response_curve_compatibility && $colourspace=="RGB" && (isset($untagged_rgb_profile))){
        $target_rgb_profile = dirname(__FILE__) . '/../iccprofiles/' . $untagged_rgb_profile;
        $assign_profile=run_command($exiftool_fullpath.' "-icc_profile<='.$target_rgb_profile.'" '.escapeshellarg($file));
        if (file_exists($file.'_original')){
            $delete_exif_backup=run_command($exiftool_fullpath.' -delete_original! '.escapeshellarg($file));

        }
    }
   
// Assign profile for untagged CMYK images
if (!$icc_profile && $colourspace=="CMYK" && (isset($untagged_cmyk_profile))){
        $target_cmyk_profile = dirname(__FILE__) . '/../iccprofiles/' . $untagged_cmyk_profile;
        $assign_profile=run_command($exiftool_fullpath.' "-icc_profile<='.$target_cmyk_profile.'" '.escapeshellarg($file));
        if (file_exists($file.'_original')){
            $delete_exif_backup=run_command($exiftool_fullpath.' -delete_original! '.escapeshellarg($file));
        }
    }
   
// Assign profile for untagged LAB images
if (!$icc_profile && $colourspace=="LAB" && (isset($untagged_lab_profile))){
        $target_lab_profile = dirname(__FILE__) . '/../iccprofiles/' . $untagged_lab_profile;
        $assign_profile=run_command($exiftool_fullpath.' "-icc_profile<='.$target_lab_profile.'" '.escapeshellarg($file));
        if (file_exists($file.'_original')){
            $delete_exif_backup=run_command($exiftool_fullpath.' -delete_original! '.escapeshellarg($file));
        }
    }
   
// Assign profile for untagged grayscale images
if (!$icc_profile && $colourspace=="gray" && (isset($untagged_gray_profile))){
        $target_gray_profile = dirname(__FILE__) . '/../iccprofiles/' . $untagged_gray_profile;
        $assign_profile=run_command($exiftool_fullpath.' "-icc_profile<='.$target_gray_profile.'" '.escapeshellarg($file));
        if (file_exists($file.'_original')){
            $delete_exif_backup=run_command($exiftool_fullpath.' -delete_original! '.escapeshellarg($file));
        }
    }
   
/* ----------------------------------------
    This section determines behaviour of
    colour space conversion and preservation
    of ICC profiles after conversion.
   ----------------------------------------
*/

    // If $preserve_source_profiles=true;
    if($preserve_source_profiles){
        // Preserve the embedded source profile for all sizes. No conversion will take place.
        $profile="";
    }
   
    // If $preserve_source_profiles_large_only=true; then for sizes larger than 'scr', the embedded source profile will be preserved and no conversion will take place.
    if($preserve_source_profiles_large_only && $id!="thm" && $id!="col" && $id!="pre" && $id!="scr"){
        // Preserve embedded source profile for larger sizes only.
        $profile="";
    }
   
    // If $preserve_source_profiles_large_only=true; then 'scr' sizes and smaller will be converted to the target profile specified. Strip ICC profile to save space.
    if($preserve_source_profiles_large_only && $id=="thm" && $id=="col" && $id=="pre" && $id=="scr"){
        // Preserve embedded source profile for larger sizes only.
        $profile="-colorspace $tonal_response_curve_compatibility_options $icc_preview_options -profile $targetprofile +profile icc";
    }
   
    // If $preserve_source_profiles_large_only=true; then 'scr' sizes and smaller will be converted to the target profile specified. Preserve target profile.
    if($preserve_source_profiles_large_only && $id=="thm" && $id=="col" && $id=="pre" && $id=="scr" && $preserve_target_profiles){
        // Preserve embedded source profile for larger sizes only.
        $profile="-colorspace $tonal_response_curve_compatibility_options $icc_preview_options -profile $targetprofile";
    }
   
    // If $preserve_target_profiles=true;
    if($preserve_target_profiles && !$preserve_source_profiles && !$preserve_source_profiles_large_only){
        // Preserve the embedded source profile then convert to target profile. Preserve target profile.

        $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
        $profile  = "-colorspace $tonal_response_curve_compatibility_options $icc_preview_options -profile $targetprofile";
    }
   
    // If $preserve_target_profiles=false;
    if(!$preserve_target_profiles && !$preserve_source_profiles && !$preserve_source_profiles_large_only){
        // Preserve the embedded source profile then convert to target profile. Preserve target profile.

        $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
        $profile  = "-colorspace $tonal_response_curve_compatibility_options $icc_preview_options -profile $targetprofile +profile icc";
    }
   
    } else {
        /* ----------------------------------------
            This section is the default behaviour
            for ResourceSpace when colour management
            is turned off. The embedded profile (if
            it exists) is used, then the file is
            converted to the target ICC profile
            specified in config.php. The profile is
            then stripped from the generated previews
            to save space.
               ----------------------------------------
        */
       
        // Convert image to target profile as set by $icc_preview_profile. Strip ICC profile to save space.

        $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
        $profile  = "-colorspace $tonal_response_curve_compatibility_options $icc_preview_options -profile $targetprofile +profile icc";
    }


And the relevant stuff for config.php

# ICC Colour Management Features (Experimental)
# Requires Exiftool and either Imagemagick or GraphicsMagick where Imagemagick is preferred
# Note that ImageMagick must be installed with LCMS or LCMS2 support
# Uncomment below to activate colour management
$colour_management=true;

# Defining profiles for untagged images here will enable tagging for any untagged image of that colour mode (RGB, CMYK, Lab, Gray)
# Be aware that original files will be modified in this process to tag them. If using Staticsync, please note this as your original file resource will be modified to add the ICC profile.
# Colour profiles for preview generation must be located in the /iccprofiles folder of Resourcespace
# High quality CMYK offset printing profiles may be freely downloaded from http://colormanagement.org/
$untagged_rgb_profile = 'sRGB_IEC61966-2-1_black_scaled.icc';
$untagged_cmyk_profile = 'ISOcoated_v2_bas.ICC';
$untagged_lab_profile = '';
$untagged_grayscale_profile = 'ISOcoated_v2_grey1c_bas.ICC';

# This target profile will be used for the conversion and but is discarded unless $preserve_target_profiles=true;
# In almost all cases, this should be set to 'sRGB_IEC61966-2-1_black_scaled.icc'
$icc_preview_profile = 'sRGB_IEC61966-2-1_black_scaled.icc';

# Additional options for profile conversion during preview generation

$icc_preview_options = '-intent relative -black-point-compensation';

# Uncomment ONLY if using GraphicsMagick or ImageMagick 6.7.1-0 or older.
# Setting $tonal_response_curve_compatibility=true; forces ImageMagick to check the colour mode before proceeding so as to use the correct tonal response curve when converting the image.
#$tonal_response_curve_compatibility=true;

# With $preserve_source_profiles=true;, source profiles are preserved for all files tagged with an ICC profile. No ICC colour space conversions are made.
# This option requires a colour managed browser with colour management turned on for correct display of preview images and thumbnails. E.g. Safari 2.0+, Chrome 22.0+, Firefox 3.6+ (ICC v2, v4 with manual config), Opera 12.10+
# Check browser compatibility here - http://www.color.org/version4html.xalter
#$preserve_source_profiles=true;

# With $preserve_source_profiles_large_only=true;, only Thumbnails, Screen resolution previews and Collection Thumbnails are converted to the target profile set by $icc_preview_profile. All other file sizes retain the original source profile.
#$preserve_source_profiles_large_only=true;

# Set $preserve_target_profiles=true; to ensure that images which have been converted to the target profile set by $icc_preview_profile preserve the target profile after conversion.
# If the target profile set in $icc_preview_profile is NOT sRGB IEC61966-2.1 then this setting is required for properly colour managed images. A colour managed browser is also required (see comments for $preserve_source_profiles=true; for details about browsers).
# If the target profile set in $icc_preview_profile is sRGB IEC61966-2.1 then, dependent upon browser behaviour, this setting may still be required for properly colour managed images (with the safest assumption to be that it IS required).
# Enabling this setting will add to the preview file size (approximately 4k per image).
$preserve_target_profiles=true;



Please note this code is currently untested. I'm going to do some testing today. The only part really which causes a problem for me at the moment that I haven't been able to solve is assigning profiles to untagged images, and only for the reason that it will currently modify the original file. If we could get around that, then I think we may have something...

Let me know what you think. Be gentle, I'm not a programmer! :)

Thanks,
Tristan.

Jeff Harmon

unread,
Jul 30, 2013, 11:37:04 PM7/30/13
to resour...@googlegroups.com, resour...@googlegroups.com
You only have to apply the profile when making previews. There's no need to store or embed the profile in the original. 

Jeff

--
Jeff Harmon
Chief Executive Officer
Colorhythm LLC

Main Office:  +1 415-399-9921
Mobile:  +1 510-710-9590

Electric Art

unread,
Jul 30, 2013, 11:56:51 PM7/30/13
to resour...@googlegroups.com
Hey Jeff,

Absolutely agree with you. I'd rather just be doing it that way, however I can't work out an easy way to do that yet unfortunately.

Still working on it... but may run out of time soon unfortunately.

Tristan.

Electric Art

unread,
Jul 31, 2013, 12:24:40 AM7/31/13
to resour...@googlegroups.com
Hey Jeff I think I've solved it. :)

Will get back to you shortly.

Tristan.

Jeff Harmon

unread,
Jul 31, 2013, 1:54:59 AM7/31/13
to resour...@googlegroups.com, resour...@googlegroups.com
So awesome!!!   Rooting for you!!!

Jeff

--
Jeff Harmon
Chief Executive Officer
Colorhythm LLC

Main Office:  +1 415-399-9921
Mobile:  +1 510-710-9590

Electric Art

unread,
Jul 31, 2013, 4:50:32 AM7/31/13
to resour...@googlegroups.com
Hey Jeff,

Just an update. I've almost got it. The code is looking (and working) much better now. However it's developed a strange problem that seems to only affect PSD and PSB files. Not sure what is happening. Once I get to the bottom of that, I'll post the updated code and see if maybe you might be able to test it as well?

Tristan.

Jeff Harmon

unread,
Jul 31, 2013, 12:47:00 PM7/31/13
to resour...@googlegroups.com
What kind of problem?  You do have to flatten and handle alphas before conversion. 

Jeff

--
Jeff Harmon
Chief Executive Officer
Colorhythm LLC

Main Office:  +1 415-399-9921
Mobile:  +1 510-710-9590

Jeff Harmon

unread,
Aug 1, 2013, 2:50:01 AM8/1/13
to resour...@googlegroups.com, resour...@googlegroups.com
Just to add a small crazy spin into a fast moving  weave, there are EXIF tags that are now reliably interpreted as profile indicators and actually so reliable that files with such tags open as having an embedded profile and are automatically assigned the profile by Adobe Photoshop!

So, if exif:colorspace="sRGB" we can proceed as if that file were sRGB.  Also if exif:interopindex= "R98 - DCF basic file (sRGB)," that indicates sRGB. 

However, if exif:colorspace="Uncalibrated" then we look at exif:interopindex to see if it says "R03 - DCF option file (Adobe RGB)," which indicates an Adobe RGB file.

See ExifTool's notes below:


ColorSpace:
(the value of "Adobe RGB" is not standard EXIF. Instead, an Adobe RGB image is indicated by "Uncalibrated" with an InteropIndex of "R03". The values Wide Gamut RGB and ICC Profile are also non-standard, and are used by some Sony cameras)

sRGB 
Adobe RGB 
Wide Gamut RGB 
ICC Profile 
Uncalibrated

InteropIndex:
R03 - DCF option file (Adobe RGB) 
R98 - DCF basic file (sRGB) 
THM - DCF thumbnail file

http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html


As arcane as this all looks, this algorithm above is very routine for software that deals with raw photography or the JPEGs created from it. 

If we really only on actually embedded ICC profiles, we will have gone very, very far but would still frustrate a lot of photographers!

I say this all with much gratitude for everything you shared, somewhat sheepishly trying to contribute what I can!

Jeff


--
Jeff Harmon
Chief Executive Officer
Colorhythm LLC

Main Office:  +1 415-399-9921
Mobile:  +1 510-710-9590

Electric Art

unread,
Aug 1, 2013, 4:26:20 AM8/1/13
to resour...@googlegroups.com
Hey Jeff,

The problem was a bizarre one indeed. It has something to do with the way ImageMagick handles PSD and PSB files specifically. Basically, it was converting to the target profile (in my test case, sRGB_IEC61966-2-1_black_scaled.icc), however it wasn't properly embedding the profile, and when the file was opened in Photoshop, Photoshop would assume the original source profile (which was still embedded in there somehow even though the conversion had taken place to sRGB_IEC61966-2-1_black_scaled.icc), resulting in extremely saturated and incorrect colours. To make matters worse, this effect was compounded (as smaller previews are generated from the HPR high res preview). The effect was similar to opening the original in Photoshop, converting to sRGB_IEC61966-2-1_black_scaled.icc, then (incorrectly) assigning the original source profile. For the screen res preview and thumbs, it was equivalent to doing that twice! In MacOS Preview and Quicklook, the HPR looked ok, because it somehow ignored the 'hidden' profile information Photoshop found.

After hours and hours of testing, the only reliable way I could make a conversion using a PSD/PSB file with an embedded profile to sRGB_IEC61966-2-1_black_scaled.icc, was to extract the profile (as per a modified version of the old ICC code), strip the profile (using * as ic* or icc in this case did NOT work), then assign the extracted profile before finally converting to sRGB_IEC61966-2-1_black_scaled.icc. Once I had that working on the command line just with ImageMagick, I was able to move forward and get it happening in ResourceSpace... Finally just solved it so I can move onto some proper testing!

Electric Art

unread,
Aug 1, 2013, 4:37:18 AM8/1/13
to resour...@googlegroups.com
Hey Jeff!

Thanks - that looks quite useful indeed! I'm a little confused as to what the information indicates? I.e. does the EXIF data potentially tell us for example that the file is in AdobeRGB yet it may not have a profile embedded? If that is the case, then I could probably add something to the code that handles assigning profiles so as to look for this EXIF information and assigns the corresponding profile - e.g. AdobeRGB or Wide Gamut RGB or sRGB as appropriate - however these would need to be installed in the ResourceSpace /iccprofiles directory for this to work... Is that what you were hoping for?

Tristan.

Electric Art

unread,
Aug 1, 2013, 4:38:54 AM8/1/13
to resour...@googlegroups.com
Just wondering - do you have any example files for this?

Tristan.

Jeff Harmon

unread,
Aug 1, 2013, 5:56:17 AM8/1/13
to resour...@googlegroups.com
That is correct. This information is used by cameras and raw processing engines instead of embedding profiles. And yes, Photoshop acts as though such a file has an embedded profile. 

The goal would not be the assignment per se but the intelligent assignment in converting to the preview color space (typically sRGB).  

Jeff

--
Jeff Harmon
Chief Executive Officer
Colorhythm LLC

Main Office:  +1 415-399-9921
Mobile:  +1 510-710-9590

Jeff Harmon

unread,
Aug 1, 2013, 5:56:55 AM8/1/13
to resour...@googlegroups.com
I do.  Will send soon. 

J


--
Jeff Harmon
Chief Executive Officer
Colorhythm LLC

Main Office:  +1 415-399-9921
Mobile:  +1 510-710-9590

Jeff Harmon

unread,
Aug 2, 2013, 4:45:55 PM8/2/13
to resour...@googlegroups.com
I think we can use these profiles:


The license is permissive, aside from the caveat that we not use the "Adobe RGB (1998)" trademark, and we do not expose ICC profile names in our software, so I think we are safe.  I wouldn't mind someone else reviewing the terms though!

Other source:




Electric Art

unread,
Aug 6, 2013, 4:17:25 AM8/6/13
to resour...@googlegroups.com
Hey Jeff,

I've pretty much got the code to a finished state now (I hope). I'm yet to do more hardcore testing, however everything (at least for my purposes, works correctly at the moment).

So left on the TO DO list is the automatic removal of extracted ICC profiles from PSDs/PSBs after conversion, and check how it operates with other parts of the code.

Currently untested is;

* Image uploads (I'm using Staticsync)
* Watermarked and alternate images
* GraphicsMagick / ImageMagick v6.7.6-3 or earlier compatibility (though the code should support this)

What we should have though is code that will (depending upon settings defined by the user);

* Use embedded profiles and convert to a target profile, then either keeping the target profile or removing it as defined by the user
* Use embedded profiles and only convert the non high resolution previews to the target profile, preserving the embedded profile for larger sizes
* Preserve the embedded profiles for all previews
* Auto-assign certain common pre-defined profiles based upon EXIF tag information (thanks so much Jeff for the suggestion and solution for that one) before conversion to the target profile
* Assign user defined profiles in the absence of an embedded profile and failure of the auto-assign to find an appropriate profile
* Optionally perform the image resize commands in a linear space for more accurate colour (see http://www.imagemagick.org/Usage/resize/#resize_colorspace ) - I've tested this and it does make a difference - sometimes significant depending upon the image
* Correctly convert files that are in a linear space (e.g. EXR, HDR) to the target profile for correct display


So, the code is not thoroughly tested, however it appears to work correctly for how I would be using it (so far). Here is what I have;

In config.php add the following (this replaces any other colour management related settings in config.php);

# ICC Colour Management Features (Experimental)
# Requires Exiftool and either Imagemagick or GraphicsMagick where ImageMagick is preferred

# Note that ImageMagick must be installed with LCMS or LCMS2 support
# Uncomment below to activate colour management
$colour_management=true;

# If $assign_profiles_to_untagged_images=true;, defining profiles for untagged images here will enable tagging for any untagged image of the corresponding colour mode (RGB, CMYK, Lab, Gray)
# Profiles must exist in the /iccprofiles directory of ResourceSpace for this to function and, apart from sRGB, are NOT included in the default installation.

# High quality CMYK offset printing profiles may be freely downloaded from http://colormanagement.org/
$assign_profiles_to_untagged_images=true;

$untagged_rgb_profile = 'sRGB_IEC61966-2-1_black_scaled.icc';
$untagged_cmyk_profile = 'ISOcoated_v2_bas.ICC';
$untagged_lab_profile = '';
$untagged_grayscale_profile = 'ISOcoated_v2_grey1c_bas.ICC';

# Turning on auto assigning of profiles will use Exiftool to check JPEG or TIFF captures from digital cameras to see if they indicate a profile in EXIF tags but do not have a profile embedded.
# Profiles are then assigned based upon the definitions below.
# Profiles must exist in the /iccprofiles directory of ResourceSpace for this to function and, apart from sRGB, are NOT included in the default installation.
# Some of these profiles may be downloadable from http://www.adobe.com/support/downloads/detail.jsp?ftpID=4076
# and http://color.org/profiles.xalter
# NOTE that $assign_profiles_to_untagged_images must be set to true for this section to apply
$auto_assign_based_on_exif_tags=true;
$default_srgb_profile = 'sRGB_IEC61966-2-1_black_scaled.icc';
$default_widegamut_profile = 'WideGamutRGB.icc';
$default_adobergb_profile = 'AdobeRGB1998.icc';

# This target profile will be used for the conversion for display but is discarded after conversion unless $preserve_target_profiles=true;

# In almost all cases, this should be set to 'sRGB_IEC61966-2-1_black_scaled.icc'
$icc_preview_profile = 'sRGB_IEC61966-2-1_black_scaled.icc';

# Additional options for profile conversion during preview generation

$icc_preview_options = '-intent relative -black-point-compensation';

# With $linear_resize=true;, ResourceSpace will tell ImageMagick/GraphicsMagick to convert the file to a linear tonal response curve before performing the resize operation. This ensures more accurate colour during resizing.
# See http://www.imagemagick.org/Usage/resize/#resize_colorspace
$linear_resize=true;


# Uncomment ONLY if using GraphicsMagick or ImageMagick 6.7.1-0 or older.
# Setting $tonal_response_curve_compatibility=true; forces ImageMagick to check the colour mode before proceeding so as to use the correct tonal response curve when converting the image.
#$tonal_response_curve_compatibility=true;

# With $preserve_source_profiles=true;, source profiles are preserved for all files tagged with an ICC profile. No ICC colour space conversions are made.
# This option requires a colour managed browser with colour management turned on for correct display of preview images and thumbnails. E.g. Safari 2.0+, Chrome 22.0+, Firefox 3.6+ (ICC v2, v4 with manual config), Opera 12.10+
# Check browser compatibility here - http://www.color.org/version4html.xalter
#$preserve_source_profiles=true;

# With $preserve_source_profiles_large_only=true;, only Thumbnails, Screen resolution previews and Collection Thumbnails are converted to the target profile set by $icc_preview_profile. All other file sizes retain the original source profile.
#$preserve_source_profiles_large_only=true;

# Set $preserve_target_profiles=true; to ensure that images which have been converted to the target profile set by $icc_preview_profile preserve the target profile after conversion.
# If the target profile set in $icc_preview_profile is NOT sRGB IEC61966-2.1 then this setting is required for properly colour managed images. A colour managed browser is also required (see comments for $preserve_source_profiles=true; for details about browsers).
# If the target profile set in $icc_preview_profile is sRGB IEC61966-2.1 then, dependent upon browser behaviour, this setting may still be required for properly colour managed images (with the safest assumption to be that it IS required).
# Enabling this setting will add to the preview file size (approximately 4k per image).
$preserve_target_profiles=true;




In image_processing.php (replacing the section labelled # EXPERIMENTAL CODE TO USE EXISTING ICC PROFILE IF PRESENT);

/* ----------------------------------------
    Colour Management section.
    Requires Exiftool and ImageMagick
    (GraphicsMagick is compatible however
    all functions may not work correctly)
   ----------------------------------------
*/

// Check if colour management is enabled
global $colour_management;
if($colour_management){
   
    global $imagemagick_path, $exiftool_path, $preserve_source_profiles, $preserve_target_profiles, $preserve_source_profiles_large_only, $assign_profiles_to_untagged_images, $tonal_response_curve_compatibility, $tonal_response_curve_compatibility_options, $assign_profile, $icc_profile, $icc_preview_profile, $icc_preview_options, $colourspace, $profile, $linear_resize, $ffmpeg_supported_extensions;

    /*  ----------------------------------------
        This section checks that a target profile
        is defined and exists. All basic functions
        of the Colour Managment section require a
        target profile to work.
       ----------------------------------------
    */
   
    if (!isset($icc_preview_profile)){
        // No target profile set, exit
        exit("No ICC target profile is set. An ICC preview profile must be set in config.php and the file exist to enable colour management.");
    } else {
        // A profile is set - check if it exists

        $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
        if (!file_exists($targetprofile)){
            exit("An ICC target profile is set however it cannot be found at the location $targetprofile. Check icc_preview_profile settings in config.php. An ICC preview profile must be set in config.php and the file exist to enable colour management.");

        }
    }
   
    /*  ----------------------------------------
        This section determines information about
        the file including colour mode and if it
        has an ICC profile or not
       ----------------------------------------
    */

    // Locate Exiftool
    $exiftool_fullpath = get_utility_path("exiftool");
    if ($exiftool_fullpath==false){
        // Exiftool not found, exit
        exit("Could not find Exiftool utility at location '$exiftool_path'.");
    } else {
        // Determine ICC profile of image (if exist) using Exiftool
        $icc_profile=run_command($exiftool_fullpath.' -profiledescription '.escapeshellarg($file));
    }

    // Locate ImageMagick
    $convert_fullpath = get_utility_path("im-convert");
    if ($convert_fullpath==false){
        // ImageMagick not found, exit
        exit("Could not find ImageMagick 'convert' utility at location '$imagemagick_path'.");
    } else {
        // Determine colour mode of image
        $colourspace=run_command($convert_fullpath.' '.escapeshellarg($file).' -print "%[colorspace]\n" null:');
    }

    // If GraphicsMagick or Imagemagick v6.7.6-3 or earlier is being used, set appropriate colourspace option.
    // In each case, this setting will tell ImageMagick or GraphicsMagick to assume a non-linear (sRGB) tonal response curve when converting if the source file is non-linear. Only needed if there is no embedded profile and no profile will be assigned.

    if ($tonal_response_curve_compatibility){
        // Set 'RGB' for compatibility for GraphicsMagick or ImageMagick v6.7.6-3 or earlier
        $tonal_response_curve_compatibility_options="RGB";
    } else {
        // Set 'sRGB' for ImageMagick v6.7.6-4 or newer
        $tonal_response_curve_compatibility_options="sRGB";
    }
   
    // Check if file has a linear tonal response curve
    if ($colourspace=="RGB" && (!$icc_profile) && !$tonal_response_curve_compatibility){
        // Tell ImageMagick it's a linear file
        $assign_profile=' -set colorspace RGB ';
    }
       
    // Check if file has a linear tonal response curve (Compatibility for GraphicsMagick or ImageMagick v6.7.6-3 or earlier)
    if ($colourspace=="sRGB" && (!$icc_profile) && $tonal_response_curve_compatibility){
        // Tell ImageMagick it's a linear file
        $assign_profile=' -set colorspace sRGB ';

    }
   
    /*  ----------------------------------------
        This section handles assigning ICC profiles
        to untagged images. Profiles are assigned
        dependent upon colour mode and the profiles
        defined in config.php
       ----------------------------------------
    */

    global $tonal_response_curve_compatibility, $assign_profiles_to_untagged_images, $colourspace, $icc_profile, $assign_profile;
   
    // Check if assigning profiles is set. Don't try to assign profiles for RAW images or video files.
    if($assign_profiles_to_untagged_images && !$icc_profile && !preg_match('/^(dng|nef|x3f|cr2|crw|mrw|orf|raf|dcr)$/i', $extension, $rawext) && !in_array($extension,$ffmpeg_supported_extensions)){
        global $auto_assign_based_on_exif_tags, $exiftool_fullpath, $untagged_rgb_profile, $untagged_cmyk_profile, $untagged_lab_profile, $untagged_gray_profile, $default_srgb_profile, $default_widegamut_profile, $default_adobergb_profile;

        // Attempt to automatically assign appropriate profile based upon EXIF tag information
        if ($auto_assign_based_on_exif_tags){
            // First try ColorSpace tag

            // Locate Exiftool
            $exiftool_fullpath = get_utility_path("exiftool");
            if ($exiftool_fullpath==false){
                // Exiftool not found, exit
                exit("Could not find Exiftool utility at location '$exiftool_path'.");
            } else {
                // Determine Colorspace EXIF tag of image (if exist) using Exiftool
                $exif_colorspace=run_command($exiftool_fullpath.' -ColorSpace '.escapeshellarg($file));
            }
           
            // If Exiftool returns sRGB
            if (!$assign_profile && (preg_match("/sRGB/",$exif_colorspace))){
                $target_rgb_profile = dirname(__FILE__) . '/../iccprofiles/' . $default_srgb_profile;
                // Check if profile exists
                if (!file_exists($target_rgb_profile)){
                    exit("An ICC target profile is set however it cannot be found at the location $target_rgb_profile. Check default_srgb_profile settings in config.php. An ICC preview profile must be set in config.php and the file exist to enable colour management for this file.");
                } else {
                    // Define profile to assign during conversion
                    $assign_profile=' -profile '.$target_rgb_profile;
                }
            }
           
            // If Exiftool returns Wide Gamut RGB
            if (!$assign_profile && (preg_match("/Wide Gamut RGB/",$exif_colorspace))){
                $target_rgb_profile = dirname(__FILE__) . '/../iccprofiles/' . $default_widegamut_profile;
                // Check if profile exists
                if (!file_exists($target_rgb_profile)){
                    exit("An ICC target profile is set however it cannot be found at the location $target_rgb_profile. Check default_widegamut_profile settings in config.php. An ICC preview profile must be set in config.php and the file exist to enable colour management for this file.");
                } else {
                    // Define profile to assign during conversion
                    $assign_profile=' -profile '.$target_rgb_profile;
                }
            }
           
            // If Exiftool returns Uncalibrated, check for AdobeRGB
            if (!$assign_profile && (preg_match("/Uncalibrated/",$exif_colorspace))){
                // Check InteropIndex for AdobeRGB

                $exiftool_fullpath = get_utility_path("exiftool");
                if ($exiftool_fullpath==false){
                    // Exiftool not found, exit
                    exit("Could not find Exiftool utility at location '$exiftool_path'.");
                } else {
                    // Determine InteropIndex EXIF tag of image (if exist) using Exiftool
                    $exif_interop_index=run_command($exiftool_fullpath.' -InteropIndex '.escapeshellarg($file));
                }
                if (preg_match("/Adobe RGB/",$exif_interop_index)){
                    $target_rgb_profile = dirname(__FILE__) . '/../iccprofiles/' . $default_adobergb_profile;
                    // Check if profile exists
                    if (!file_exists($target_rgb_profile)){
                        exit("An ICC target profile is set however it cannot be found at the location $target_rgb_profile. Check default_adobergb_profile settings in config.php. An ICC preview profile must be set in config.php and the file exist to enable colour management for this file.");
                    } else {
                        // Define profile to assign during conversion
                        $assign_profile=' -profile '.$target_rgb_profile;
                    }
                }
            }
        }

        // Assign profile for untagged RGB images
        if (!$assign_profile && $colourspace=="sRGB" && (isset($untagged_rgb_profile))){
            $target_rgb_profile = dirname(__FILE__) . '/../iccprofiles/' . $untagged_rgb_profile;
            // Define profile to assign during conversion
            $assign_profile=' -profile '.$target_rgb_profile;

        }
   
        // Assign profile for untagged RGB images (Compatibility for GraphicsMagick or ImageMagick v6.7.6-3 or earlier)
        if (!$assign_profile && $colourspace=="RGB" && (isset($untagged_rgb_profile)) && $tonal_response_curve_compatibility){
            $target_rgb_profile = dirname(__FILE__) . '/../iccprofiles/' . $untagged_rgb_profile;
            // Define profile to assign during conversion
            $assign_profile=' -profile '.$target_rgb_profile;

        }
   
        // Assign profile for untagged CMYK images
        if (!$assign_profile && $colourspace=="CMYK" && (isset($untagged_cmyk_profile))){
            $target_cmyk_profile = dirname(__FILE__) . '/../iccprofiles/' . $untagged_cmyk_profile;
            // Define profile to assign during conversion
            $assign_profile=' -profile '.$target_cmyk_profile;
        }
   
        // Assign profile for untagged LAB images
        if (!$assign_profile && $colourspace=="LAB" && (isset($untagged_lab_profile))){
            $target_lab_profile = dirname(__FILE__) . '/../iccprofiles/' . $untagged_lab_profile;
            // Define profile to assign during conversion
            $assign_profile=' -profile '.$target_lab_profile;
        }
   
        // Assign profile for untagged grayscale images
        if (!$assign_profile && $colourspace=="gray" && (isset($untagged_gray_profile))){
            $target_gray_profile = dirname(__FILE__) . '/../iccprofiles/' . $untagged_gray_profile;
            // Define profile to assign during conversion
            $assign_profile=' -profile '.$target_gray_profile;
        }
    } else {
        // Tell ImageMagick to explicity set -colorspace for untagged RGB images (Compatibility for GraphicsMagick or ImageMagick v6.7.6-3 or earlier)
        if (!$assign_profiles_to_untagged_images && $colourspace=="RGB" && !$icc_profile && $tonal_response_curve_compatibility){
            // Define profile to assign during conversion
            $assign_profile=' -set colorspace RGB ';
        }
    }


    /*  ----------------------------------------
        This section handles ICC extraction for
        PSD and PSB files so that ImageMagick
        will handle the conversion correctly.
       ----------------------------------------
    */
   
    // If this is the high resolution preview being generated, extract and use the embedded ICC profile in the PSD or PSB file
    if (($extension=="psd" || $extension=="psb") && $id!="thm" && $id!="col" && $id!="pre" && $id!="scr" && $id!="lpr"){
        global $assign_profile, $icc_path, $icc_transform_complete;
        $iccpath = get_resource_path($ref,true,'',false,$extension).'.icc';
        if (!file_exists($iccpath) && !isset($iccfound)) {
            // Extracted profile doesn't exist. Try extracting.
            if (extract_icc_profile($ref,$extension)){
                $iccfound = true;
            } else {
                $iccfound = false;
            }
        }
       
        if(file_exists($iccpath) && !$icc_transform_complete){
            // We have an extracted ICC profile, so use it as source
            // Set option to remove any existing embedded ICC profiles and explicitly assign extracted profile
            $assign_profile=" +profile \"*\" -profile $iccpath";
            $icc_transform_complete=true;
        }
    } else {
        global $icc_transform_complete, $assign_profile;
        // When generating smaller PSD or PSB previews from the high resolution preview JPEG, don't attempt to reassign the original source profile
        if (($extension=="psd" || $extension=="psb") && ($id=="thm" || $id=="col" || $id=="pre" || $id=="scr" || $id=="lpr")){
            $assign_profile="";
        }       
        $icc_transform_complete=true;

    }
   
    /*  ----------------------------------------
        This section determines behaviour of
        colour space conversion and preservation
        of ICC profiles after conversion.
       ----------------------------------------
    */

    // If $preserve_source_profiles=true;
    if($preserve_source_profiles){
        // Preserve the embedded source profile for all sizes. No conversion will take place.
        $profile="";
    }
   
    // If $preserve_source_profiles_large_only=true; then for sizes larger than 'scr', the embedded source profile will be preserved and no conversion will take place.
    if($preserve_source_profiles_large_only && $id!="thm" && $id!="col" && $id!="pre" && $id!="scr"){
        // Preserve embedded source profile for larger sizes only.
        $profile="";
    }

    // If $preserve_source_profiles_large_only=true; then 'scr' sizes and smaller will be converted to the target profile specified. Strip ICC profile to save space.
    if($preserve_source_profiles_large_only && $id=="thm" && $id=="col" && $id=="pre" && $id=="scr"){
        // Preserve embedded source profile for larger sizes only.
        $profile=$assign_profile.' '.$icc_preview_options.' -profile '.$targetprofile.' +profile ic*';

    }
   
    // If $preserve_source_profiles_large_only=true; then 'scr' sizes and smaller will be converted to the target profile specified. Preserve target profile.
    if($preserve_source_profiles_large_only && $id=="thm" && $id=="col" && $id=="pre" && $id=="scr" && $preserve_target_profiles){
        // Preserve embedded source profile for larger sizes only.
        $profile="$assign_profile $icc_preview_options -profile $targetprofile";

    }
   
    // If $preserve_target_profiles=true;
    if($preserve_target_profiles && !$preserve_source_profiles && !$preserve_source_profiles_large_only){
        // Preserve the embedded source profile then convert to target profile. Preserve target profile.
        $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
        $profile="$assign_profile $icc_preview_options -profile $targetprofile";

    }
   
    // If $preserve_target_profiles=false;
    if(!$preserve_target_profiles && !$preserve_source_profiles && !$preserve_source_profiles_large_only){
        // Preserve the embedded source profile then convert to target profile. Strip target profile.

        $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
        $profile=$assign_profile.' '.$icc_preview_options.' -profile '.$targetprofile.' +profile ic*';
    }
       
    /*  ----------------------------------------
        This section determines appropriate options
        to enable resize operations to take place
        in a linear colourspace to ensure accurate
        colours.
        See http://www.imagemagick.org/Usage/resize/#resize_colorspace
       ----------------------------------------
    */
    global $resize_prefix, $resize_suffix, $tonal_response_curve_compatibility, $colourspace, $profile, $icc_preview_options, $targetprofile;
   
    if ($linear_resize){
        // If Imagemagick v6.7.6-4 or later is being used
        if (!$tonal_response_curve_compatibility && $colourspace=="RGB"){
            // Convert linear file for display

            $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
            $resize_suffix=" -colorspace sRGB $icc_preview_options -profile $targetprofile";
            // Skip first conversion as file is linear already
            $resize_prefix="";
            unset($GLOBALS['profile']);
        }
   
        // If Imagemagick v6.7.6-4 or later is being used
        if (!$tonal_response_curve_compatibility && $colourspace!="RGB"){
            // Convert the file to linear space before resizing
            $resize_prefix=" -colorspace RGB";
            // Convert the file back to the target profile after resizing

            $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
            $resize_suffix=" -colorspace sRGB $icc_preview_options -profile $targetprofile";

        }
   
        // If GraphicsMagick or Imagemagick v6.7.6-3 or earlier is being used
        if ($tonal_response_curve_compatibility && $colourspace=="sRGB"){
            // Convert linear file for display

            $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
            $resize_suffix=" -colorspace sRGB $icc_preview_options -profile $targetprofile";
            // Skip first conversion as file is linear already
            $resize_prefix="";
            unset($GLOBALS['profile']);

        }
   
        // If GraphicsMagick or Imagemagick v6.7.6-3 or earlier is being used
        if ($tonal_response_curve_compatibility && $colourspace!="sRGB"){
            // Convert the file to linear space before resizing
            $resize_prefix=" -colorspace sRGB";
            // Convert the file back to the target profile after resizing

            $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
            $resize_suffix=" -colorspace RGB $icc_preview_options -profile $targetprofile";
        }
    } else {
        // Tell ResourceSpace to skip unnecessary conversions for linear files anyway to save time
       
        // If Imagemagick v6.7.6-4 or later is being used
        if (!$tonal_response_curve_compatibility && $colourspace=="RGB"){
            // Convert linear file for display

            $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
            $resize_suffix=" -colorspace sRGB $icc_preview_options -profile $targetprofile";
            // Skip first conversion as file is linear already
            $resize_prefix="";
            unset($GLOBALS['profile']);

        }
       
        // If GraphicsMagick or Imagemagick v6.7.6-3 or earlier is being used
        if ($tonal_response_curve_compatibility && $colourspace=="sRGB"){
            // Convert linear file for display

            $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
            $resize_suffix=" -colorspace sRGB $icc_preview_options -profile $targetprofile";
            // Skip first conversion as file is linear already
            $resize_prefix="";
            unset($GLOBALS['profile']);

        }
    }
   
} else {
   
    /*  ----------------------------------------
        This section is the default behaviour
        for ResourceSpace when colour management
        is turned off. The embedded profile (if
        it exists) is stripped, then the file is
        converted to RGB. ICC profiles, if any,
        are stripped from the resulting file.
       ----------------------------------------
    */

    global $tonal_response_curve_compatibility_options, $colourspace_options, $icc_preview_profile;
       
    if (!isset($colourspace_options)){
        // Define default -colorspace options
        $colourspace_options="-colorspace $tonal_response_curve_compatibility_options";
    }
           
    // Convert image to target profile as set by $icc_preview_profile. Strip ICC profile to save space.

    $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
    $profile  = '+profile ic* '.$colourspace_options.' +profile ic*';
}


    /*  ----------------------------------------
        End colour management section.
       ----------------------------------------
    */



The following changes also need to be made in image_processing.php;

Under the function extract_icc (at the end of image_processing.php) change the line;

if ( preg_match("/no color profile is available/",$cmdout) || !file_exists($outfile) ||filesize_unlimited($outfile) == 0){

to;

if (!file_exists($outfile)){

That stops the ICC profile extraction code from deleting the profile before we get to use it.

In the same function, change the line;

$cmdout = run_command("$convert_fullpath $infile $outfile $stderrclause");

to;

$cmdout = run_command("$convert_fullpath $infile".'[0]'." $outfile");

That fixes the problem in the ICC extraction code which causes multilayer PSDs and PSBs to spit out multiple profiles.

We need to also change the command that resizes the images so that we can introduce the appropriate options for resizing in linear space, as well as clean up the code a tiny touch by removing a superfluous '+ matte'. It's probably also worth noting that '+ matte' has been depreciated (since v6.6.0-4) and is replaced with '-alpha Off' (http://www.imagemagick.org/script/command-line-options.php#alpha) - though this change will probably not be necessary till ImageMagick v7 is released (then a bunch of changes will be needed).

The command is located just below the existing experimental ICC profile code.

We need to change the image resize command from;

$runcommand = $command ." +matte $profile -resize " . $tw . "x" . $th . "\">\" ".escapeshellarg($path);

to;

$runcommand = $command .' '.$profile.$resize_prefix.' -resize ' . $tw . 'x' . $th . '">"'.$resize_suffix.' '.escapeshellarg($path);

I think that's it.

I'll let you know if I uncover any more bugs in further testing and will post any amended code.

From memory, also to do will be some editing of the preview_preprocessing.php code which makes mention of some ICC code that will either need to be removed or changed for this new code.

Let me know what you think and how your testing goes.

thanks!
Tristan.

Electric Art

unread,
Aug 6, 2013, 9:54:43 PM8/6/13
to resour...@googlegroups.com
Hey Jeff,

Found some problems with the code - I've re-written some parts of it (and simplified it slightly in the process). I'll post the updated code shortly.

Tristan.
...

Jeff Harmon

unread,
Aug 6, 2013, 9:57:30 PM8/6/13
to ResourceSpace
I won't be able to test until after 8/15 anyway.  Awesome work though!!!

Jeff


--

Electric Art

unread,
Aug 14, 2013, 11:14:20 PM8/14/13
to resour...@googlegroups.com
Hey Jeff,

I've finally finished it. I just need to test compatibility with older versions of ImageMagick, but everything else works great for me! (with the exception of Photoshop EPS files, which I just noticed). I believe though that everything except EPS/AI and PDF files should work correctly, where EPS/AI and PDF files will assume sRGB (which I believe is the same as previous behaviour).

Here's the new code;


In config.php add the following (this replaces any other colour management related settings in config.php);

# ICC Colour Management Features (Experimental)
# Requires Exiftool and either Imagemagick or GraphicsMagick where ImageMagick is preferred
# Note that ImageMagick must be installed with LCMS or LCMS2 support
# The web server user (e.g. www-data) should have permissions to write to /iccprofiles to allow profile extraction

# Uncomment below to activate colour management
$colour_management=true;

# Display warnings when profiles are either incorrectly set in config.php or are required and are missing from the /iccprofiles directory
$display_profile_warnings=true;

# If $assign_profiles_to_untagged_images=true;, defining profiles for untagged images here will enable tagging for any untagged image of the corresponding colour mode (RGB, CMYK, Gray)

# Profiles must exist in the /iccprofiles directory of ResourceSpace for this to function and, apart from sRGB, are NOT included in the default installation.
# High quality CMYK offset printing profiles may be freely downloaded from http://colormanagement.org/
$assign_profiles_to_untagged_images=true;
$untagged_rgb_profile = 'sRGB_IEC61966-2-1_black_scaled.icc';
$untagged_cmyk_profile = 'ISOcoated_v2_bas.ICC';
$untagged_gray_profile = 'ISOcoated_v2_grey1c_bas.ICC';


# Turning on auto assigning of profiles will use Exiftool to check JPEG or TIFF captures from digital cameras to see if they indicate a profile in EXIF tags but do not have a profile embedded.
# Profiles are then assigned based upon the definitions below.
# Profiles must exist in the /iccprofiles directory of ResourceSpace for this to function and, apart from sRGB, are NOT included in the default installation.
# Some of these profiles may be downloadable from http://www.adobe.com/support/downloads/detail.jsp?ftpID=4076
# and http://color.org/profiles.xalter
# NOTE that $assign_profiles_to_untagged_images must be set to true for this section to apply
$auto_assign_based_on_exif_tags=true;
$default_srgb_profile = 'sRGB_IEC61966-2-1_black_scaled.icc';
$default_widegamut_profile = 'WideGamutRGB.icc';
$default_adobergb_profile = 'AdobeRGB1998.icc';

# This target profile will be used for the conversion for display but is discarded after conversion unless $preserve_target_profiles=true;
# In almost all cases, this should be set to 'sRGB_IEC61966-2-1_black_scaled.icc'
$icc_preview_profile = 'sRGB_IEC61966-2-1_black_scaled.icc';

# Additional options for profile conversion during preview generation
$icc_preview_options = '-intent relative -black-point-compensation';

# With $linear_resize enabled, ResourceSpace will tell ImageMagick/GraphicsMagick to convert the file to a linear tonal response curve before performing the resize operation. In some situations this may enable more accurate colour during resizing.
# Setting this option may increase preview generation time.
# See http://www.imagemagick.org/Usage/resize/#resize_colorspace
# CMYK images are not resized in linear as the colours become inaccurate in the conversion to linear and back to non-linear space.
#$linear_resize=true;

# Uncomment ONLY if using GraphicsMagick or ImageMagick v6.7.6-3 or older.
# Setting $tonal_response_curve_compatibility=true; sets the correct colour mode options for non-linear RGB when converting the image for compatibility with GraphicsMagick and ImageMagick v6.7.6-3 or older.

#$tonal_response_curve_compatibility=true;

# With $preserve_source_profiles=true;, source profiles are preserved for all files tagged with an ICC profile. No ICC colour space conversions are made.
# This option requires a colour managed browser with colour management turned on for correct display of preview images and thumbnails. E.g. Safari 2.0+, Chrome 22.0+, Firefox 3.6+ (ICC v2, v4 with manual config), Opera 12.10+
# Check browser compatibility here - http://www.color.org/version4html.xalter
#$preserve_source_profiles=true;

# With $preserve_source_profiles_large_only=true;, only Thumbnails, Screen resolution previews and Collection Thumbnails are converted to the target profile set by $icc_preview_profile. All other file sizes retain the original source profile.
#$preserve_source_profiles_large_only=true;

# Set $preserve_target_profiles=true; to ensure that images which have been converted to the target profile set by $icc_preview_profile preserve the target profile after conversion.
# If the target profile set in $icc_preview_profile is NOT sRGB IEC61966-2.1 then this setting is required for properly colour managed images. A colour managed browser is also required (see comments for $preserve_source_profiles=true; for details about browsers).
# If the target profile set in $icc_preview_profile is sRGB IEC61966-2.1 then, dependent upon browser behaviour, this setting may still be required for properly colour managed images (with the safest assumption to be that it IS required).
# Enabling this setting will add to the preview file size (approximately 4k per image).
$preserve_target_profiles=true;





In image_processing.php (replacing the section labelled # EXPERIMENTAL CODE TO USE EXISTING ICC PROFILE IF PRESENT);


/* ----------------------------------------
    Colour Management section.
    Requires Exiftool and ImageMagick
    (GraphicsMagick is compatible however
    all functions may not work correctly)
   ----------------------------------------
*/

// If GraphicsMagick or Imagemagick v6.7.6-3 or earlier is being used, set appropriate colourspace option.
// In each case, this setting will tell ImageMagick or GraphicsMagick to assume a non-linear (sRGB) tonal response curve when converting if the source file is non-linear. Only needed if there is no embedded profile and no profile will be assigned.
global $tonal_response_curve_compatibility, $tonal_response_curve_compatibility_options;

if ($tonal_response_curve_compatibility){
    // Set 'RGB' for compatibility for GraphicsMagick or ImageMagick v6.7.6-3 or earlier
    $tonal_response_curve_compatibility_options="RGB";
} else {
    // Set 'sRGB' for ImageMagick v6.7.6-4 or newer
    $tonal_response_curve_compatibility_options="sRGB";
}

// Check if colour management is enabled
global $colour_management;
if($colour_management){
   
    global $imagemagick_path, $exiftool_path, $preserve_source_profiles, $preserve_target_profiles, $preserve_source_profiles_large_only, $assign_profiles_to_untagged_images, $tonal_response_curve_compatibility, $tonal_response_curve_compatibility_options, $assign_profile, $icc_profile, $icc_preview_profile, $icc_preview_options, $colourspace, $profile, $linear_resize, $display_profile_warnings, $supported_icc_colour_modes, $use_target_profile, $ffmpeg_supported_extensions;


    /*  ----------------------------------------
        This section checks that a target profile
        is defined and exists. All basic functions
        of the Colour Managment section require a
        target profile to work.
           ----------------------------------------
    */
   
    if (!isset($icc_preview_profile)){
        // No target profile set, exit
        exit("No ICC target profile is set. An ICC preview profile must be set in config.php and the file exist to enable colour management.");
    } else {
        // A profile is set - check if it exists
        $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
        if (!file_exists($targetprofile)){
            exit("An ICC target profile is set however it cannot be found at the location $targetprofile. Check icc_preview_profile settings in config.php. Also check that the webserver user has access to /iccprofiles and has permissions to access the target profile. An ICC preview profile must be set in config.php and the file exist to enable colour management.");

        }
    }
   
    /*  ----------------------------------------
        This section determines information about
        the file including colour mode and if it
        has an ICC profile or not
           ----------------------------------------
    */

    // Locate Exiftool
    $exiftool_fullpath = get_utility_path("exiftool");
    if ($exiftool_fullpath==false){
        // Exiftool not found, exit
        exit("Could not find Exiftool utility at location '$exiftool_path'.");
    } else {
        // Extract the ICC profile description from image (if exist) using Exiftool
        $icc_profile_extract=run_command($exiftool_fullpath.' -profiledescription '.escapeshellarg($file));
        // Remove non profile name information
        $icc_profile_extended_name = substr(strrchr($icc_profile_extract, ":"), 1);
        $icc_profile=trim($icc_profile_extended_name);
        // Remove special characters from the profile name for file naming purposes
           $icc_profile = str_replace(" ", "_", $icc_profile); // Replaces all spaces with hyphens.
           $icc_profile = preg_replace('/[^A-Za-z0-9\-]/', '', $icc_profile); // Removes special chars.
           $icc_profile = preg_replace('/-+/', '_', $icc_profile); // Replaces multiple hyphens with single one.
    }

    // Define array of colour modes with specific handling
    $supported_icc_colour_modes = array(
        "RGB",
        "sRGB",
        "CMYK",
        "Gray",
        "CIELab",

      );

    // Locate ImageMagick
    $convert_fullpath = get_utility_path("im-convert");
    if ($convert_fullpath==false){
        // ImageMagick not found, exit
        exit("Could not find ImageMagick 'convert' utility at location '$imagemagick_path'.");
    } else {
        // Determine colour mode of image
        $colourspace=run_command($convert_fullpath.' '.escapeshellarg($file).' -print "%[colorspace]\n" null:');   
    }

    /*  ----------------------------------------
        This section determines behaviour of
        colour space conversion.
           ----------------------------------------
    */   
    global $convert_profile, $strip_profile, $assign_profile;

    // If the file is linear RGB, CIELab, an unsupported colourspace or a RAW file, then don't attempt to preserve profiles
    if(preg_match('/^(dng|nef|x3f|cr2|crw|mrw|orf|raf|dcr)$/i', $extension, $rawext) || in_array($extension,$ffmpeg_supported_extensions) || (!$tonal_response_curve_compatibility && $colourspace=="RGB") || ($tonal_response_curve_compatibility && $colourspace=="sRGB") || $colourspace=="CIELab" || !in_array($colourspace, $supported_icc_colour_modes)){
        $preserve_source_profiles="";
        $preserve_source_profiles_large_only="";
    }
       
    // If $preserve_source_profiles=false;
    if(!$preserve_source_profiles || !$preserve_source_profiles_large_only){
        // Preserve the embedded source profile for all sizes then convert to the target profile.

        $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
        $convert_profile=$icc_preview_options.' -profile '.escapeshellarg($targetprofile);

    }

    // If $preserve_source_profiles_large_only=true; then 'scr' sizes and smaller will be converted to the target profile specified.
    if($preserve_source_profiles_large_only && ($id=="thm" || $id=="col" || $id=="pre" || $id=="scr")){
        // Preserve the embedded source profile then convert smaller sizes to target display profile.

        $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
        $convert_profile=$icc_preview_options.' -profile '.escapeshellarg($targetprofile);
        $assign_profile="";
    }
   
    // If $preserve_source_profiles=true; and there is an embedded profile then preserve the embedded profile.
    if($preserve_source_profiles){
        // Preserve the embedded source or assigned profile for all sizes. No conversion will take place.
        $convert_profile="";
    }
   
    // If $preserve_source_profiles_large_only=true; and there is an embedded profile then for sizes larger than 'scr', the embedded source profile will be preserved and no conversion will take place.

    if($preserve_source_profiles_large_only && $id!="thm" && $id!="col" && $id!="pre" && $id!="scr"){
        // Preserve embedded source or assigned profile for larger sizes only.
        $convert_profile="";
    }

   
    /*  ----------------------------------------
        This section determines specific behaviour
        based upon colour mode. Special conditions
        need to be considered for certain colour
        modes.
           ----------------------------------------
    */
   
    // Non-linear RGB
    if ((!$tonal_response_curve_compatibility && $colourspace=="sRGB") || ($tonal_response_curve_compatibility && $colourspace=="RGB")){
        // File is non-linear RGB
        //echo "File is non-linear RGB";
       
    /*  ----------------------------------------

        This section handles assigning ICC profiles
        to untagged images. Profiles are assigned
        dependent upon colour mode and the profiles
        defined in config.php
           ----------------------------------------
    */
        global $untagged_rgb_profile;

        // Check if assigning profiles is set. Don't try to assign profiles for RAW images or video files.
        if($assign_profiles_to_untagged_images && !$icc_profile && !preg_match('/^(dng|nef|x3f|cr2|crw|mrw|orf|raf|dcr)$/i', $extension, $rawext) && !in_array($extension,$ffmpeg_supported_extensions) && (isset($untagged_rgb_profile))){
            global $auto_assign_based_on_exif_tags, $exiftool_fullpath, $default_srgb_profile, $default_widegamut_profile, $default_adobergb_profile;


            // Attempt to automatically assign appropriate profile based upon EXIF tag information
            if ($auto_assign_based_on_exif_tags){
                // First try ColorSpace tag
                // Locate Exiftool
                $exiftool_fullpath = get_utility_path("exiftool");
                if ($exiftool_fullpath==false){
                    // Exiftool not found, exit
                    exit("Could not find Exiftool utility at location '$exiftool_path'.");
                } else {
                    // Determine Colorspace EXIF tag of image (if exist) using Exiftool
                    $exif_colorspace=run_command($exiftool_fullpath.' -ColorSpace '.escapeshellarg($file));
                }
           
                // If Exiftool returns sRGB
                if (!$assign_profile && (preg_match("/sRGB/",$exif_colorspace))){
                    $target_rgb_profile = dirname(__FILE__) . '/../iccprofiles/' . $default_srgb_profile;
                    // Check if profile exists
                    if ((isset($default_srgb_profile)) && !file_exists($target_rgb_profile)){
                        if ($display_profile_warnings){
                            echo "An ICC target profile is set however it cannot be found at the location $target_rgb_profile. Check default_srgb_profile settings in config.php. An ICC preview profile must be set in config.php and the file exist to enable colour management for this file.";

                        }
                    } else {
                        // Define profile to assign during conversion
                        $assign_profile=' -profile '.escapeshellarg($target_rgb_profile);

                    }
                }
           
                // If Exiftool returns Wide Gamut RGB
                if (!$assign_profile && (preg_match("/Wide Gamut RGB/",$exif_colorspace))){
                    $target_rgb_profile = dirname(__FILE__) . '/../iccprofiles/' . $default_widegamut_profile;
                    // Check if profile exists
                    if ((isset($default_widegamut_profile)) && !file_exists($target_rgb_profile)){
                        if ($display_profile_warnings){
                            echo "An ICC target profile is set however it cannot be found at the location $target_rgb_profile. Check default_widegamut_profile settings in config.php. An ICC preview profile must be set in config.php and the file exist to enable colour management for this file.";

                        }
                    } else {
                        // Define profile to assign during conversion
                        $assign_profile=' -profile '.escapeshellarg($target_rgb_profile);

                    }
                }
           
                // If Exiftool returns Uncalibrated, check for AdobeRGB
                if (!$assign_profile && (preg_match("/Uncalibrated/",$exif_colorspace))){
                    // Check InteropIndex for AdobeRGB
                    $exiftool_fullpath = get_utility_path("exiftool");
                    if ($exiftool_fullpath==false){
                        // Exiftool not found, exit
                        exit("Could not find Exiftool utility at location '$exiftool_path'.");
                    } else {
                        // Determine InteropIndex EXIF tag of image (if exist) using Exiftool
                        $exif_interop_index=run_command($exiftool_fullpath.' -InteropIndex '.escapeshellarg($file));
                    }
                    if (preg_match("/Adobe RGB/",$exif_interop_index)){
                        $target_rgb_profile = dirname(__FILE__) . '/../iccprofiles/' . $default_adobergb_profile;
                        // Check if profile exists
                        if ((isset($default_adobergb_profile)) && !file_exists($target_rgb_profile)){
                            if ($display_profile_warnings){
                                echo "An ICC target profile is set however it cannot be found at the location $target_rgb_profile. Check default_adobergb_profile settings in config.php. An ICC preview profile must be set in config.php and the file exist to enable colour management for this file.";

                            }
                        } else {
                            // Define profile to assign during conversion
                            $assign_profile=' -profile '.escapeshellarg($target_rgb_profile);
                        }
                    }
                }
            }   
       
            // If there is still no profile assigned, assign a default RGB profile as defined in config.php
            if(!$assign_profile){

                $target_rgb_profile = dirname(__FILE__) . '/../iccprofiles/' . $untagged_rgb_profile;
                // Check profile exists
                if (!file_exists($target_rgb_profile) && $display_profile_warnings){
                    echo "An ICC target profile is set however it cannot be found at the location $target_rgb_profile. Check settings in config.php. An ICC preview profile must be set in config.php and the file exist to enable colour management for this file.";

                }
                // Define profile to assign during conversion
                $assign_profile=' -profile '.escapeshellarg($target_rgb_profile);   
            }   
        }
       
        // If not assigning profiles, tell ImageMagick to explicity set -colorspace for untagged images (Compatibility for GraphicsMagick or ImageMagick v6.7.6-3 or earlier)
        if (!$assign_profiles_to_untagged_images && !$icc_profile && $tonal_response_curve_compatibility){

            // Define profile to assign during conversion
            $assign_profile=' -set colorspace $tonal_response_curve_compatibility_options ';

        }
       
    /*  ----------------------------------------
        This section determines behaviour of
        preservation of ICC profiles after
        conversion.
           ----------------------------------------
    */
   
        // If $preserve_target_profiles=false; we want to strip the profiles after conversion to save space
        if(!$preserve_target_profiles){
            // If $preserve_source_profiles is enabled, preserve all profiles
            // If $preserve_source_profiles_large_only is enabled, preserve only the profiles of larger previews
            if($preserve_source_profiles || ($preserve_source_profiles_large_only && $id!="thm" && $id!="col" && $id!="pre" && $id!="scr")){
                // Keep target profile.
                $strip_profile="";
            } else {
                // Strip target profile.
                $strip_profile=" +profile ic*";
                // Preserve the embedded source profile then convert smaller sizes to target display profile.

                $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
                $convert_profile=$icc_preview_options.' -profile '.escapeshellarg($targetprofile);
                $assign_profile="";
            }
        }
   
        // If $preserve_target_profiles=true; we want to keep the target profile
        if($preserve_target_profiles){
            // Keep target profile.
            $strip_profile="";

        }
   
    /*  ----------------------------------------
        This section determines appropriate options
        to enable resize operations to take place
        in a linear colourspace to ensure accurate
        colours.
        See http://www.imagemagick.org/Usage/resize/#resize_colorspace
           ----------------------------------------
    */
   
        global $resize_prefix, $resize_suffix, $tonal_response_curve_compatibility, $colourspace, $profile, $icc_preview_options, $convert_profile;
        if ($linear_resize){   
            global $restore_profile, $assign_profile, $strip_profile, $icc_path, $icc_transform_complete, $icc_preview_profile;   
       
            // If the profile is to be preserved, the file has an embedded profile, we must extract the profile so we can convert back from linear space to the original profile.
            if (($preserve_source_profiles || ($preserve_source_profiles_large_only && $id!="thm" && $id!="col" && $id!="pre" && $id!="scr")) && !empty($icc_profile)){           
                $iccpath = dirname(__FILE__) . '/../iccprofiles/' . $icc_profile .'.icc';

                if (!file_exists($iccpath) && !isset($iccfound)) {
                    // Extracted profile doesn't exist. Try extracting.
                    if (extract_icc_profile($ref,$extension)){
                        $iccfound = true;
                    } else {
                        $iccfound = false;
                        // Profile extraction failed. Fall back to target preview profile.
                        if ($display_profile_warnings){
                            echo "WARNING! Profile extraction failed.";
                        }
                    }
                }
           
                if(file_exists($iccpath)){

                    // We have an extracted ICC profile, so use it as source
                    // Set option to assign extracted profile
                    $restore_profile=" -set profile ".escapeshellarg($iccpath);
                    $icc_transform_complete=true;
                }
            }
       
            // If $preserve_source_profiles=true;
            if($preserve_source_profiles && isset($assign_profile)){

                // Preserve the embedded source profile for all sizes. No conversion will take place.
                $restore_profile=$assign_profile;

            }
   
            // If $preserve_source_profiles_large_only=true; then for sizes larger than 'scr', the embedded source profile will be preserved and no conversion will take place.
            if($preserve_source_profiles_large_only && isset($assign_profile) && $id!="thm" && $id!="col" && $id!="pre" && $id!="scr"){

                // Preserve embedded source profile for larger sizes only.
                $restore_profile=$assign_profile;

            }
           
            // If $preserve_source_profiles_large_only=true; then 'scr' sizes and smaller will be converted to the target profile specified.
            if ($preserve_source_profiles_large_only && ($id=="thm" || $id=="col" || $id=="pre" || $id=="scr")){
                $restore_profile="";
            }
       
            // Set linear resize options for GraphicsMagick or ImageMagick v6.7.6-3 or earlier
            if ($tonal_response_curve_compatibility){

                // Convert the file to linear space before resizing
                $resize_prefix=" -colorspace sRGB";
                // Convert the file back to the target profile after resizing
                $resize_suffix=" -colorspace RGB $restore_profile $convert_profile $strip_profile";           
            }
           
            // Set linear resize options for GraphicsMagick or ImageMagick v6.7.6-4 or later
            if (!$tonal_response_curve_compatibility){

                // Convert the file to linear space before resizing
                $resize_prefix=" -colorspace RGB";
                // Convert the file back to the target profile after resizing
                $resize_suffix=" -colorspace sRGB $restore_profile $convert_profile $strip_profile";           
            }
        }
    }   

   
    // Linear RGB
    if ((!$tonal_response_curve_compatibility && $colourspace=="RGB") || ($tonal_response_curve_compatibility && $colourspace=="sRGB")){
        // File is linear RGB
        //echo "File is linear RGB";
       
        // Always convert to the target profile as linear RGB does not have any profiles to preserve

        $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
        $convert_profile=$icc_preview_options.' -profile '.escapeshellarg($targetprofile);

       
    /*  ----------------------------------------
        This section determines appropriate options
        to enable resize operations to take place
        in a linear colourspace to ensure accurate
        colours.
        See http://www.imagemagick.org/Usage/resize/#resize_colorspace
           ----------------------------------------
    */
        global $resize_prefix, $resize_suffix, $tonal_response_curve_compatibility, $colourspace, $profile, $icc_preview_options, $convert_profile;
        global $restore_profile, $assign_profile, $icc_path, $icc_transform_complete, $icc_preview_profile;                   
        // Convert linear file for display using target profile

        $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
        $convert_profile=$icc_preview_options.' -profile '.escapeshellarg($targetprofile);
        $resize_suffix=" -colorspace sRGB $convert_profile $strip_profile";

        // Skip first conversion as file is linear already
        $resize_prefix="";
        $convert_profile="";   
    }
   
    // CMYK
    if ($colourspace=="CMYK"){
        // File is CMYK
        //echo "File is CMYK";

       
    /*  ----------------------------------------
        This section handles assigning ICC profiles
        to untagged images. Profiles are assigned
        dependent upon colour mode and the profiles
        defined in config.php
           ----------------------------------------
    */
       
        global $untagged_cmyk_profile;

        // Assign profile for untagged CMYK images
        if ($assign_profiles_to_untagged_images && !$icc_profile && (isset($untagged_cmyk_profile))){

            $target_cmyk_profile = dirname(__FILE__) . '/../iccprofiles/' . $untagged_cmyk_profile;
            // Check profile exists
            if (!file_exists($target_cmyk_profile) && $display_profile_warnings){
                echo "An ICC target profile is set however it cannot be found at the location $target_cmyk_profile. Check settings in config.php. An ICC preview profile must be set in config.php and the file exist to enable colour management for this file.";

            }
            // Define profile to assign during conversion
            $assign_profile=' -profile '.escapeshellarg($target_cmyk_profile);
        }
       
        // If not assigning profiles, tell ImageMagick to explicity set -colorspace for untagged images (Compatibility for GraphicsMagick or ImageMagick v6.7.6-3 or earlier)
        if (!$assign_profiles_to_untagged_images && !$icc_profile && $tonal_response_curve_compatibility){

            // Define profile to assign during conversion
            $assign_profile=' -set colorspace CMYK ';

        }
       
    /*  ----------------------------------------
        This section determines behaviour of
        preservation of ICC profiles after
        conversion.
           ----------------------------------------
    */
   
        // If $preserve_target_profiles=false; we want to strip the profiles after conversion to save space
        if(!$preserve_target_profiles){
            // If $preserve_source_profiles is enabled, preserve all profiles
            // If $preserve_source_profiles_large_only is enabled, preserve only the profiles of larger previews
            if($preserve_source_profiles || ($preserve_source_profiles_large_only && $id!="thm" && $id!="col" && $id!="pre" && $id!="scr")){
                // Keep target profile.
                $strip_profile="";
            } else {
                // Strip target profile.
                $strip_profile=" +profile ic*";
                // Preserve the embedded source profile then convert smaller sizes to target display profile.

                $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
                $convert_profile=$icc_preview_options.' -profile '.escapeshellarg($targetprofile);
                $assign_profile="";
            }
        }
   
        // If $preserve_target_profiles=true; we want to keep the target profile
        if($preserve_target_profiles){
            // Keep target profile.
            $strip_profile="";
        }

       
    }
   
    // Gray
    if ($colourspace=="Gray"){
        // File is Gray
        //echo "File is Gray";

       
    /*  ----------------------------------------
        This section handles assigning ICC profiles
        to untagged images. Profiles are assigned
        dependent upon colour mode and the profiles
        defined in config.php
           ----------------------------------------
    */
       
        global $untagged_gray_profile;

        // Assign profile for untagged grayscale images
        if ($assign_profiles_to_untagged_images && !$icc_profile && (isset($untagged_gray_profile))){

            $target_gray_profile = dirname(__FILE__) . '/../iccprofiles/' . $untagged_gray_profile;
            // Check profile exists
            if (!file_exists($target_gray_profile) && $display_profile_warnings){
                echo "An ICC target profile is set however it cannot be found at the location $target_gray_profile. Check settings in config.php. An ICC preview profile must be set in config.php and the file exist to enable colour management for this file.";

            }
            // Define profile to assign during conversion
            $assign_profile=' -profile '.escapeshellarg($target_gray_profile);
        }
       
        // If not assigning profiles, tell ImageMagick to explicity set -colorspace for untagged images (Compatibility for GraphicsMagick or ImageMagick v6.7.6-3 or earlier)
        if (!$assign_profiles_to_untagged_images && !$icc_profile && $tonal_response_curve_compatibility){

            // Define profile to assign during conversion
            $assign_profile=' -set colorspace Gray ';

        }

    /*  ----------------------------------------
        This section determines behaviour of
        preservation of ICC profiles after
        conversion.
           ----------------------------------------
    */
   
        // If $preserve_target_profiles=false; we want to strip the profiles after conversion to save space
        if(!$preserve_target_profiles){
            // If $preserve_source_profiles is enabled, preserve all profiles
            // If $preserve_source_profiles_large_only is enabled, preserve only the profiles of larger previews
            if($preserve_source_profiles || ($preserve_source_profiles_large_only && $id!="thm" && $id!="col" && $id!="pre" && $id!="scr")){
                // Keep target profile.
                $strip_profile="";
            } else {
                // Strip target profile.
                $strip_profile=" +profile ic*";
                // Preserve the embedded source profile then convert smaller sizes to target display profile.

                $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
                $convert_profile=$icc_preview_options.' -profile '.escapeshellarg($targetprofile);
                $assign_profile="";
            }
        }
   
        // If $preserve_target_profiles=true; we want to keep the target profile
        if($preserve_target_profiles){
            // Keep target profile.
            $strip_profile="";

        }   
       
    /*  ----------------------------------------
        This section determines appropriate options
        to enable resize operations to take place
        in a linear colourspace to ensure accurate
        colours.
        See http://www.imagemagick.org/Usage/resize/#resize_colorspace
           ----------------------------------------
    */
       
        global $resize_prefix, $resize_suffix, $tonal_response_curve_compatibility, $colourspace, $profile, $icc_preview_options, $convert_profile;
        if ($linear_resize){   
            global $restore_profile, $assign_profile, $strip_profile, $icc_path, $icc_transform_complete, $icc_preview_profile;   
       
            // If the profile is to be preserved, the file has an embedded profile, we must extract the profile so we can convert back from linear space to the original profile.
            if (($preserve_source_profiles || ($preserve_source_profiles_large_only && $id!="thm" && $id!="col" && $id!="pre" && $id!="scr")) && !empty($icc_profile)){           
                $iccpath = dirname(__FILE__) . '/../iccprofiles/' . $icc_profile .'.icc';

                if (!file_exists($iccpath) && !isset($iccfound)) {
                    // Extracted profile doesn't exist. Try extracting.
                    if (extract_icc_profile($ref,$extension)){
                        $iccfound = true;
                    } else {
                        $iccfound = false;
                        // Profile extraction failed. Fall back to target preview profile.
                        if ($display_profile_warnings){
                            echo "WARNING! Profile extraction failed.";
                        }
                    }
                }
           
                if(file_exists($iccpath)){

                    // We have an extracted ICC profile, so use it as source
                    // Set option to assign extracted profile
                    $restore_profile=" -set profile ".escapeshellarg($iccpath);
                    $icc_transform_complete=true;
                }
            }
       
            // If $preserve_source_profiles=true;
            if($preserve_source_profiles && isset($assign_profile)){

                // Preserve the embedded source profile for all sizes. No conversion will take place.
                $restore_profile=$assign_profile;

            }
   
            // If $preserve_source_profiles_large_only=true; then for sizes larger than 'scr', the embedded source profile will be preserved and no conversion will take place.
            if($preserve_source_profiles_large_only && isset($assign_profile) && $id!="thm" && $id!="col" && $id!="pre" && $id!="scr"){

                // Preserve embedded source profile for larger sizes only.
                $restore_profile=$assign_profile;

            }
           
            // If $preserve_source_profiles_large_only=true; then 'scr' sizes and smaller will be converted to the target profile specified.
            if ($preserve_source_profiles_large_only && ($id=="thm" || $id=="col" || $id=="pre" || $id=="scr")){
                $restore_profile="";
                // Make sure conversions to the target display profile are in the correct colour mode
                if ($tonal_response_curve_compatibility){
                    $colourspace="RGB";
                }
                if (!$tonal_response_curve_compatibility){
                    $colourspace="sRGB";
                }
            }
       
            // Set linear resize options for GraphicsMagick or ImageMagick v6.7.6-3 or earlier
            if ($tonal_response_curve_compatibility){

                // Convert the file to linear space before resizing
                $resize_prefix=" -colorspace sRGB";
                // Convert the file back to the target profile after resizing
                $resize_suffix=" -colorspace $colourspace $restore_profile $convert_profile $strip_profile";           
            }
           
            // Set linear resize options for GraphicsMagick or ImageMagick v6.7.6-4 or later
            if (!$tonal_response_curve_compatibility){

                // Convert the file to linear space before resizing
                $resize_prefix=" -colorspace RGB";
                // Convert the file back to the target profile after resizing
                $resize_suffix=" -colorspace $colourspace $restore_profile $convert_profile $strip_profile";           
            }
        }
    }
   
    // CIELab
    if ($colourspace=="CIELab"){
        // File is CIELab
        //echo "File is CIELab";
       
        // Always convert to the target profile as CIELab does not have any profiles to preserve

        $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
        $convert_profile=$icc_preview_options.' -colorspace '.$tonal_response_curve_compatibility_options.' -profile '.escapeshellarg($targetprofile);

       
    /*  ----------------------------------------
        This section determines appropriate options
        to enable resize operations to take place
        in a linear colourspace to ensure accurate
        colours.
        See http://www.imagemagick.org/Usage/resize/#resize_colorspace
           ----------------------------------------
    */
       
        global $resize_prefix, $resize_suffix, $tonal_response_curve_compatibility, $colourspace, $profile, $icc_preview_options, $convert_profile, $strip_profile, $icc_path, $icc_preview_profile;
        if ($linear_resize){                       
            // Set linear resize options for GraphicsMagick or ImageMagick v6.7.6-3 or earlier
            if ($tonal_response_curve_compatibility){

                // Convert the file to linear space before resizing
                $resize_prefix=" -colorspace sRGB";
                // Convert the file back to the target profile after resizing
                $resize_suffix=" -colorspace RGB $convert_profile $strip_profile";
            }
           
            // Set linear resize options for GraphicsMagick or ImageMagick v6.7.6-4 or later
            if (!$tonal_response_curve_compatibility){

                // Convert the file to linear space before resizing
                $resize_prefix=" -colorspace RGB";
                // Convert the file back to the target profile after resizing
                $resize_suffix=" -colorspace sRGB $convert_profile $strip_profile";
            }
        }       
    }
   
    // All other colour modes
    if (!in_array($colourspace, $supported_icc_colour_modes)){
        // File is in an unsupported colour mode - use default handling
        //echo "File is in an unsupported colour mode - use default handling";
       
        // Always convert to the target profile as unsupported colour modes do not have any profiles to preserve

        $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
        $convert_profile=$icc_preview_options.' -colorspace '.$tonal_response_curve_compatibility_options.' -profile '.escapeshellarg($targetprofile);

       
    /*  ----------------------------------------
        This section determines appropriate options
        to enable resize operations to take place
        in a linear colourspace to ensure accurate
        colours.
        See http://www.imagemagick.org/Usage/resize/#resize_colorspace
           ----------------------------------------
    */
       
        global $resize_prefix, $resize_suffix, $tonal_response_curve_compatibility, $colourspace, $profile, $icc_preview_options, $convert_profile, $restore_profile, $assign_profile, $strip_profile, $icc_path, $icc_preview_profile;
        if ($linear_resize){                       
            // Set linear resize options for GraphicsMagick or ImageMagick v6.7.6-3 or earlier
            if ($tonal_response_curve_compatibility){

                // Convert the file to linear space before resizing
                $resize_prefix=" -colorspace sRGB";
                // Convert the file back to the target profile after resizing
                $resize_suffix=" -colorspace RGB $convert_profile $strip_profile";
            }
           
            // Set linear resize options for GraphicsMagick or ImageMagick v6.7.6-4 or later
            if (!$tonal_response_curve_compatibility){

                // Convert the file to linear space before resizing
                $resize_prefix=" -colorspace RGB";
                // Convert the file back to the target profile after resizing
                $resize_suffix=" -colorspace sRGB $convert_profile $strip_profile";

            }
        }       
    }   
   
       
    /*  ----------------------------------------
        This section handles ICC extraction for
        PSD and PSB files so that ImageMagick
        will handle the conversion correctly.
           ----------------------------------------
    */
   
    // If this is the high resolution preview being generated, extract and use the embedded ICC profile in the PSD or PSB file
    if (($extension=="psd" || $extension=="psb") && $id!="thm" && $id!="col" && $id!="pre" && $id!="scr" && $id!="lpr"){
        global $assign_profile, $icc_path, $icc_transform_complete;

        $iccpath = dirname(__FILE__) . '/../iccprofiles/' . $icc_profile .'.icc';

        if (!file_exists($iccpath) && !isset($iccfound)) {
            // Extracted profile doesn't exist. Try extracting.
            if (extract_icc_profile($ref,$extension)){
                $iccfound = true;
            } else {
                $iccfound = false;
            }
        }
       
        if(file_exists($iccpath)){

            // We have an extracted ICC profile, so use it as source
            // Set option to remove any existing embedded ICC profiles and explicitly assign extracted profile
            $assign_profile=" +profile \"*\" -profile ".escapeshellarg($iccpath);

            $icc_transform_complete=true;
        }
    } else {
        global $icc_transform_complete, $assign_profile;
        // When generating smaller PSD or PSB previews from the high resolution preview JPEG, don't attempt to reassign the original source profile
        if (($extension=="psd" || $extension=="psb") && ($id=="thm" || $id=="col" || $id=="pre" || $id=="scr" || $id=="lpr")){
            $assign_profile="";
        }       
        $icc_transform_complete=true;
    }

    /*  ----------------------------------------
        Set the conversion options ready for the
        preview generation commands.
           ----------------------------------------
    */   

    if ($linear_resize){
        $profile=$assign_profile.' '.$convert_profile.' ';
    } else {
        $profile=$assign_profile.' '.$convert_profile.' '.$strip_profile;

    }
   
} else {
   
    /*  ----------------------------------------
        This section is the default behaviour
        for ResourceSpace when colour management
        is turned off. The embedded profile (if
        it exists) is stripped, then the file is
        converted to RGB. ICC profiles, if any,
        are stripped from the resulting file.
           ----------------------------------------
    */

    global $tonal_response_curve_compatibility_options, $colourspace_options, $icc_preview_profile;
       
    if (!isset($colourspace_options)){
        // Define default -colorspace options
        $colourspace_options="-colorspace $tonal_response_curve_compatibility_options";
    }
           
    // Convert to sRGB tonal response curve. Strip profiles. No other colour handling is applied.
    $profile  = $colourspace_options.'+profile ic* ';

}


    /*  ----------------------------------------
        End colour management section.
           ----------------------------------------
    */


In image_processing.php, just below the old experimental ICC code, we need to find the following lines and replace them;

Find this line;


$runcommand = $command ." +matte $profile -resize " . $tw . "x" . $th . "\">\" ".escapeshellarg($path);

And replace with this;

global $resize_prefix, $resize_suffix;
$runcommand = $command ." +matte $profile $resize_prefix -resize " . $tw . "x" . $th . "\">\" $resize_suffix ".escapeshellarg($path);

Find this line;

$runcommand = $command ." +matte $profile -resize " . $tw . "x" . $th . "\">\" -tile ".escapeshellarg($watermarkreal)." -draw \"rectangle 0,0 $tw,$th\" ".escapeshellarg($path);

And replace with this;

$runcommand = $command ." +matte $profile $resize_prefix -resize " . $tw . "x" . $th . "\">\" $resize_suffix -tile ".escapeshellarg($watermarkreal)." -draw \"rectangle 0,0 $tw,$th\" ".escapeshellarg($path);


At the bottom of image_processing.php, we need to replace the old ICC function 'function extract_icc'. Replace the whole function with this;

function extract_icc($infile) {
    global $icc_profile;

    // Locate Imagemagick, or fail this if it isn't installed

    $convert_fullpath = get_utility_path("im-convert");
    if ($convert_fullpath==false) {return false;}

    // Set directory for storing the ICC profile to the ResourceSpace iccprofiles folder
    $outfile = dirname(__FILE__) . '/../iccprofiles/' . $icc_profile .'.icc';

    // Extract ICC profile. Use [0] to extract a single profile from multi-layer PSD/PSBs
    $cmdout = run_command($convert_fullpath.' '.escapeshellarg($infile).'[0] '.escapeshellarg($outfile));

    // Check if file was extracted successfully
    if ((!file_exists($outfile)) || (filesize($outfile))==0){
        // The ICC profile extraction failed. So delete file.
        if (file_exists($outfile)){ unlink ($outfile); };
        return false;
    }

    if (file_exists($outfile)) { return true; } else { return false; }
}




Lastly, we need to replace some code in preview_preprocessing.php. I've not been able to test it thoroughly at the stage (not too sure what test data to throw at it?). We need to find the lines;

	# Preserve colour profiles?    
	$profile="+profile icc -colorspace ".$imagemagick_colorspace; # By default, strip the colour profiles ('+' is remove the profile, confusingly)
    if ($imagemagick_preserve_profiles) {$profile="";}

And replace with;

global $tonal_response_curve_compatibility, $tonal_response_curve_compatibility_options;

if ($tonal_response_curve_compatibility){
    // Set 'RGB' for compatibility for GraphicsMagick or ImageMagick v6.7.6-3 or earlier
    $tonal_response_curve_compatibility_options="RGB";
} else {
    // Set 'sRGB' for ImageMagick v6.7.6-4 or newer
    $tonal_response_curve_compatibility_options="sRGB";
}


We need to find any instances of $imagemagick_colorspace and replace it with $tonal_response_curve_compatibility_options


At the moment I've noticed that Photoshop EPS files do not retain their colour profile information due to a lack of appropriate code within preview_preprocessing.php. I will try to make something for this soon. Basically it will involve extracting the profile to re-add it after the EPS has been converted to non-linear sRGB and flattened.

Honestly I may not have time though, and this might be the end of what I can do for now. But I believe this to be a vast improvement on where it was, and should your testing go ok, perhaps we can integrate this into the ResourceSpace code?

Let me know what you think...

thanks,
Tristan.

Jeff Harmon

unread,
Aug 15, 2013, 12:00:25 AM8/15/13
to ResourceSpace
Wonderful!  Electric indeed!  We will test locally thoroughly with a large variety of file types, modes and bit depths, and report our findings.  Note that EPS, PS, and PDF files can use what's called PostScript color management, which is a different animal, and this may be causing you grief.  But it sounds like this is not the cause for your test files?

Congratulations on your effort and your dedication.  We won't let it be wasted.  Our team will test this, report to you and the rest of the community, then commit it in your name with rightful credit when it's ready.

This takes ResourceSpace to another level, truly.  Miraculous work.  <applause!>

Jeff

Jeff Harmon

unread,
Aug 15, 2013, 3:57:03 AM8/15/13
to ResourceSpace
Following these instructions, the variable $profile is no longer defined in image_processing, because we delete its definition with the prior ICC extraction code:   include/image_processing.php line 948: Undefined variable: profile

What would help immensely is if you could send me your working image_processing and preview_processing, so I can run a diff against base and really see the differences.  Please email them off-list?  Thanks so much!!

Jeff

Electric Art

unread,
Aug 15, 2013, 4:17:58 AM8/15/13
to resour...@googlegroups.com
Hey Jeff,

Seems I was too perhaps too quick. I'm currently testing v6.7.4-10 and am having problems, but it seems to be only with 16bit files - maybe this version of ImageMagick is broken.

I will try my best to fix it if I have time. On the upside it works great with v6.7.6-4 and above.

In regards to EPS files - Photoshop EPS files embed ICC profiles, as can newer PDFs. My test Photoshop EPS had a profile embedded, that I should have been able to extract (given the right code in the right place).

Thanks for your kind words!

Also, here are some small amends to the code I posted before (removing a superfluous +matte command);

In image_processing.php, just below the old experimental ICC code, we need to find the following lines and replace them;

Find this line;


$runcommand = $command ." +matte $profile -resize " . $tw . "x" . $th . "\">\" ".escapeshellarg($path);

And replace with this;

global $resize_prefix, $resize_suffix;
$runcommand = $command ." $profile $resize_prefix -resize " . $tw . "x" . $th . "\">\" $resize_suffix ".escapeshellarg($path);


Find this line;

$runcommand = $command ." +matte $profile -resize " . $tw . "x" . $th . "\">\" -tile ".escapeshellarg($watermarkreal)." -draw \"rectangle 0,0 $tw,$th\" ".escapeshellarg($path);

And replace with this;

$runcommand = $command ." $profile $resize_prefix -resize " . $tw . "x" . $th . "\">\" $resize_suffix -tile ".escapeshellarg($watermarkreal)." -draw \"rectangle 0,0 $tw,$th\" ".escapeshellarg($path);


Tristan.
...

Electric Art

unread,
Aug 15, 2013, 4:24:59 AM8/15/13
to resour...@googlegroups.com
Whoops. Sorry Jeff.

That's actually a simple fix. Find the line;

global $colour_management;

And replace with;

global $colour_management, $profile;

Sorry - I never noticed as I always had $colour_management set to true, which would initialise $profile. You should have only received that error if you did not have $colour_management set to true in config.php - is that correct?

Tristan.
...

Jeff Harmon

unread,
Aug 15, 2013, 4:25:34 AM8/15/13
to resour...@googlegroups.com
Hey there,

Why support old ImageMagicks for such a cutting edge feature?  Anyone wanting to turn on full blown color management is gonna have an ImageMagick that's pretty damn recent.

Also, not sure of a Q8 variant of ImageMagick handles 16-bit or higher. Not sure what it would do. You need a Q16, yes?

I beg of you to send me your working image_processing and preview_processing files. It will save years of my life.

Thanks!
Jeff



--
Jeff Harmon
Chief Executive Officer
Colorhythm LLC

Main Office:  +1 415-399-9921
Mobile:  +1 510-710-9590

--

Electric Art

unread,
Aug 15, 2013, 4:54:37 AM8/15/13
to resour...@googlegroups.com
Hey Jeff,

I guess because I wanted to keep compatibility with GraphicsMagick (if possible) as well as older versions of ImageMagick just because distributions such as Ubuntu Server LTS often have quite old versions of ImageMagick, but are still supported.

Anyway, it turns out I was thrown off track by a broken version of the older ImageMagick that I was testing with. Though I did uncover a few more bugs (related to the old version only). I've now fixed them. I'll post the final code here, and email you in a second with the two files you requested.

Final code to replace experimental ICC code in image_processing.php;

/* ----------------------------------------
    Colour Management section.
    Requires Exiftool and ImageMagick
    (GraphicsMagick is compatible however
    all functions may not work correctly)
   ----------------------------------------
*/

global $colour_management, $resize_prefix, $resize_suffix, $profile, $tonal_response_curve_compatibility, $tonal_response_curve_compatibility_options;


// If GraphicsMagick or Imagemagick v6.7.6-3 or earlier is being used, set appropriate colourspace option.
// In each case, this setting will tell ImageMagick or GraphicsMagick to assume a non-linear (sRGB) tonal response curve when converting if the source file is non-linear. Only needed if there is no embedded profile and no profile will be assigned.

if ($tonal_response_curve_compatibility){
    // Set 'RGB' for compatibility for GraphicsMagick or ImageMagick v6.7.6-3 or earlier
    $tonal_response_curve_compatibility_options="RGB";
} else {
    // Set 'sRGB' for ImageMagick v6.7.6-4 or newer
    $tonal_response_curve_compatibility_options="sRGB";
}

// Check if colour management is enabled

        if($tonal_response_curve_compatibility){

            $convert_profile=$icc_preview_options.' -colorspace '.$tonal_response_curve_compatibility_options.' -profile '.escapeshellarg($targetprofile);
        } else {

            $convert_profile=$icc_preview_options.' -profile '.escapeshellarg($targetprofile);
        }
    }

    // If $preserve_source_profiles_large_only=true; then 'scr' sizes and smaller will be converted to the target profile specified.
    if($preserve_source_profiles_large_only && ($id=="thm" || $id=="col" || $id=="pre" || $id=="scr")){
        // Preserve the embedded source profile then convert smaller sizes to target display profile.
        $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
        if($tonal_response_curve_compatibility){

            $convert_profile=$icc_preview_options.' -colorspace '.$tonal_response_curve_compatibility_options.' -profile '.escapeshellarg($targetprofile);
        } else {
    /*  ----------------------------------------
        This section determines behaviour of
        preservation of ICC profiles after
        conversion.
           ----------------------------------------
    */
   
        // If $preserve_target_profiles=false; we want to strip the profiles after conversion to save space
        if(!$preserve_target_profiles){
            // If $preserve_source_profiles is enabled, preserve all profiles
            // If $preserve_source_profiles_large_only is enabled, preserve only the profiles of larger previews
            if($preserve_source_profiles || ($preserve_source_profiles_large_only && $id!="thm" && $id!="col" && $id!="pre" && $id!="scr")){
                // Keep target profile.
                $strip_profile="";
            } else {
                // Strip target profile.
                $strip_profile=" +profile ic*";
                // Preserve the embedded source profile then convert smaller sizes to target display profile.
                $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
                if($tonal_response_curve_compatibility){

                    $convert_profile=$icc_preview_options.' -colorspace '.$tonal_response_curve_compatibility_options.' -profile '.escapeshellarg($targetprofile);
                } else {
        if($tonal_response_curve_compatibility){

            $convert_profile=$icc_preview_options.' -colorspace '.$tonal_response_curve_compatibility_options.' -profile '.escapeshellarg($targetprofile);
        } else {

            $convert_profile=$icc_preview_options.' -profile '.escapeshellarg($targetprofile);
        }
       
    /*  ----------------------------------------
        This section determines appropriate options
        to enable resize operations to take place
        in a linear colourspace to ensure accurate
        colours.
        See http://www.imagemagick.org/Usage/resize/#resize_colorspace
           ----------------------------------------
    */
        global $resize_prefix, $resize_suffix, $tonal_response_curve_compatibility, $colourspace, $profile, $icc_preview_options, $convert_profile;
        global $restore_profile, $assign_profile, $icc_path, $icc_transform_complete, $icc_preview_profile;                   
        // Convert linear file for display using target profile
        $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
        if($tonal_response_curve_compatibility){

            $convert_profile=$icc_preview_options.' -colorspace '.$tonal_response_curve_compatibility_options.' -profile '.escapeshellarg($targetprofile);
        } else {
    /*  ----------------------------------------
        This section determines behaviour of
        preservation of ICC profiles after
        conversion.
           ----------------------------------------
    */
   
        // If $preserve_target_profiles=false; we want to strip the profiles after conversion to save space
        if(!$preserve_target_profiles){
            // If $preserve_source_profiles is enabled, preserve all profiles
            // If $preserve_source_profiles_large_only is enabled, preserve only the profiles of larger previews
            if($preserve_source_profiles || ($preserve_source_profiles_large_only && $id!="thm" && $id!="col" && $id!="pre" && $id!="scr")){
                // Keep target profile.
                $strip_profile="";
            } else {
                // Strip target profile.
                $strip_profile=" +profile ic*";
                // Preserve the embedded source profile then convert smaller sizes to target display profile.
                $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
                if($tonal_response_curve_compatibility){

                    $convert_profile=$icc_preview_options.' -colorspace '.$tonal_response_curve_compatibility_options.' -profile '.escapeshellarg($targetprofile);
                } else {
    /*  ----------------------------------------
        This section determines behaviour of
        preservation of ICC profiles after
        conversion.
           ----------------------------------------
    */
   
        // If $preserve_target_profiles=false; we want to strip the profiles after conversion to save space
        if(!$preserve_target_profiles){
            // If $preserve_source_profiles is enabled, preserve all profiles
            // If $preserve_source_profiles_large_only is enabled, preserve only the profiles of larger previews
            if($preserve_source_profiles || ($preserve_source_profiles_large_only && $id!="thm" && $id!="col" && $id!="pre" && $id!="scr")){
                // Keep target profile.
                $strip_profile="";
            } else {
                // Strip target profile.
                $strip_profile=" +profile ic*";
                // Preserve the embedded source profile then convert smaller sizes to target display profile.
                $targetprofile = dirname(__FILE__) . '/../iccprofiles/' . $icc_preview_profile;
                if($tonal_response_curve_compatibility){

                    $convert_profile=$icc_preview_options.' -colorspace '.$tonal_response_curve_compatibility_options.' -profile '.escapeshellarg($targetprofile);
                } else {


Tristan.
...

Electric Art

unread,
Aug 15, 2013, 5:04:30 AM8/15/13
to resour...@googlegroups.com
Hey Jeff,

For some reason I got the impression a lot of ResourceSpace users preferred GraphicsMagick (as it is apparently faster) so I wanted to try my best to keep it compatible. We've never used GraphicsMagick ourselves as it doesn't (or at least when we last tried it didn't) have PSB support. But, like you say, this is a cutting-edge feature and so I suppose if you want to use it, you may have to upgrade to the latest ImageMagick!

Tristan.


On Thursday, August 15, 2013 6:25:34 PM UTC+10, Jeff Harmon wrote:
Hey there,

Why support old ImageMagicks for such a cutting edge feature?  Anyone wanting to turn on full blown color management is gonna have an ImageMagick that's pretty damn recent.

Also, not sure of a Q8 variant of ImageMagick handles 16-bit or higher. Not sure what it would do. You need a Q16, yes?

I beg of you to send me your working image_processing and preview_processing files. It will save years of my life.

Thanks!
Jeff



--
Jeff Harmon
Chief Executive Officer
Colorhythm LLC

Main Office:  +1 415-399-9921
Mobile:  +1 510-710-9590

             &nbs
...

Electric Art

unread,
Aug 15, 2013, 5:11:22 AM8/15/13
to resour...@googlegroups.com
Also, just thought it was important to note that the linear resize feature is probably best left off at the moment. It increases the time to generate previews for mostly very little benefit. It also doesn't work exactly how I'd like it to either (it can't handle CMYK conversions properly) because of some quirkyness of ImageMagick. If there was a good generic linear RGB profile in existence then I reckon I could get some nicer code happening for linear resizes as I could use it to facilitate better conversions using ImageMagick between linear and non-linear RGB, however I can't find one, and unfortunately I'm sure there are some licensing issues with taking the sRGB profile and changing it's tonal response curve to linear and redistributing it.

Tristan.


On Thursday, August 15, 2013 6:25:34 PM UTC+10, Jeff Harmon wrote:
Hey there,

Why support old ImageMagicks for such a cutting edge feature?  Anyone wanting to turn on full blown color management is gonna have an ImageMagick that's pretty damn recent.

Also, not sure of a Q8 variant of ImageMagick handles 16-bit or higher. Not sure what it would do. You need a Q16, yes?

I beg of you to send me your working image_processing and preview_processing files. It will save years of my life.

Thanks!
Jeff



--
Jeff Harmon
Chief Executive Officer
Colorhythm LLC

Main Office:  +1 415-399-9921
Mobile:  +1 510-710-9590

             &nbs
...

Electric Art

unread,
Aug 15, 2013, 5:48:15 AM8/15/13
to resour...@googlegroups.com
Arrrg... I think I broke something in those last couple of changes. Sorry. It's late and I'm making mistakes. I'll email you through an updated set of files hopefully tomorrow.

Very close!

Apologies.

Tristan.

Electric Art

unread,
Aug 15, 2013, 5:54:04 AM8/15/13
to resour...@googlegroups.com
False alarm! (I really am tired).

Turns out after I upgraded back to the latest ImageMagick version I forgot to turn tonal_response_curve_compatibility back to false. :)

That latest code I posted and emailed to you should be all good.

Tristan.

Electric Art

unread,
Aug 21, 2013, 8:49:13 PM8/21/13
to resour...@googlegroups.com
Hey Jeff,

Can you confirm if you received my email with the image_processing and preview_processing files? I believe there were some changes since the last version I posted here so it's important you have the latest. Also not sure if you received them at all at this stage?

Tristan.
...

Jeff Harmon

unread,
Aug 21, 2013, 10:39:55 PM8/21/13
to ResourceSpace
Confirmed!  My project is running long, and I haven't gotten to test them yet!  Sorry!  Next week.

Jeff


--

Jeff Harmon

unread,
Aug 27, 2013, 10:58:40 PM8/27/13
to ResourceSpace
We started testing today and so far.... perfect.  As in, perfect!  Tested some SWOP and Adobe RGB in Safari 6.0.5 and the results were pretty much identical to Adobe's rendering in Photoshop CC!  (Note that we are using a different CMM - Adobe's vs. LCMS, so some differences are expected.)

A LOT more testing will ensue - I'll put a number of staff on this, and we'll put it through its paces, including untagged, Lab, PSDs, PSBs, layered, with/without alphas etc.

I did turn off linear resize, FYI.  I have to assume the processing takes longer than before, and that we should not enable this by default, but for power users, this will be revolutionary!

Congratulations!!!!
Jeff

Electric Art

unread,
Aug 28, 2013, 12:34:44 AM8/28/13
to resour...@googlegroups.com
Hey Jeff, that's great news! I hope further testing works just as well for you.

An interesting note regarding the matching of colour vs Adobe's CMM, is that I found I had much more accurate preview conversions in certain situations with RGB files with ImageMagick when I used the NON black scaled version of the sRGB profile. They would match Adobe's almost exactly. The downside was that CMYK conversions then had milky blacks. This behaviour was annoying and didn't make sense to me, because the black point compensation option passed to ImageMagick '-black-point-compensation' should mean that the appearance should be the same, and the blacks adjusted anyway - well, at least according to my understanding and according to the information in this link;

http://www.color.org/srgbprofiles.xalter

The relevant excerpt from the above link;

The 'no black scaling' profile can be used with BPC on or off in the CMM. If it is used with BPC on the results should be the same as when using the 'black scaled' profile. If it is used with BPC off it will produce un-black-scaled media-relative colorimetry: if the source encoding has tones darker than the destination encoding black point they will be clipped, and if the source black point is higher than the destination black point the source black point will be accurately reproduced.

The same link also suggests that using the NON black scaled version should be more colour accurate - which, incidentally is what I found. It also suggests that differences in CMMs can be mostly negated by using the v4 versions of the sRGB profile. This I haven't tested, and potentially causes other problems (mostly related to compatibility with browsers and other programs).

Linear resize will increase the time taken to produce the previews, and for most images, very little benefit. I agree it should be off by default.

Glad to hear it's working well so far.

Tristan.

jeffreyhharmon

unread,
Aug 28, 2013, 1:07:28 AM8/28/13
to resour...@googlegroups.com
I'm familiar with those materials. Have you tried the 2.1 sRGB profile normally used by Adobe?  Maybe that would match their soft proof better.

Also, we do need to question "more accurate" being equal to "match Adobe," though it's a reasonable assumption!

J


--
Jeff Harmon
Chief Executive Officer
Colorhythm LLC

Main Office:  +1 415-399-9921
Mobile:  +1 510-710-9590

Electric Art

unread,
Aug 28, 2013, 3:45:43 AM8/28/13
to resour...@googlegroups.com
Hey Jeff,

No I hadn't thought to try that - good idea. I'll try and test that when I can.

Perhaps I should have said 'more accurate match' rather than just 'more accurate'. Regardless of matching Adobe's output, using the non-black scaled version of the profile included with ResourceSpace (where is this from by the way?) results in (as I see it) unexpected behaviour when used with the '-black-point-compensation'. I will test with other non-black-scaled versions of the sRGB profile, including Adobe's and the one from color.org and see if there is a difference. I wonder if it is;

a) A profile issue
b) An ImageMagic/LCMS issue
c) User error / intended behaviour and not an issue at all

Will let you know what I find out.

Tristan.
     &nb
...

Electric Art

unread,
Aug 28, 2013, 3:47:13 AM8/28/13
to resour...@googlegroups.com
Sorry I should clarify -

Unexpected behaviour when used with the '-black-point-compensation' when converting CMYK files to sRGB (non-black-scaled).

T.

Electric Art

unread,
Aug 28, 2013, 3:54:46 AM8/28/13
to resour...@googlegroups.com
I should also clarify that I am curious about the source of the included ICC profiles as I recently read this blog post (while doing my research for the colour management code I wrote);

http://www.oyranos.org/2011/11/quality-of-default-icc-profiles/

Whilst it seems it would probably not be an issue with sRGB profiles, it makes me wonder if there are potentially any problems with the included profiles?

Tristan.

jeffreyhharmon

unread,
Aug 28, 2013, 1:30:40 PM8/28/13
to resour...@googlegroups.com
Not sure, I'm only using the profiles provided by Adobe for bundling.

Jeff

--
Jeff Harmon
Chief Executive Officer
Colorhythm LLC

Main Office:  +1 415-399-9921
Mobile:  +1 510-710-9590

--

Electric Art

unread,
Aug 28, 2013, 8:39:42 PM8/28/13
to resour...@googlegroups.com
Hey Jeff,

Sorry, so are you saying that the profiles bundled with ResourceSpace that are included in the /iccprofiles directory when you install are Adobe profiles?

Tristan.
  &
...

jeffreyhharmon

unread,
Aug 28, 2013, 10:00:51 PM8/28/13
to resour...@googlegroups.com
No, they aren't. They're from the ICC. didn't mean to say that. I meant other than those  
J

--
Jeff Harmon
Chief Executive Officer
Colorhythm LLC

Main Office:  +1 415-399-9921
Mobile:  +1 510-710-9590

--

Electric Art

unread,
Aug 28, 2013, 10:25:22 PM8/28/13
to resour...@googlegroups.com
Ah ok great. Sorry for the confusion.

Tristan.
...

Electric Art

unread,
Aug 28, 2013, 10:46:14 PM8/28/13
to resour...@googlegroups.com
Hey Jeff,

Was musing some possible improvements for the future for the colour managment code, and have two thoughts and wondered what you thought.

1) There appears to already be a function written in image_processing.php to determine the installed version of ImageMagick. We could potentially use this to determine $tonal_response_curve_compatibility rather than having to have the user specify it - this would make it completely transparent to the user and they wouldn't have to worry about if they have ImageMagick version X installed or GraphicsMagick. This might also play and important role when ImageMagick 7 is released and depreciated options that are still in use in the ResourceSpace code could be transparently corrected depending upon which version of ImageMagick is installed. E.g. '+matte' is depreciated and will be invalid in ImageMagick 7. Also I believe the command 'convert' changes to 'magick' or similar with version 7. Anyway, starting to get a little off topic, but something worth considering.

2) It would be great if the profile name that is extracted in the colour management code could be stored and displayed in the resource view so that one could see what profile the original image resource has attached. Is this currently possible with the existing code of ResourceSpace? Or would we need to write some code to enable such a feature?

Tristan.
...

jeffreyhharmon

unread,
Aug 29, 2013, 12:23:49 AM8/29/13
to resour...@googlegroups.com
1) I don't believe version 7 includes such a radical departure from basic syntax? I've implied this before, but I personally don't care much about supporting a wide range of ImageMagicks and GraphicsMagicks, especially backward compatible. This is such an advanced feature that most people will not want - its largely contingent on using very specific browsers, for example - that I think you're being over-thorough. It also slows the whole algorithm down. 

2). You can map that to a field now using ExifTool. ExifTool supports a vast amount of metadata from ICC profiles, including those embedded in a file. 

-J


--
Jeff Harmon
Chief Executive Officer
Colorhythm LLC

Main Office:  +1 415-399-9921
Mobile:  +1 510-710-9590

--

Electric Art

unread,
Aug 29, 2013, 1:17:12 AM8/29/13
to resour...@googlegroups.com
Hey Jeff,

I could be wrong, but as I understand it, there are a number of big changes with ImageMagick 7. More information here;

http://www.imagemagick.org/script/porting.php#cli

Some relevant excerpts;

The "magick" command is the new primary command of the Shell API, replacing the old "convert" command. This allows you to create a 'magick script' of the form "#!/path/to/command/magick -script", or pipe options into a command "magick -script -, as abackground process.

Deprecated warning given, but will work (for now)


-/+matte
Replaced by -alpha Set/Off.

I read an ImageMagick forum post (which I cannot find now unfortunately) that suggests the +matte will be removed in v7.

I also did some more digging and found that 'convert' will still exist (for now), however it is no longer recommended as it potentially conflicts with other 'convert' commands on some platforms.

http://www.imagemagick.org/discourse-server/viewtopic.php?f=4&t=22934&p=101339&hilit=magick+convert#p101339

I guess I was trying to come up with a solution that would not only make it easier to deal with changes in newer versions, but also just as easily provide compatibility for older versions.

I'll try the mapping for the ProfileDescription - thanks for the tip - I thought this may be how to do it!

thanks again,
Tristan.
...

jeffreyhharmon

unread,
Aug 29, 2013, 1:58:59 AM8/29/13
to resour...@googlegroups.com, resour...@googlegroups.com
Wowsa!!  I am sad to be wrong this time (usually I like it - it's when I'm learning something!). 

It's great to have you on the team!!!

Jeff

--
Jeff Harmon
Chief Executive Officer
Colorhythm LLC

Main Office:  +1 415-399-9921
Mobile:  +1 510-710-9590

--

Electric Art

unread,
Aug 29, 2013, 2:35:29 AM8/29/13
to resour...@googlegroups.com
Hey Jeff,

I feel that perhaps you misunderstood my motivation to potentially create code to transparently determine correct command line options dependent upon the version of ImageMagick/GraphicsMagick installed? I believe it not so much about the colour management code, but more about providing a seamless experience for the user regardless of what colour management features they choose to use (if at all).

With the current setup (not including the new colour management code), if the user has an older version of ImageMagick, or they choose to run GraphicsMagick for the apparent speed benefits, then they need to explicitly define in config.php the correct command line options, otherwise they get extremely dark previews - then perhaps come here to the forum to ask how to make it work. If we wrote code that pre-defined a number of important command-line options based upon the determined version of ImageMagick/GraphicsMagick, we could create a transparent working solution for a wide install base, as well as start to build in future-proofing for upcoming changes to ImageMagick - without having users need to change or add anything to config.php when and if they upgrade ImageMagick.

A solution like this would also help people who choose to have the new colour management code switched off, as the command line compatibility options for older versions of ImageMagick/GraphicsMagick are required whether one would choose to use the new colour management features or not.

This could also help users who cannot upgrade ImageMagick for whatever reason (e.g. shared hosting)?

My proposed solution would be something like this (obviously this is not working code);

if $imagemagick_version < 6.7.6-4 then
   $magick_command="convert"
   $tonal_response_curve_compatibility_options="RGB"
   $alpha_options="+matte"
end if

if $imagemagick_version > or = 6.7.6-3 then
   $magick_command="convert"
   $tonal_response_curve_compatibility_options="sRGB"
   $alpha_options="-alpha off"
end if

if $imagemagick_version > or = 7.0.0 then
   $magick_command="magick"
   $tonal_response_curve_compatibility_options="sRGB"
   $alpha_options="-alpha off"
end if

We could add other options as appropriate if needed.

If this happened once, at the very beginning somewhere of the algorithm, do you feel a solution like this would still slow the algorithm that significantly?

What do you think?

Tristan.
     &
...

Electric Art

unread,
Aug 29, 2013, 3:01:37 AM8/29/13
to resour...@googlegroups.com
Thanks Jeff! Glad to be able to help out.

It's a shame about ImageMagick 7 and the changes - hopefully they won't end up being too much of a pain in the neck.

Tristan.
...

Jeff Harmon

unread,
Aug 29, 2013, 3:04:27 AM8/29/13
to ResourceSpace
No, I was wrong, you were right.  I think this is a good idea.  It's just also a pain in the arse!!

J


--

Electric Art

unread,
Aug 29, 2013, 4:55:10 AM8/29/13
to resour...@googlegroups.com
No problem. Wasn't trying to push my idea, and I understand it will probably be a pain to implement, but I felt like I should explain my idea a little more clearly.

I'm hoping it shouldn't be too hard to implement, as the function to determine the version of ImageMagick is already written (I have not tested it though). Replacing instances of '+matte' with $alpha_options should not be too difficult either I imagine. And the changing of the 'convert' command may just be changing the path to ImageMagick in config.php to /usr/bin/magick? Since it needs to be specified anyway?

It may be easier than it seems? Well here's hoping anyway!

Tristan.
<br
...

Electric Art

unread,
Oct 21, 2013, 8:00:40 PM10/21/13
to resour...@googlegroups.com
Hey Jeff.

Just wondering if there had been any progress on your testing of the colour management code I wrote and if by any chance it had been implemented into ResourceSpace yet? If there are any issues with it I'm more than happy to help. We're looking to upgrade to the latest ResourceSpace and I'm wondering if I'll need to manually add the colour management code back in after upgrade...

Thanks!
kind regards,
Tristan.
                $strip_profile=&
...

jeffreyhharmon

unread,
Oct 21, 2013, 8:14:27 PM10/21/13
to resour...@googlegroups.com
We'll hustle to release it this week. If it's deemed ready. I'll keep you posted!

J

--
Jeff Nova
Chief Executive Officer
Colorhythm LLC

Main Office:  +1 415-399-9921
Mobile:  +1 510-710-9590

--

Jeff Nova

unread,
Nov 6, 2013, 8:10:37 PM11/6/13
to ResourceSpace
Axel just committed r5045, which affects your work.  Should we try to make your code compatible?  It seems to me that your code replicates Axel's, and then some, but I'd like your input.


Thanks!  So sorry this is taking longer than anyone would like.

Jeff


--

Electric Art

unread,
Nov 7, 2013, 2:38:48 AM11/7/13
to resour...@googlegroups.com
Hey Jeff,

Thanks for letting me know. Axel's code looks great, and addresses (what I see as) a fundamental issue of ResourceSpace in that, by default, it ignores ICC profiles. It addresses it in a very succinct way. However I believe there are a few caveats.

It appears that Axel's code (if I'm reading it correctly) actually changes the behaviour of

$imagemagick_preserve_profiles

so that if

$default_icc_file

is defined, then it will convert to that profile, and embed that profile. So $imagemagick_preserve_profiles only acts to preserve the source profile to the end user as long as $default_icc_file is NOT set. Stripping the profile then requires adding

+profile *

to

$default_icc_file

e.g.


$default_icc_file='my-sRGB-profile.icc +profile *'

In effect, it is operating the same as my code if you set;

$colour_management=true;
$icc_preview_profile = 'sRGB_IEC61966-2-1_black_scaled.icc';
$preserve_target_profiles=true;

Then, if you want to strip the profile to save space, with my code you simply change;
$preserve_target_profiles=false;

However, unfortunately I don't believe Axel's code will handle PSDs correctly due to ImageMagick handling of PSDs (which require special profile extraction handling) or linear files (32bit EXR, HDR, e.t.c.) correctly as they require special attention. LAB files and even CMYK and Gray files may present a problem with certain versions of ImageMagick. Since Axel's code does not explicitly define the target colourspace with ImageMagick when converting using $default_icc_file, some files may not convert correctly. You may find that ImageMagick will assign the sRGB profile to an untagged CMYK file for example (rather than convert to it), but will not convert the file to RGB, and the profile is therefore invalid and ignored (even though it gets embedded). I believe this depends upon the version of ImageMagick and whether or not the source image has a profile embedded or not. From memory, the behaviour of -profile has historically changed from version to version of ImageMagick (also these changes are not very well documented) and depending upon if there is a profile embedded or not.

My code is obviously more complex, but I believe it accounts for all variations I came across in my testing regarding embedded profiles, colour spaces and ImageMagick/GraphicsMagick version differences (with the exception of ImageMagick 7 changes).

I don't know that there is a way of making my code 'compatible' as such, as it would really have to replace Axel's code to work properly. Axel's code is potentially a very simple, quick and ideal fix, however, from the extensive testing I did with my own code (which started in a very similar place), I found that simple unfortunately did not account for many potential issues that came up (as mentioned just before). I'm sure it will work for RGB files quite well, though I might argue that it makes the nature of '$imagemagick_preserve_profiles' perhaps confusing. A lot of my code is simply there to deal with the appropriate handling required for the different cases that would come up - tagged/untagged/colourspace/PSD/Linear/e.t.c.

Did you find any issues with my code?

I have looked at making some optimisations to my code, but ran out of time. After testing, the optimisations, while neater, made very little real-world difference anyway, so I haven't followed it up. The plan was, at the same time, to add support for ImageMagick 7...

So far my code provides the following options/features;

• Auto-assigning profiles based on camera metadata
• Assigning of profiles to untagged images as defined by the user
• Handling of PSD/PSB profile extraction (necessary for correct ICC conversion)
• Handling of linear, LAB and other colour spaces
• Handling of ImageMagick/GraphicsMagick version variations
• Warns the user if a required profile is missing
• Option of resizing in linear space for more accurate colour during resize
• Options to preserve the source profile for all images or for larger than screen sizes only
• Option for very simple colour management, converting to sRGB and stripping the profile (similar to current ResourceSpace behaviour, but with accurate colour conversion but no additional space).


So I think Axel's code is essence is good. However my concerns are;

• It may not work correctly for untagged CMYK files, tagged/untagged PSDs, Linear or LAB files.
• The implementation with  $imagemagick_preserve_profiles and $default_icc_file, especially regarding how to strip profiles after conversion (which has previously been the default behaviour for ResourceSpace) is perhaps a little confusing - obviously my code has a lot more options, however I feel it would be better to ideally hide options like '+profile *' to the end user, considering how easy it is to make a typo, and the fact that a new version of ImageMagick may change these kinds of options. My solution makes it a simple true/false for the user - e.g. $preserve_target_profiles=true;


It's up to you. To be honest though, I spend many, many, many hours on writing this code and testing it, and I believe it addresses almost every possible issue with ICC handling that I could throw at it and I'd hate to see it be set aside.


kind regards,
Tristan.
...

Axel Dörfler

unread,
Nov 7, 2013, 8:16:40 AM11/7/13
to resour...@googlegroups.com
Hey Tristan,

On Thu, Nov 7, 2013 at 8:38 AM, Electric Art <em...@electricart.com.au> wrote:
It appears that Axel's code (if I'm reading it correctly) actually changes the behaviour of
$imagemagick_preserve_profiles

You misread that part; I did not change its behavior.

The rest of your findings might be correct, though. I have not tested it with PSD files, just with a great number of CMYK files.
I'm not sure what you mean by untagged CMYK file - do you have an example file for this handy?
 
So I think Axel's code is essence is good. However my concerns are;

• It may not work correctly for untagged CMYK files, tagged/untagged PSDs, Linear or LAB files.
• [...] - obviously my code has a lot more options, however I feel it would be better to ideally hide options like '+profile *' to the end user, considering how easy it is to make a typo, and the fact that a new version of ImageMagick may change these kinds of options. My solution makes it a simple true/false for the user - e.g. $preserve_target_profiles=true;

I haven't looked at your code; I wasn't really aware of it, and currently have no time to look into them either.
In any case I agree with you that it's a simple solution, and could easily be replaced by a more sophisticated solution. Your solution seem to be just that, and I wouldn't mind at all seeing my code replaced with a better implementation.
HTH

Bye,
   Axel.

Electric Art

unread,
Nov 7, 2013, 8:50:38 AM11/7/13
to resour...@googlegroups.com
Hi Axel,

Thanks so much for the reply.

Much apologies - I see that your implementation preserves source profiles for sizes other than screen / thumb. I did read it incorrectly.

When I say untagged CMYK, I mean a CMYK file without an embedded profile. I believe this is an issue because ImageMagick uses '-profile' in two ways - if the source file has an profile embedded (is tagged), then it uses the embedded profile for the conversion, and '-profile' is used to define the target profile for the conversion. If the source file does NOT have a profile embedded (is untagged), then '-profile' is used to assign a profile to the image. An additional '-profile' is then required to then define the target profile.

Hence, if you feed your code an untagged image, your code will assign sRGB, rather than converting to it. Result for an untagged RGB is incorrect colour if the source file is in any colour space other than sRGB, and the result for an untagged CMYK or Gray image is that an RGB profile is assigned to a CMYK or Gray file, without converting it, and is ignored by programs trying to read the ICC profile for the image as it is invalid (wrong colour space).

To make matters slightly more complicated, I don't know with which version ImageMagick actually implemented support for using embedded profiles from tagged images. Previously I believe one had to extract the profile first (perhaps why the old experimental ICC code attempts to extract ICC profiles from all images).

Does that make sense?

For more information see here;
http://www.imagemagick.org/Usage/formats/#color_profile

The relevant extract;

Raf Lenaerts pointed out the following rules in using the "-profile" operator within ImageMagick...
If there is no embedded profile then the first "-profile" is the input profile. A second "-profile" then defines the output profile.
If there is an embedded profile then a single of "-profile" operator will immediately define the output profile.

Hope this helps.

I believe my code handles the difference between untagged and tagged images correctly. My code definitely is a more sophisticated solution, but as I said, most of the code is actually to deal with situations like this, to make sure it correctly handles (hopefully) all potential situations handed to it....

kind regards,
Tristan.

Electric Art

unread,
Nov 7, 2013, 9:02:13 AM11/7/13
to resour...@googlegroups.com
Hi Axel,

For reference, the specific problem with PSD/PSB files is that there is an ICC profile stored for potentially each pixel layer in the Photoshop file. Depending upon the file, this could be hundreds of ICC profiles. For some reason, while it is possible to correctly extract a single ICC profile from a PSD/PSB using convert, ImageMagick does not seem to be able to assume a single embedded profile for the PSD/PSB formats correctly, and, as a result, one is required to first extract a profile from the PSD/PSB, and then re-assign that profile as the input profile when making the conversion. Unfortunately this seems to be the only way to get it to work - at least until ImageMagick change their code (which may not happen).


kind regards,
Tristan.

On Friday, November 8, 2013 12:16:40 AM UTC+11, Axel Dörfler wrote:

Electric Art

unread,
Nov 7, 2013, 9:41:05 AM11/7/13
to resour...@googlegroups.com
Hi Axel,

I believe that it is also important to note, that because of the '-profile' usage issue I mentioned, I believe your code will NOT convert previews for untagged CMYK files to RGB, and the files will remain in the source colour space (in this case CMYK). Instead, an sRGB profile will be erroneously assigned. The same is likely true for Gray, Linear and LAB files. In these cases, colour is likely to be way off base, as browsers don't really like displaying files in colour spaces other than RGB...

Obviously I have not tested this, however if true, I would consider it a big issue.

kind regards,
Tristan.

Axel Dörfler

unread,
Nov 7, 2013, 10:15:07 AM11/7/13
to resour...@googlegroups.com
Hi Tristan,

On Thu, Nov 7, 2013 at 2:50 PM, Electric Art <em...@electricart.com.au> wrote:
When I say untagged CMYK, I mean a CMYK file without an embedded profile. I believe this is an issue because ImageMagick uses '-profile' in two ways - if the source file has an profile embedded (is tagged), then it uses the embedded profile for the conversion, and '-profile' is used to define the target profile for the conversion. If the source file does NOT have a profile embedded (is untagged), then '-profile' is used to assign a profile to the image. An additional '-profile' is then required to then define the target profile.
[...]

Thanks for the explanation! Do you have example test files you are able to share (CMYK, but also LAB)? I couldn't find any so far.
ImageMagick's profile handling is definitely non-optimal.

Bye,
   Axel.

Jeff Nova

unread,
Nov 7, 2013, 2:56:56 PM11/7/13
to ResourceSpace
I just sent you a link privately containing a rather exhaustive set of test files, CMYK, Lab, RGB, 8 and 16-bit.  Oops, as I write this, I realize I didn't send any grayscale.  Will do that post haste!

Jeff


It is loading more messages.
0 new messages