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为白色)
压缩图片
这是我的自定义缩放器(代码有点难看,因为它只是草稿):
<?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文件的大小,而不会增加尺寸,也不会有明显的质量损失。
更新
imagetruecolortopalette
将alpha值重置为0或127,没有2-126值。因此图像的边缘松动了它们的光滑度。我正在尝试修复它为每个像素设置旧的alpha值,但还没有成功
上述图片上的人工制品只是小尺寸调整(此配置中的'拇指')
formats:
wide: { width: 1306, quality: 95}
mobile: { width: 640, quality: 95}
thumb: { height: 50 , quality: 95}
所以我认为麻烦在于复合一些不完全透明的像素
答案 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