PHP压缩图片到指定的KB

PHP压缩图片到指定的KB


PHP压缩图片主要是用imagejpeg()函数实现的, 官方文档

function imagejpeg($image, $filename = null, $quality = null) { }
参数:
image
由图象创建函数(例如imagecreatetruecolor())返回的图象资源。
filename
文件保存的路径,如果未设置或为 NULL,将会直接输出原始图象流。
如果要省略这个参数而提供 quality 参数,使用NULL。
quality
quality 为可选项,范围从 0(最差质量,文件更小)到 100(最佳质量,文件最大)。默认为 IJG 默认的质量值(大约 75)。

返回值:
成功时返回 TRUE, 或者在失败时返回 FALSE。

quality 参数可以调整图片的质量,以此来压缩图片,该参数的范围是0-100.
我一开始想到的是一直循环使用这个方法,同时检测文件大小,直到文件大小符合要求位置,可是遇到几个坑:

  1. 发现每次使用 filesize() 方法获取到的文件大小都一样,后来翻官方文档发现这样一段话:Note: 此函数的结果会被缓存。参见 clearstatcache() 以获得更多细节。原来 filesize() 方法的结果会缓存,使用 clearstatcache() 函数可以清楚该缓存。
  2. 发现几个循环下来,得到的图片是被损坏的或者有马赛克模样的。分析后我认为是以下原因导致的:前一个保存图片的函数还没有结束,下一个保存图片的函数就已经执行了,导致图片损坏。

经过优化得到以下压缩图片到指定的KB的函数。算法原理:循环以一定的质量保存图片到一个临时文件,当图片大小小于或等于目标大小时跳出循环,获取图片文件大小前执行 clearstatcache() 函数,跳出循环后删除临时文件。临时文件名需各不相同,以免出现上面说的第二个问题。

原代码如下:

<?php

//把当前目录的test.jpg压缩到50kb
compressImage('./test.jpg', 50);

/**
 * 压缩图片
 * 
 * @param string $filename 图片文件路径
 * @param int $maxFileSize 需要将图片压缩图片到最大多少KB
 * @return int -1 压缩失败|0 未压缩|1 压缩成功
 */
function compressImage($filename, $maxFileSize = 150)
{
    if (empty($filename) || $maxFileSize < 0 || !is_file($filename)) {
        return 0;
    }
    clearstatcache(); //filesize函数的结果会被缓存,使用此函数清除文件状态缓存
    $filesize = filesize($filename) / 1024; //filesize函数获得的是字节数,除以1024为KB数
    if ($filesize <= $maxFileSize) {
        return 0;
    }
    if ($filesize > 1024) {
        $i = 80;
    } elseif ($filesize > 500) {
        $i = 90;
    } else {
        $i = 99;
    }
    $tempDir = "E:\\tmp\\"; //临时文件存放文件夹
    if (!is_dir($tempDir)) { //文件夹不存在,创建
        mkdir($tempDir);
    }
    $tmpFile = ''; //临时文件
    $tmpFileList = []; //临时文件数组
    do {
        if ($i <= 0) {
            return -1;
        }
        if ($filesize > 1024) {
            $step = 5;
        } elseif ($filesize > 500) {
            $step = 3;
        } else {
            $step = 2;
        }
        $imageResource = getImageResources($filename); //获取图片文件资源
        $tmpFile = $tempDir . uuid() . '.jpg'; //临时文件
        imagejpeg($imageResource, $tmpFile, $i); //保存质量为$i的图片文件
        imagedestroy($imageResource); //销毁图片资源
        $tmpFileList[] = $tmpFile;
        $i -= $step;
        clearstatcache();
        $filesize = filesize($tmpFile) / 1024;
        echo $i . ' ' . $filesize . PHP_EOL;
    } while ($filesize > $maxFileSize);
    copy($tmpFile, $filename); //替换源图片
    foreach ($tmpFileList as $tmpFile) { //删除临时文件
        if (is_file($tmpFile)) {
            @unlink($tmpFile);
        }
    }
    return 1;
}
/**
 * 获取图像资源
 *
 * @param $filename 图片路径
 * @return null|resource 图片资源
 */
function getImageResources($filename)
{
    $fileInfo = @getimagesize($filename);
    $type = $fileInfo[2];
    $imgResource = null;
    switch ($type) {
        case 1:
            $imgResource = imagecreatefromgif($filename);
            break; // GIF
        case 2:
            $imgResource = imagecreatefromjpeg($filename);
            break; // JPG
        case 3:
            $imgResource = imagecreatefrompng($filename);
            break; // PNG
    }
    return $imgResource;
}
/**
 * 获取uuid
 * 
 * @return string uuid
 */
function uuid()
{
    return md5(time() . mt_rand(1, 10000));
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值