利用Imagick+php对图片进行优化(一)
微wx笑 2022-03-21【编程语言】 2 0关键字: php imagick
严格图片缩放顾名思义,将图片进行严格缩放到规定尺寸,允许图片变形。 严格切图 严格按照指定尺寸进行切图 大头贴举例说明,原图尺寸(1500*1000),需求尺寸(1000*800),利用该方法进行处
严格图片缩放
顾名思义,将图片进行严格缩放到规定尺寸,允许图片变形。 严格切图 严格按照指定尺寸进行切图 大头贴
举例说明,原图尺寸(1500*1000),需求尺寸(1000*800),利用该方法进行处理时首先将图片以最小缩放的方式缩放,然后再将图片切割到需求尺寸,即先将图片缩成1200*800,再进行切割。
自定义缩放
调用人员指定需求尺寸,同时指定缩放模式(按较大边进行缩放还是按照较小边进行缩放)……
添加水印
顾名思义……
实现示例
添加水印
代码
方案1(处理动态gif有问题):
1 $im = new Imagick();//初始化一个IM对象
2 $im->readImage("/home/ben/xiao2.gif");//将带处理图片读入IM对象
3 $water = new Imagick();//再初始化一个IM对象,用于临时存储水印图
4 $water->readImage("/home/ben/watermark.png");//读入水印图
5 for($i = 0;$i < $im->getNumberImages();$i++)//由于gif是多帧图片,需要一帧帧处理
6 {
7 $im->setImageIndex($i);//设定当前待处理帧
8 $im->compositeimage($water,Imagick::COMPOSITE_OVER,0,0);//合并水印
9 }
10 //file_put_contents("/home/ben/result.gif",$im->getImagesBlob(),FILE_APPEND);//输出方案1
11 $im->writeImages("/home/ben/result3.gif",true);//输出方案2
2 function addWatermarkOnAllImgs($im,$water,$x,$y)
3 {
4 $format = strtolower($im->getImageFormat());
5 $color_transparent = new ImagickPixel("transparent"); //透明色
6 7 $dest = new Imagick();
8 foreach($im as $img)
9 {
10 $page = $img->getImagePage();//获得当前图片属性
11 $tmp = new Imagick();
12 $tmp->newImage($page['width'], $page['height'], $color_transparent, $format);//生成一张同大小的透明图片
13 $tmp->compositeImage($img, Imagick::COMPOSITE_OVER, $page['x'], $page['y']);//合并当前图片
14 $tmp->compositeImage($water,Imagick::COMPOSITE_OVER,$x,$y);//合并水印
15 16 $dest->addImage($tmp);//将图片添加进新的IM容器
17 $dest->setImagePage($tmp->getImageWidth(), $tmp->getImageHeight(), 0, 0);//设定图片的几何属性
18 $dest->setImageDelay($img->getImageDelay());//设定图片延迟
19 $dest->setImageDispose($img->getImageDispose());//设定动画处理方式
20 }
21 $dest->coalesceImages();//合并IM容器中的所有图片
22 $dest->writeImages("/home/ben/addwater.gif",true);
23 return true;
24 }
25 $src = new Imagick();
26 $src->readImage("/home/ben/xiao2.gif");
27 $water = new Imagick();
28 $water->readImage("/home/ben/watermark.png");
29 addWatermarkOnAllImgs($src,$water,0,0);
处理结果
1.原始图片
2.处理结果
2.1 方案一
2.2 方案二
注意事项
从以上处理结果可以看出,如果不逐帧进行处理会造成水印时隐时现的现象,为此在处理多帧图片时必须注意以下几点:
(1)处理多帧图片时必须循环得到各帧图片,然后进行相关处理;
(2)输出图片时(writeImages或getImagesBlob)一定注意image的复数形式,不然只会得到当前一帧静态图片,而非动态gif动画。
(3)动画处理方式(disposal method):
a)None--不进行处理。选择此方式时,下一帧的内容会直接覆盖在当前帧的内容上面。
b)Restore to Background--恢复背景色。此选项会首先擦除当前帧的图像内容,然后恢复到背景色或背景图案(如果背景是透明的,就恢复成透明),接下来在显示下一帧的内容。此选项常用在背景透明的动画上。
c)Restore to Previous--恢复上一帧。此选项会擦除当前帧的内容,然后恢复上一帧的内容,接下来在显示下一帧的内容。
两种方案的比较:
从处理结果可以清楚的看出不同,其原因正如http://wxw850227.iteye.com/blog/402085中所述------动画的每一帧图片大小不一定相同,采用方案一会造成图片因添加水印位置的不统一而发生错乱
gif图片调整大小
代码
function resizeImage($filename,$width,$height)
{
$src = new Imagick();
$src->readImage($filename);
$framenum = $src->getNumberImages();
if($framenum>1)
{
$format = strtolower($src->getImageFormat());//获得图片格式,备用
$dest = new Imagick();
$color_transparent = new ImagickPixel("transparent"); //透明色
foreach($src as $img)
{
$page = $img->getImagePage();
$tmp = new Imagick();
$tmp->newImage($page['width'], $page['height'], $color_transparent, $format);//在临时IM对象中生成一张同大小透明新图
$tmp->compositeImage($img, Imagick::COMPOSITE_OVER, $page['x'], $page['y']);//合并原图
$tmp->resizeimage($width,$height,Imagick::FILTER_UNDEFINED,0.75,false);//重设图片大小
$dest->addImage($tmp);//将处理后的图片放入输出IM对象中
$dest->setImagePage($tmp->getImageWidth(), $tmp->getImageHeight(), 0, 0);//设定当前图片大小
$dest->setImageDelay($img->getImageDelay());//设定图片延迟
$dest->setImageDispose($img->getImageDispose());//设定动画处理方式
}
$dest->coalesceImages();//合并所有图片
$dest->writeImages("/home/ben/resize.gif",true);
}
else
{
$src->resizeimage($width,$height,Imagick::FILTER_UNDEFINED,0.75,false);
$src->writeImages("/home/ben/resize.gif",true);
}
}
resizeImage("/home/ben/xiao.gif",200,200);
处理结果
注意事项
也许有人会说,简单的缩放干嘛搞这么复杂直接采用如下的方式逐帧缩放不就完了?
for($i=0;$i<$framenum;$i++)
{
$src->setImageIndex($i);
$src->resizeimage($width,$height,Imagick::FILTER_UNDEFINED,0.75,false);
}
有人提出了对gif动画逐帧缩放时存在的问题:
(1)透明动画的问题
(2)帧图片比显示尺寸小,并且有坐标控制的问题,直接缩小会使得动画完全乱掉
并给出了上述解决办法,故借鉴别人的繁琐但有效的处理方式。
附加几点注意事项:
1.resizeimage()可以利用第四个参数来增加模糊效果,=1相当于没有添加效果;<1,相当于锐化图片,使图片更清晰;>1,其值越大就会越模糊;=0时,是无穷大的模糊,也就是变成一片黑……0.75是一个经验值,利用该值可以调整绝大多数图片因缩放所带来的模糊。
2.有关resizeimage与scaleImage():二者均可以用于图片缩放,不同之处在于:Resizing the image changes the dimensions of the image without applying a transformation to the existing contents. Scaling the image will stretch the existing contents to the new dimensions.用事实说话吧:
如下图为用scale处理后的同一张图,与resize处理后的效果非常明显(够恶心的哈):
3.一种错误的处理方式:
3.1 code
$format = strtolower($src->getImageFormat());
$dest =new Imagick();
$color_transparent = new ImagickPixel("transparent"); //透明色
$src_page = $src->getImagePage();
$src_width = $src_page['width'];
$src_height = $src_page['height'];
$rate_w = $width/$src_width;
$rate_h = $height/$src_height;
foreach($src as $img)
{
$page = $img->getImagePage();
// $img->resizeimage($page['width']*$rate_w,$page['height']
*$rate_h,Imagick::FILTER_UNDEFINED,1,false);
// $img->resizeimage($width,$height,Imagick::FILTER_UNDEFINED,1,false);
$img->setImagePage($page['width']*$rate_w,$page['height']*$rate_h,$page['x']*$rate_w,$page['y']*$rate_h);
$page = $img->getImagePage();
$tmp = new Imagick();
$tmp->newImage($page['width'], $page['height'], $color_transparent, $format);
$tmp->compositeImage($img, Imagick::COMPOSITE_OVER, $page['x'], $page['y']);
// $tmp->resizeimage($width,$height,Imagick::FILTER_UNDEFINED,1,false);
$dest->addImage($tmp);
$dest->setImagePage($tmp->getImageWidth(), $tmp->getImageHeight(), 0, 0);
$dest->setImageDelay($img->getImageDelay());
$dest->setImageDispose($img->getImageDispose());
}
$dest->coalesceImages();
$dest->writeImages("/home/ben/zoomres1.gif",true);
3.2 处理结果
3.3 原因分析
与可行代码的差异描述:
可行代码是将当前图片合并到一新的IM容器中,然后对该图片进行缩放,最后将该图片合并;上述代码的操作步骤为:先将当前图片进行缩放,再新建一个IM容器,将缩放后的图片合并到IM容器的透明图上,最后将所有图片合并。可以预见这样处理会发生坐标偏移,尝试用setImagePage来控制图片坐标,仍不对……原因未明~~
大头贴效果
明显可以看出缩放切割效果~
转自:http://blog.sina.com.cn/s/blog_6bf82eb20100w5lr.html
本文为转载文章,版权归原作者所有,不代表本站立场和观点。