Google Pagespeed can convert RGB images to the YUV 4:2:0 colourspace. I would like to do the same in PHP using imagick.
Briefly, on why 4:2:0 is desired:
"This filter reduces the color sampling of jpeg images to 4:2:0. Human vision is much more sensitive to changes in brightness than changes in hue or saturation, and 4:2:0 color sampling allows us to keep brightness data while reducing the amount of hue and saturation data by 3/4. This can significantly reduce the image size while having only a small effect on perception."
I have tried to change the colorspace with imagemagick to YUV but it is not working at all well! The white backdrop goes to green and the rest of the colours are wrong, plus inverted luminance.
The following code is useless, but it shows a few of the things I have tried.
With the Google format created by mod_pagespeed the resultant images look fine in a browser. That is what I am hoping to achieve, images that are 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);
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::identifyImage
method it became clear that the Imagick library doesn't use the 4:2:0 notation for chroma subsampling, but something like '1x1,1x1,1x1'. At http://www.ftgimp.com/help/C/filters/jpeg.html (20180608: no longer available, archived here) it's made clear that '1x1,1x1,1x1' translates to 4:4:4, and '2x2,1x1,1x1' to 4:2:0. As the Imagick::setSamplingFactors
method requires an array as its argument I tried the following, which worked successfully:
$img = new Imagick($source_file)
$img->setSamplingFactors(array('2x2', '1x1', '1x1'));
$im->writeImage($fileName);
Maybe not technically an answer, but too awkward to format as a comment, and it may help find the answer.
You can do this sort of thing that may provide some insight as to how to use 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 filesizes for a variety of settings. It does seem that the output filesizes correlate pretty well with the sampling, and that IM's default sampling is 4:4:4 since that matches the size when I don't provide any -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 may help.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With