Imagick - převod palety CMYK na RGB v PHP
Petr Wiedemann, 10. prosinec 2009
Imagick je rozšíření knihovny ImageMagick pro PHP. Podpora formátů závisí na konfiguraci knihovny ImageMagick. Například pro Gentoo mám v souboru package.use následující obsah.
media-gfx/imagemagick png jpeg jpeg2k tiff gs lcms
Pro změnu barevné palety obrázku nabízí Imagick metodu setImageColorspace. Pro její zjištění naopak metodu getImageColorspace.
Obě metody pracují s jednou z předdefinovaných konstant. Barevné paletě CMYK odpovídá konstanta Imagick::COLORSPACE_CMYK. Pouhé volání předchozích metod sice můžeme využít pro změnu palety, ovšem v některých případech může dojít k nepříjemné změně barev obrázků. Na následujících obrázcích je zdroj a výsledek pouhého volání metody setImageColorspace(Imagick::COLORSPACE_SRGB).
Problém je způsoben absencí ICC profilu ve zdrojovém obrázku. Abychom zachovali barvy při změně palety, musíme nahrát CMYK profil metodou profileImage.
Následující kousek skriptu změní barevnou paletu ze CMYK na SRGB a zmenší obrázek na maximální velikost strany 600 bodů.
<?php
/**
* Otevre obrazek, zmeni paletu na sRGB a prevede do JPEG.
*
* @param string $src_file Zdrojovy obrazek.
* @param string $dst_file Cilovy obrazek.
*/
function ExportImage($src_file, $dst_file)
{
try
{
// Otevreni obrazku.
$i = new Imagick($src_file);
// Zjisteni palety.
$cs = $i->getImageColorspace();
// Zmena palety
if ($cs == Imagick::COLORSPACE_CMYK)
{
// Nacteni profilu v obrazku.
$profiles = $i->getImageProfiles('*', false);
// Kontrola, jestli obrazek obsahuje icc profil.
$has_icc_profile = (array_search('icc', $profiles) !== false);
// Obrazek icc profil neobsahuje. Nacteni cmyk profilu ze souboru.
if ($has_icc_profile === false)
{
$icc_cmyk = file_get_contents('USWebCoatedSWOP.icc');
$i->profileImage('icc', $icc_cmyk);
}
// Zmena barevne palety, CMYK -> SRGB.
$icc_rgb = file_get_contents('sRGB_v4_ICC_preference.icc');
$i->profileImage('icc', $icc_rgb);
$i->setImageColorspace(Imagick::COLORSPACE_SRGB);
}
// Zmena velikosti obrazku, pokud nektera
// jeho strana presahuje 600 bodu.
if ($i->getImageWidth() > 600 || $i->getImageHeight() > 600)
{
$i->resizeImage(600, 600, Imagick::FILTER_LANCZOS, true, true);
}
// Nastaveni formatu.
$i->setImageCompression(Imagick::COMPRESSION_JPEG);
$i->setImageCompressionQuality(95);
$i->setImageFormat('jpeg');
// Ulozeni obrazku.
$i->writeImage($dst_file);
$i->clear();
$i->destroy();
$i = null;
}
catch (ImagickException $e)
{
echo 'Chyba pri uprave obrazku: '.$e->getMessage();
}
}
?>
Zdroje, ze kterých jsem čerpal: