SonataMediaBundle increases PNG image size with this settings:
video_image:
providers:
- sonata.media.provider.image
formats:
medium: { width: 1306, quality: 100 }
Original image size is 246Kb (with same width and height), and the size of the "resized" image is 3Mb. It happens because of quality: 100
that sets png_compression_level => 0
.
If I set quality: 0
, PNG size is almost ok (and image looks very ok), but JPG compression makes image look like impressionism.
So I solved it with a custom resizer for PNG images.
But with setting png_compression_level => 9
the size of compressed image is still not ideal, it's 664Kb.
Converting PNG image to PNG8 solved this, and the size became very ok - 233Kb (that is even smaller than the original image), but I got some troubles with the alpha channel.
Most of images with transparency compressed fine, but some of them were corrupted:
original image (it is white on transparent bg)
compressed image
This is my custom resizer (the code is a little bit ugly, because it's just a draft):
<?php
namespace AppBundle\Resizer;
use Gaufrette\File;
use Imagine\Gd\Image;
use Sonata\MediaBundle\Model\MediaInterface;
use Sonata\MediaBundle\Resizer\SimpleResizer;
class PngCustomResizer extends SimpleResizer
{
public function resize(MediaInterface $media, File $in, File $out, $format, array $settings)
{
/** @var Image $image */
$image = $this->adapter->load($in->getContent());
$thumbnail = $image->thumbnail($this->getBox($media, $settings), $this->mode);
$resource = $thumbnail->getGdResource();
$width = $thumbnail->getSize()->getWidth();
$height = $thumbnail->getSize()->getHeight();
// convert to png8 with alpha
$img = imagecreatetruecolor($width, $height);
$bga = imagecolorallocatealpha($img, 0, 0, 0, 127);
imagecolortransparent($img, $bga);
imagefill($img, 0, 0, $bga);
imagecopy($img, $resource, 0, 0, 0, 0, $width, $height);
imagetruecolortopalette($img, false, 255);
imagealphablending($img, false);
imagesavealpha($img, true);
$optimizedImage = new Image($img, $image->palette(), $image->metadata());
// set quality 0 to set png compression = 9
$content = $optimizedImage->get($format, ['quality' => 0]);
$out->setContent($content, $this->metadata->get($media, $out->getName()));
}
}
Is there something wrong with my code, or may be I should use another way?
All I want is resize both JPG and PNG files without increasing size and without noticeable loss of quality.
UPDATE
imagetruecolortopalette
resets alpha values to 0 or 127, without 2-126 values. So image's edges loose their smoothness. I'm trying to fix it setting old alpha value for each pixel, but don't have success yetartefacts on the above-mentioned image appear just in small size resizing ('thumb' in this config)
formats: wide: { width: 1306, quality: 95} mobile: { width: 640, quality: 95} thumb: { height: 50 , quality: 95}
so I presume that the trouble is in compounding some not-fully-transparent pixels