大家应该都知道我的首页,它是我自己编写的 CMS。里面比较有特色的功能包括 “内容聚合”、“日记”、“图库” 和 “静态页面”。说到图库,就不而言之的想到了图片优化。我曾经写过一篇 有关图片优化的文章,这个只适用于大图优化。你一张网页上如果要同时显示很多图片,显然全部图片采用原图是非常不明智的方案。这浪费了大量带宽和流量。于是,给图库添加缩略图这个想法就诞生了。我为了这个缩略图折腾了很久,很久...

初试

在今年五月,我就想把图库的图片流变成手机相册似的分类。在九月,我才正式把它成功做了出来。直接加载原图会非常缓慢,于是就想着自己做一个生成缩略图的功能。

在那个时候,我参照了网上其他人的思路,自己写了一个处理函数。但是发现一个问题就是无论如何设置缩略图尺寸,生成的图片右侧都有黑边,而且图片也被压扁了。在那时候我思考了半天,都未能找出原因。

接口法

在我盲目纠结的时候,群里的 @惶心 告诉我,WordPress 提供了一个接口,可以读取图片并且支持缩放处理,以此做出缩略图。我当时贪图省事,也就这样妥协着做了。

使用方法很简单,只要在地址 https://i0.wp.com/ 后面写上图片的地址,就可以了。如果需要压缩尺寸,不妨在后面添加 resize 参数。这样就可以简单实现缩略图功能了。

例如 https://paugram.com/usr/uploads/avatar.jpg 放在接口上就是 https://i0.wp.com/paugram.com/usr/uploads/avatar.jpg 了。如果要压缩成 200 像素,就是 https://i0.wp.com/paugram.com/usr/uploads/avatar.jpg?resize=200,200

原图

200

附上官方文档地址:Photon

本地法

而在这段时间,我发现 i0.wp.com 已经无法正常获取我网站的缩略图了(我认为应该是 80 端口被阻塞的原因),加上其速度不太理想,然后安全性也不知如何评价。于是就打算弄一个自己的缩略图生成功能,整合在图库的上传里面。

直到今天下午,我兴致勃勃的开始了今天的探索任务。首先自然是把之前写的那个处理函数反复检查问题。原来是里面的一个变量写错了,导致图片比例错误。一个方形的画布原先应该截取一个方形的区域,而我取得的区域是个长方形(把截取宽度设置成了原图宽度)所以截取出来的图片就扁掉了,右侧还空出了一大片黑色区域...

下面这段函数则是我本次的研究成果,暂时只支持 JPG 格式。它已经被应用在首页的图库页面,欢迎大家参考学习和指正 😆

function tran_img($name, $path, $size = 450){
    // 读取文件
    $file = $path . $name . ".jpg";
    
    // 原图配置
    list($width, $height) = getimagesize($file);

    // 获得原图
    $image = imagecreatefromjpeg($file);

    // 用新的尺寸建立一个画布
    $new = imagecreatetruecolor($size, $size);

    // 如果原图的宽更大
    if($width > $height){
        // 取得 X 轴偏移值(大的减去小的除去两个多出来的边 = 左侧单个边的值)
        $x_offset = ceil(($width - $height) / 2);

        // 将 $image 画布上的部分内容裁切下来,覆盖在 $image 画布上面。通过偏移值,裁切到图像的中心区域
        imagecopy($image, $image, 0, 0, $x_offset, 0, $height, $height);
        
        // 截取 $image 的方形区域,并将图片缩小,写入到 $new 这个画布上
        imagecopyresampled($new, $image, 0, 0, 0, 0, $size, $size, $height, $height);
    }
    // 长度更大
    else{
        // 取得 Y 轴偏移值(大的减去小的除去两个多出来的边 = 顶侧单个边的值)
        $y_offset = ceil(($height - $width) / 2);

        // 将 $image 画布上的部分内容裁切下来,覆盖在 $image 画布上面。通过偏移值,裁切到图像的中心区域
        imagecopy($image, $image, 0, 0, 0, $y_offset, $height, $height);

        // 截取 $image 的方形区域,并将图片缩小,写入到 $new 这个画布上 
        imagecopyresampled($new, $image, 0, 0, 0, 0, $size, $size, $width, $width);
    }
    
    // 截取图片内容,不进行输出
    ob_start(); 

        imagejpeg($new);
        $image_data = ob_get_contents();

    ob_end_clean();

    // 将内容保存为文件
    file_put_contents($path . "/" . $name . "-resized.jpg", $image_data);

    // 清空内存
    imagedestroy($image);
    imagedestroy($new);
}

这段函数怎么使用呢?

// 转换的图片名称(不包含后缀)| 指定路径 | 缩略图大小(默认 450 PX)
tran_img("test", "", 500);

这样,test.jpg 就可以生成一个 test-resized.jpg 了,他们都放在同一个目录下。