天涯家园HomeH天涯家园HomeH

- 网络编程,php编编程,php代码,WEB精品软件资源分享学习家园

PHP图片压缩(TinyPNG在线API)和(使用Imagick扩展)

  PHP图片压缩(TinyPNG在线API)和(使用Imagick扩展)

1、调用TinyPng网站提供的API

            TinyPNG 使用智能有损压缩技术来减小 WEBP、JPEG 和 PNG 文件的文件大小。 通过有选择地减少图像中的颜色数量,存储数据所需的字节更少。 效果几乎不可见,但它在文件大小上有很大的不同!

        1)、官网地址:https://tinypng.com/

              github:https://github.com/tinify/tinify-php

        2)、API key申请地址:https://tinypng.com/developers 

               调用这个网站提供的API需要申请一个API key,输入邮箱,它会把包含API key的网址发到你邮箱,打开其中的链接就可以看到属于你的API key了;

        3)、调用这个网站的API进行图片压缩的话,每个月前500张是免费的,之后要收费;

        4)、虽然域名是tinypng,但是操作 WEBP, JPEG and PNG files大小。

    

        composer安装

1
D:\wamp\www\tinypng>composer require tinify/tinify

        

        使用API之前,先用api秘钥进行身份验证。编辑文件index.php,添加内容:

1
2
3
4
5
require_once("vendor/autoload.php");
 
\Tinify\setKey("*****QF8jqvp5GDjvRKrjXvfGd9*****");
$source = \Tinify\fromFile("test.jpeg");
$source->toFile("1.jpeg");

        

        可以看到test.jpeg,文件生成了1.jpeg文件。同事文件大小也小了很多。打开压缩图片,图片质量还是很高。


        网上TinyImg类库

        (1) class TinyImg 是我自己写的一个类,包含下面三个方法:

            《1》压缩文件夹下全部图片

            public function compressImgsFolder($key,$inputFolder,$outputFolder)是用来压缩文件夹 $inputFolder (目录路径)中的图片,保存到文件夹 $outputFolder (目录路径)中,其中 $key 就是上边申请的API key;

            《2》压缩单张图片

            public function compressImg($key, $input, $output) 将输入的图片 $input (图片路径)进行压缩并保存到图片 $output (图片路径);

            这个函数中的代码是从官网调用示例中提取出来的,初始的时候,line40是被注释掉的,直接使用会出错,我们需要

            <1> 去掉注释; 

            <2> 到http://curl.haxx.se/ca/cacert.pem把这个网页(文本)保存(Ctrl+S)到class TinyImg 类文件的同一目录下;

            《3》获取文件夹下全部图片的名字 

            public function getFiles($filedir) 获取$filedir下的全部图片的名字列表;

<?php
/**
 * Created by PhpStorm.
 * User: Zhang He
 * Date: 2015/6/8
 * Time: 10:14
 */
 
class TinyImg {
    /*Compress all images in folder $inputFolder and save final images in folder $outputFolder*/
    public function compressImgsFolder($key,$inputFolder,$outputFolder){
        $images = $this->getFiles($inputFolder);
        if(empty($images)){
           return false;
        }
        foreach($images as $image){
            $input = $inputFolder."\\".$image;
            $output = $outputFolder."\\".$image;
            print($input."<br>");
            print($output."<br>");
            $this->compressImg($key,$input,$output);
        }
        return true;
    }
    /*Compress one image $input and save as $output*/
    public function compressImg($key, $input, $output){
        $url = "https://api.tinify.com/shrink";
        $options = array(
            "http" => array(
                "method" => "POST",
                "header" => array(
                    "Content-type: image/png",
                    "Authorization: Basic " . base64_encode("api:$key")
                ),
                "content" => file_get_contents($input)
            ),
            "ssl" => array(
                /* Uncomment below if you have trouble validating our SSL certificate.
                   Download cacert.pem from: http://curl.haxx.se/ca/cacert.pem */
                "cafile" => __DIR__ . "/cacert.pem",
                "verify_peer" => true
            )
        );
 
        $result = fopen($url, "r", false, stream_context_create($options));
        if ($result) {
            /* Compression was successful, retrieve output from Location header. */
            foreach ($http_response_header as $header) {
                if (strtolower(substr($header, 0, 10)) === "location: ") {
                    file_put_contents($output, fopen(substr($header, 10), "rb", false));
                }
            }
        } else {
            /* Something went wrong! */
            print("Compression failed<br>");
        }
    }
    //get all files' fullname in $filedir
    public function getFiles($filedir){
        $files = [];
        $dir = @dir($filedir);
        while(($file = $dir->read())!= false){
            if($file != "." and $file != ".."){
                $files[] = $file;
            }
        }
        $dir->close();
        return $files;
    }
}

      (2) 测试代码


<?php
include("TinyImg.php");
/**
 * Created by PhpStorm.
 * User: Zhang He
 * Date: 2015/6/8
 * Time: 11:45
 */
$tinyImg = new TinyImg();
$key = "****HDtB9xgcry4tdcgbqkhLHs0****";//这里是你申请的API key
$input = "D:\\wamp\\www\\zh\\testTinyPng\\ibg_large_test"; //这个文件夹下的文件会被压缩
$output = "D:\\wamp\\www\\zh\\testTinyPng\\ibg_small_test";//压缩的结果会被保存到这个文件夹中
$tinyImg->compressImgsFolder($key,$input,$output);

2、使用PHP的Imagick扩展

    2.1、PHP图像处理扩展包GD、Imagick、Gmagick对比

            GD属于老古董级别的,丢掉吧,效率很低,而且压缩的图片体积很大。

            Imagick是个不错的选择,在PHP的图片处理扩展中表现的很显眼。不管是对jpg或png的静态图片,还是对gif的动态图片,压缩和缩小放大尺寸都非常给力。

            Gmagic没怎么试过,而GraphicsMagick据说也是相当的给力,但网上很多评论基本上都是对效率的一些评测。

            用Imagick替代php的GD库, 安装流程:https://cksite.cn/article/165


测试用例:

<?php
//读取pdf页面的第一页
$im = new Imagick('more.pdf');
//设置输出图片的格式
$im->setImageFormat('png');
//输出图片
header('Content-Type:image/png');
echo $im;


   2.2、优化前代码

            这个代码中的压缩功能,主要依靠

                line18的 $imagick->cropThumbnailImage($width, $height);

                和line20的 $imagick->resizeImage($width, $height, Imagick::FILTER_LANCZOS, 1, true);

            实现的压缩。

/**
 * 缩小图片尺寸.
 *
 * @param $image 待处理的二进制图片
 * @param $width 处理后图片尺寸的宽度(px)
 * @param $height 处理后图片尺寸的高度(px)
 * @param $crop 是否裁剪图片
 *
 * @return 处理好的二进制图片
 */
function resize($image, $width, $height, $crop) {
    $imagick = new \Imagick();
    $imagick->readImageBlob($image);
    $w = $imagick->getImageWidth();
    $h = $imagick->getImageHeight();
    if ($w > $width || $h > $height) {
        if ($crop) {
            $imagick->cropThumbnailImage($width, $height);
        } else {
            $imagick->resizeImage($width, $height, \Imagick::FILTER_LANCZOS, 1, true);
        }
    }
    $processed_image = $imagick->getImageBlob();
    return $processed_image;
}


    2.3 优化后代码

/*
* User:Zhang He
* Time:20150610
* Function:Resize $src image and store as $dst
* */
function resize($src, $dst, $width=320, $height=320, $crop=false) {
 
        $imagick = new \Imagick($src);
 
        $w = $imagick->getImageWidth();
        $h = $imagick->getImageHeight();
 
        if ($w > $width || $h > $height) {
 
            if ($crop) {
                $imagick->cropThumbnailImage($width, $height);
            } else {
                $imagick->resizeImage($width, $height, \Imagick::FILTER_CATROM, 1, true);
            }
        }
 
        $imagick->setImageFormat('JPEG');
        $imagick->setImageCompression(\Imagick::COMPRESSION_JPEG);
        $a = $imagick->getImageCompressionQuality() * 0.75;
 
        if ($a == 0) {
            $a = 75;
        }
 
        $imagick->setImageCompressionQuality($a);
        $imagick->stripImage();
 
        $imagick->writeImage($dst);
        $imagick->clear();
        $imagick->destroy();
    }
     
//调用    
$src = "xxxxx/imagick/test.jpeg";    //xxxxx 为物理路径
$dst = "xxxxx/imagick/1.jpeg";
resize($src, $dst);

(1)参考文章

        优化代码集中在line22-line31,至于为什么这样优化以及优化达到的效果,可以看原文链接(代码没有格式化):

        http://www.6a8a.com/2011/PHP_0402/939.html 

(2)函数的作用

        每个函数的含义可以到 http://php.net/manual/zh/class.imagick.php   查看,下面我列出最主要的几个函数及其解释。

        bool Imagick::setImageFormat ( string $format )

        为图片设置指定格式 支持的格式以及对应的库,可以查看 http://www.imagemagick.org/script/formats.php   。


        bool Imagick::setImageCompression ( int $compression )

        设置图片压缩的类型 Imagick中定义的常量,可以查看 http://php.net/manual/en/imagick.constants.php   。


        bool Imagick::setImageCompressionQuality ( int $quality )

        设置图片压缩质量


        bool Imagick::stripImage ( void )

        去掉图片的所有配置和设置,如Exif


        bool Imagick::resizeImage ( int $columns , int $rows , int $filter , float $blur [, bool $bestfit = false ] )

        通过过滤器将图片缩放到期望的尺寸。

        过滤器也在Imagick定义的常量页面可以找到:

        http://php.net/manual/zh/imagick.constants.php#imagick.constants.filters

        Note: 参数 bestfit 的特性在 Imagick 3.0.0 中已改变。在此版本以前,当目标尺寸设为 400x400 时,原尺寸为 200x150 的图像将不会被改变。自 Imagick 3.0.0 起,源图像将会被放大到 400x300 因为这将更好的适合目标尺寸。当使用参数 bestfit 时,必须同时给出宽度和高度。


        bool Imagick::cropThumbnailImage ( int $width , int $height )

        生成一个指定大小的缩略图,首先放大或缩小图片,然后裁剪出一个指定的区域从图片中间。


示例代码:

<?php
/* Read the image */
$im = new imagick( "test.png" );
/* create the thumbnail */
$im->cropThumbnailImage( 80, 80 );
/* Write to a file */
$im->writeImage( "th_80x80_test.png" );
?>

(3)选择哪个过滤器?

        将一个5906*5906的图片压缩至1181*1181所需时间对比:

FILTER_POINT took: 0.334532976151 seconds
FILTER_BOX took: 0.777871131897 seconds
FILTER_TRIANGLE took: 1.3695909977 seconds
FILTER_HERMITE took: 1.35866093636 seconds
FILTER_HANNING took: 4.88722896576 seconds
FILTER_HAMMING took: 4.88665103912 seconds
FILTER_BLACKMAN took: 4.89026689529 seconds
FILTER_GAUSSIAN took: 1.93553304672 seconds
FILTER_QUADRATIC took: 1.93322920799 seconds
FILTER_CUBIC took: 2.58396601677 seconds
FILTER_CATROM took: 2.58508896828 seconds
FILTER_MITCHELL took: 2.58368492126 seconds
FILTER_LANCZOS took: 3.74232912064 seconds
FILTER_BESSEL took: 4.03305602074 seconds
FILTER_SINC took: 4.90098690987 seconds


        因此,CATROM在保证压缩效果接近LANCZOS的同时,耗时也比较短。

(4)最简洁代码示例

        我找到最简洁的例子是这个:

/*
Imagick::setImageCompression
Imagick::setImageCompressionQuality
Imagick::stripImage
Imagick::thumbnailImage
Imagick::writeImage
*/
 
<?php
    $image = 'image.jpg';
    $directory = '/path/to/image';
    $image_location = $directory . "/" . $image;
    $thumb_destination = $directory . "/t" . $image;
    $compression_type = Imagick::COMPRESSION_JPEG;
 
    $im = new Imagick($image_location);
    $thumbnail = $im->clone;
 
    $thumbnail->setImageCompression($compression_type);
    $thumbnail->setImageCompressionQuality(40);
    $thumbnail->stripImage();
    $thumbnail->thumbnailImage(100,null);
    $thumbnail->writeImage($thumb_destination);
?>

php_imagick实现图片剪切、旋转、锐化、减色或增加特效的方法

        https://www.jb51.net/article/58489.htm


来自冷暖自知一抹茶ckhttp://www.cksite.cn


相关文章