How to save a JPG image in 4: 2: 0 format using Imagick?

Google Pagespeed can convert RGB images to YUV 4: 2: 0 color space. I would like to do the same in PHP using imagick.

In short, why you need 4: 2: 0:

"This filter reduces the color sampling of jpeg images to 4: 2: 0. Vision is much more sensitive to changes in brightness than changes in hue or saturation and 4: 2: 0 color sampling allows us to preserve luminance data while decreasing hue and saturation data. by 3/4. It can significantly reduce the size of the image, little impact on perception. "

I tried changing the color space with imagemagick to YUV, but it doesn't work well at all! The white background turns green and the rest of the colors are wrong, plus inverted brightness.

The following code is not helpful, but it shows a few things that I have tried.

In google format created by mod_pagespeed, the resulting images look great in the browser. This is what I hope to achieve, images that are meant for the web.

    $image_info = getimagesize($source_file);
    $im = new Imagick();
    $im->readImage($source_file);
    $profiles = $im->getImageProfiles('*', false);
    $has_icc_profile = (array_search('icc', $profiles) !== false);
    if ($has_icc_profile === false) {
        $icc_srgb = file_get_contents(Mage::getBaseDir('var') . DS . 'metodo' . DS . 'demo_data' . DS . 'AdobeRGB1998.icc');
        $im->profileImage('icc', $icc_srgb);
        unset($icc_srgb);
    }
    //$im->setImageColorspace(1);
    $im->setInterlaceScheme(Imagick::INTERLACE_PLANE);
    $im->setImageCompressionQuality(85);
    //$im->stripImage(); 
    $im->setImageColorspace(11);
    $im->thumbnailImage($this->_imageSrcWidth, $this->_imageSrcHeight);
    //$im->negateImage(false, Imagick::CHANNEL_ALL);
    $im->stripImage();
    $im->writeImage($fileName);

      

+3


source to share


2 answers


I was intrigued by the lack of documentation on the Imagick :: setSamplingFactors method (see my comment ), so I tried to figure it out.

Using the Imagick :: identImage method, it became clear that the Imagick library does not use the 4: 2: 0 notation for chroma oversampling, but something like "1x1,1x1,1x1". At http://www.ftgimp.com/help/C/filters/jpeg.html he made it clear that '1x1,1x1,1x1' translates to 4: 4: 4 and '2x2,1x1,1x1' to 4: 2: 0. Since the Imagick :: setSamplingFactors method requires an array as an argument, I tried the following, which worked successfully:



$img = new Imagick($source_file)
$img->setSamplingFactors(array('2x2', '1x1', '1x1'));
$im->writeImage($fileName);

      

+4


source


Maybe not technically an answer, but too awkward to format as a comment and might help find an answer.

You can do things like this, which can give some idea of ​​how to use the parameters and what they seem to do:

convert input.jpg -colorspace YUV out.jpg
convert input.jpg -colorspace YUV -sampling-factor 4:2:2 out442.jpg
convert input.jpg -colorspace YUV -sampling-factor 4:2:0 out420.jpg

      



then you can see the resulting files for different settings. The output seems to correlate very well with sampling, and this default fetch for IM is 4: 4: 4, as this is sized when I don't provide -sampling-factor

:

ls -l out*
-rw-r--r--  1 mark  staff  105563 26 Nov 10:23 out.jpg
-rw-r--r--  1 mark  staff   77230 26 Nov 10:23 out410.jpg
-rw-r--r--  1 mark  staff   81755 26 Nov 10:24 out411.jpg
-rw-r--r--  1 mark  staff   82835 26 Nov 10:23 out420.jpg
-rw-r--r--  1 mark  staff  105563 26 Nov 10:25 out444.jpg

      

This link might help.

+1


source







All Articles