A rant + some useful code in the end. On CMYK to RGB image conversion and why would anyone even use CMYK for the Web in the first place. Some modern browsers actually display the CMYK images. Some older ones DO NOT. Also, CMYK thumbnails are twice as large (on average) than the converted RGB thumbnails. Oh, and using CMYK for screen display is fucking retarded.
Once upon a time, there was this shiny thing everyone was excited about called "the print magazine". You probably heard of it -- hell, if you're old enough -- you might've even held one or two in your hands. It was beautiful. And the techniques, expertise and experience required to produce the final product were non-trivial to say the least. Back in those days, people in print worked with the CMYK color model. They still do.
Life was good. All was dandy and along came this thing called the electronic age. Now, if you're consuming your media via an electronic system (and you are, increasingly, using only those), chances are it's using an RGB color model. But, print people still use CMYK. Even just comparing the two is an interesting read in itself, and could easily take you hours if you're thorough.
...is using RGB. So, which color model would you use if you were about to save an image that's supposed to be displayed on an electronic system? Obviously a trick question, eh? It can't be that simple, can it?
Well, it can. And it is. Except when humans are involved.
In a large enough organisation, any developer's job description over time gravitates towards the above. Instead of, you know, developing cool stuff, you're forced to "re-invent the wheel". Really. Photoshop's "Save for Web" feature came out with Photoshop 5.0 (May 1998, so, yeah, 12 years ago). Ever since its inception "save for web" wouldn't let you save a CMYK image. It silently converts it to RGB, no questions asked.
It seems, though, not everyone is using Photoshop. So you as a developer finally have a problem to solve! Let's help the ones not using Photoshop to not shoot themselves in the foot. And you come up with something. And It works. Yay!
Then, after a while, someone notices the colors are little off. Here's the dialogue:
"I e-mailed you a link, can you open it please?"
"Sure, let me just stop working instantly on whatever I was doing and devote myself fully to whatever you wish to discuss right now because you have nothing else to do."
"Haha. Ok, open it please, I need to show you something."
"The whole idea of auto-converting CMYK images was done for one reason only: so that visitors don't get broken images in Internet Explorer when someone accidentally uploads a CMYK image without using their brain. Not as a Photoshop replacement."
[upon clicking the link] "Ok, so the images are not identical, I've warned you about that. If you want Photoshop quality results, use Photoshop."
"Is there anything else I can help you with apart from explaining that your entire publishing process is horribly broken and utterly stupid and I can't really do much about it?"
[giving you a blank stare]
"kthxbai! We should have lunch sometime soon!"
CMYK thumb | RGB thumb | |
---|---|---|
16 Kb |
8 Kb |
(Yes -- I agree -- for a few lines of PHP, the conversion is fucking fantastic! Not to mention that the thumb is visible in every browser known to man kind.) |
When you wish to explain complex stuff to disinterested people, use a feature matrix. The stupider the comparison, the better the matrix! Here's why we use only RGB images for our websites and how to explain it if someone asks you:
IE6 | IE7 | IE8 | Opera 10.5 | Safari 5 | Safari 4 | Firefox 3.6 | Chrome 5 | |
---|---|---|---|---|---|---|---|---|
CMYK | ||||||||
RGB |
Image displays fine | |
Image doesn't display at all | |
Some weird stuff going on. Inverted colorspace (or so it appears -- check the screenshot) | |
Unknown / not tested yet |
Here's some sample code to convert a CMYK image to RGB (using PHP5 in this case):
<?php
// filenames
$img_path = 'img/';
$cmyk_img = $img_path . 'i-r-cmyk.jpg';
$cmyk_thumb = $img_path . 'i-r-cmyk-thumb.jpg';
$rgb_img = $img_path . 'i-r-rgb.jpg';
$rgb_thumb = $img_path . 'i-r-rgb-thumb.jpg';
// thumb dimensions
$thumb_w = 100;
$thumb_h = 100;
try {
$im = new Imagick($cmyk_img);
} catch (ImagickException $e) {
die($e->getMessage());
}
$clone = $im->clone();
// create the cmyk thumbnail so we can compare them in IE (cmyk vs rgb)
$clone->cropThumbnailImage($thumb_w, $thumb_h);
$clone->writeImage($cmyk_thumb);
$clone->destroy();
/**
* If it's a CMYK image, let's try converting it to RGB in order for
* it to be visible in Internet Explorer.
*/
if ($im->getImageColorspace() == Imagick::COLORSPACE_CMYK) {
// we get the image profiles
$profiles = $im->getImageProfiles('*', false);
// we're only interested if ICC profile(s) exist
$has_icc_profile = (array_search('icc', $profiles) !== false);
// if it doesnt have a CMYK ICC profile, we add one
if ($has_icc_profile === false) {
$icc_cmyk = file_get_contents('USWebUncoated.icc');
$im->profileImage('icc', $icc_cmyk);
unset($icc_cmyk);
}
// then we add an RGB profile
$icc_rgb = file_get_contents('sRGB_v4_ICC_preference.icc');
$im->profileImage('icc', $icc_rgb);
/**
* Here's an interesting tidbit: for some reason that's currently
* beyond me, the only way to actually get the images to not be
* negatives on *nix, and still show up as RGB in IE6,
* is to avoid explicitly setting the colorspace to rgb.
* Just adding the two profiles above seemed to do the
* trick. Fun. On Windows it worked "as expected" even with
* the uncommented line below.
*/
// $im->setImageColorSpace(Imagick::COLORSPACE_RGB);
unset($icc_rgb);
// save the rgb image to disk
try {
$im->writeImage($rgb_img);
} catch (Exception $e) {
die($e->getMessage());
}
}
/**
* Let's create the RGB thumbnail, save it to disk and output
* it to the browser.
*/
try {
// create the rgb thumbnail
$im->cropThumbnailImage($thumb_w, $thumb_h);
$im->writeImage($rgb_thumb);
// header('Cache-Control: no-cache');
// header('Expires: -1');
header('Content-Type: image/jpeg');
header('Content-Length: ' . filesize($rgb_thumb));
$file = file_get_contents($rgb_thumb);
die($file);
} catch (Exception $e) {
die($e->getMessage());
}
P.S. The .icc profiles are available from Adobe (of course, check your EULA and whatnot). OTOH, there's some interesting stuff here.
MMX©zytzagoo