使用Alpha通道进行Sonata Media PNG压缩

时间:2018-01-17 09:08:52

标签: symfony png gd sonata-media-bundle

SonataMediaBundle使用以下设置增加PNG图像大小:

video_image:
    providers:
        - sonata.media.provider.image
    formats:
        medium: { width: 1306, quality: 100 }

原始图像尺寸为246Kb(具有相同的宽度和高度),“调整大小”图像的尺寸为3Mb。这是因为quality: 100设置了png_compression_level => 0

如果我设置quality: 0,PNG尺寸几乎正常(图像看起来非常好),但JPG压缩使图像看起来像印象派。

所以我用PNG图像的自定义缩放器解决了它。

但是设置png_compression_level => 9时压缩图像的大小仍然不理想,它是664Kb。

将PNG图像转换为PNG8解决了这个问题,并且尺寸变得非常好 - 233Kb(甚至比原始图像还要小),但我在alpha通道上遇到了一些麻烦。

大多数透明压缩的图像都很好,但有些图片已损坏:

原始图像(透明bg为白色)

  

a white border

压缩图片

  

the same but smaller

这是我的自定义缩放器(代码有点难看,因为它只是草稿):

<?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()));
    }
}

我的代码有问题,或者我应该采用其他方式吗?

我想要的只是调整JPG和PNG文件的大小,而不会增加尺寸,也不会有明显的质量损失。

更新

  1. imagetruecolortopalette将alpha值重置为0或127,没有2-126值。因此图像的边缘松动了它们的光滑度。我正在尝试修复它为每个像素设置旧的alpha值,但还没有成功

  2. 上述图片上的人工制品只是小尺寸调整(此配置中的'拇指')

    formats:
        wide: { width: 1306, quality: 95}
        mobile: { width: 640, quality: 95}
        thumb: { height: 50 , quality: 95}
    
  3. 所以我认为麻烦在于复合一些不完全透明的像素

1 个答案:

答案 0 :(得分:1)

我尝试了不同的GD功能,但没有得到满意的结果。

所以我找到的最好方法是使用Imagick代替GD:

services.yml:

    sonata.media.resizer.custom:
        class: AppBundle\Resizer\CustomResizer
        arguments: [@sonata.media.adapter.image.imagick, 'outbound', @sonata.media.metadata.proxy]

的appbundle \调整器\ CustomResizer:

<?php

namespace AppBundle\Resizer;

use Sonata\MediaBundle\Resizer\SimpleResizer;

class PngCustomResizer extends SimpleResizer
{
}

config.yml:

sonata_media:
    providers:
        image:
            resizer: sonata.media.resizer.custom