Laurens Schuitemaker
Laurens Schuitemaker

Reputation: 233

Convert image from RGB to CMYK with Imagick

I'm trying to convert RGB images to CMYK, because they need to be printed. I'm using this code:

<?php
$filePath = 'rgb.jpg';

// First save image as png
$image = new Imagick($filePath);
$image->setImageCompression(Imagick::COMPRESSION_UNDEFINED);
$image->setImageCompressionQuality(0); 
$image->setImageFormat("png");
$filePath = 'rgb.png';
$image->writeImage($filePath);
$image->clear();
$image->destroy();
$image = null;

// Convert colors
$image = new Imagick($filePath);
$image->stripImage();
$image->setImageColorspace(Imagick::COLORSPACE_CMYK);
$image->setImageCompression(Imagick::COMPRESSION_UNDEFINED);
$image->setImageCompressionQuality(0); 
$image->setImageFormat("png");
$filePath = 'cmyk.png';
$image->writeImage($filePath);

$image->clear();
$image->destroy();
$image = null;


$fileUrl = 'http://www.product-designer.nl/rgb2cmyk/cmyk.png';
?>
CMYK Image:<br/>
<img src="<?php echo $fileUrl; ?>" width="400" /><br /><br />
<?php
$fileUrl = 'http://www.product-designer.nl/rgb2cmyk/rgb.png';
?>
RGB Image:<br/>
<img src="<?php echo $fileUrl ?>" width="400" />

You can see the result on http://product-designer.nl/rgb2cmyk I don't know how, but somehow the colors on the image become inverted. I need to convert the image but the colors need to be as close to the RGB colors as possible.

Does anyone know how to do this?

Thanks

Upvotes: 5

Views: 12128

Answers (3)

profport
profport

Reputation: 141

Possible reason is that RGB is additive colorscheme and CMYK is subtractive colorscheme. I.e. we can convert RGB to CMYK using this formulas:

C = 255 - R;
M = 255 - G;
Y = 255 - B;

It looks like "how to invert colors". So in this case we should also figure out K value.

To avoid it we can use ICC-profiles.

One of the possible solutions:

$image = new Imagick('img/test.jpg');
$profiles = $image->getImageProfiles('*', false);
if (!array_search('icc', $profiles)) {
    // Without this code Photoshop cannot open image with original icc-profile
    $icc_rgb = file_get_contents('profiles/AppleRGB.icc');
    if ($image->profileImage('icc', $icc_rgb))
        echo '<br>Changed!';
    unset($icc_rgb);
}
// don't use this code, it leads to inverted image
//$image->setImageColorspace(Imagick::COLORSPACE_CMYK);
// tiff format supports CMYK colorscheme
$image->setFormat('tiff');
$image->setImageCompression(Imagick::COMPRESSION_UNDEFINED);
$image->setImageCompressionQuality(0);
// We can download profiles here http://www.adobe.com/support/downloads/thankyou.jsp?ftpID=4075&fileID=3790
$icc_cmyk_profile_path='profiles/USWebCoatedSWOP.icc';

$icc_cmyk = file_get_contents($icc_cmyk_profile_path);
if ($image->profileImage('icc', $icc_cmyk))
    echo '<br>Changed!';
unset($icc_cmyk);
// Drops all profiles, so we comment it
//$image->stripImage();
if ($image->writeImage('img/test_cmyk.tiff'))
    echo '<br>Save!';
$image->clear();
$image->destroy();

Filesize is changed, e.g. from 72Kb to 1.4Mb .

Upvotes: 0

Kevin Florida
Kevin Florida

Reputation: 6771

Okay, so this is a tricky issue. I had the same problem and it took me days to solve this one. You need to negateImage(), please see my example and make sure you only do it for php 5.3.x as this issue is unique to that php vs.

$range = $jpeg->getQuantumRange();
$php_vs_arr = preg_split("/\./", phpversion());
$php_vs = $php_vs_arr[0] . '.' . $php_vs_arr[1];
if ($jpeg->getImageColorspace() == Imagick::COLORSPACE_CMYK) {

    //make sure cmyk color-space is set correctly
$jpeg->setImageColorspace(12);

// then we add an RGB profile
$icc_rgb = file_get_contents(FRAMEWORK_PATH . DS . 'color' . DS . 'AdobeRGB1998.icc');
$jpeg->profileImage('icc', $icc_rgb);
unset($icc_rgb);

//set color space to rgb
$jpeg->setImageColorspace(13);

//fix gamma, hue, saturation, brightness
if($php_vs < 5.3) {
    //ADJUST GAMMA BY 2.0 for 5.2.x
    $jpeg->levelImage(0, 2.0, $range['quantumRangeString']);
} else {
    //php 5.3 hack FOR INVERTED COLORS
    $jpeg->negateImage(false, Imagick::CHANNEL_ALL);
}

}
$jpeg->stripImage();

Note: my Imagick object is obviously $jpeg

Also, you will need to download the AdobeRGB1998.icc profile from the Adobe website, just do a google search for it.

I hope this helps, please mark it as the correct answer as a lot of folks have trouble with this.

Upvotes: 1

Roman Nazarkin
Roman Nazarkin

Reputation: 2229

Take a look here:

<?php 
// don't use this (it inverts the image) 
//    $img->setImageColorspace (imagick::COLORSPACE_RGB); 

if ($img->getImageColorspace() == Imagick::COLORSPACE_CMYK) { 
   $profiles = $img->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(dirname(__FILE__).'/USWebUncoated.icc'); 
       $img->profileImage('icc', $icc_cmyk); 
       unset($icc_cmyk); 
   } 
   // then we add an RGB profile 
   $icc_rgb = file_get_contents(dirname(__FILE__).'/sRGB_v4_ICC_preference.icc'); 
   $img->profileImage('icc', $icc_rgb); 
   unset($icc_rgb); 
} 

$img->stripImage (); // this will drop down the size of the image dramatically (removes all profiles) 
?>

Upvotes: 3

Related Questions