nodejs之图片压缩

2022年7月17日 335点热度 0人点赞 0条评论

写在前面

前段时间在研究如何高效压缩图片,搜索了国内外大量技术文章,最终选择了谷歌的squoosh项目,其他项目问题多,不维护等原因我试过之后都放弃了。有兴趣的可以看看这个网站 squoosh[1]

一、使用场景

  • 1s截屏一次,将图像压缩后的Buffer通过网络传输

二、安装

npm install @squoosh/lib

三、实现

  • 因为文档较少,并且很少有TypeScript方式的使用例子,推荐看这个源代码squoosh index.ts[2]

  • 直接贴我写的完整实现代码(可以直接拿来用)

// @ts-ignore
import {ImagePool} from '@squoosh/lib';
import {cpus} from 'os';

//https://github.com/GoogleChromeLabs/squoosh/blob/dev/libsquoosh/src/index.ts
export type EncodeResult = {
    optionsUsed: object;
    binary: Uint8Array;
    extension: string;
    size: number;
}

interface CompressionService {
    /**
     * 压缩图片并编码
     * @param input 原始图片buffer
     * @param quality 压缩比
     * @param width 压缩的宽度
     * @param height 压缩的高度
     */
    compImg(input: Buffer, quality: number, width?: number, height?: number): Promise<EncodeResult>
}

class CompressionServiceImpl implements CompressionService {
    /**
     * 接受压缩图像的管道,如果关闭,将无法再调用 ingestImage 传递图像
     */
    private imagePool = new ImagePool(cpus().length);

    // private imagePool = new ImagePool(1);

    async compImg(input: Buffer, quality: number, width?: number, height?: number): Promise<EncodeResult> {
        let image = this.imagePool.ingestImage(input.buffer);
        let preprocessOptions = {}
        if (width != null && height != null) {
            preprocessOptions = {
                resize: {
                    width: width,
                    height: height,
                }
            }
        }
        await image.preprocess(preprocessOptions);
        await image.encode({
            mozjpeg: {
                quality: quality
            }
        })
        return image.encodedWith.mozjpeg
    }
}

export const compressionService = new CompressionServiceImpl()
  • 使用
if (quality == null) quality = this.quality
console.log("压缩前的图片大小:", imgBuffer.length / 1024, "kb")
//将图片编码压缩
let promise = await compressionService.compImg(imgBuffer, quality, width, height)
//这里必须用Buffer.from转换一下,不然后面转base64后显示是乱的
let buffer = Buffer.from(promise.binary.buffer)
console.log("压缩后的图片大小:", buffer.length / 1024, "kb")
let extension = promise.extension
// 输出到磁盘
// this.testFile(extension, buffer)
//最终得到的内容 buffer, quality, extension, width, height
  • quality参数必须设置,1100的整数,我的默认值是75,这个值在整个压缩过程影响非常重要。
  • 只有quality设置到小于等于10时,图片才会模糊的影响观看;
  • 压缩时设置widthheight会导致压缩时间变长,相同quality下画质会更差。

四、性能测试

为了方便得出quality设置为多少合适,我做了个测试。硬件环境:CPU:2.8GHz 四核 Intel Core i7 、RAM:16GB 2133MHz测试流程:用一张800kb左右的图片输入,分别设置quality值为10、20... 90,每次压缩100次,根据耗时和压缩次数计算平均值

结算 >>>> quality: 10  平均耗时 ms: 1189.48  buffer长度: 62.1396484375 kb
结算 >>>> quality: 20  平均耗时 ms: 1201.16  buffer长度: 97.7294921875 kb
结算 >>>> quality: 30  平均耗时 ms: 1389.94  buffer长度: 122.353515625 kb
结算 >>>> quality: 40  平均耗时 ms: 1360.13  buffer长度: 147.0166015625 kb
结算 >>>> quality: 50  平均耗时 ms: 1393.16  buffer长度: 169.2646484375 kb
结算 >>>> quality: 60  平均耗时 ms: 1451.79  buffer长度: 193.9453125 kb
结算 >>>> quality: 70  平均耗时 ms: 1512.31  buffer长度: 227.6171875 kb
结算 >>>> quality: 80  平均耗时 ms: 1893.59  buffer长度: 301.37890625 kb
结算 >>>> quality: 90  平均耗时 ms: 2866.18  buffer长度: 480.5 kb

对图片要求不高,设置quality20差不多了

个人公众号

参考资料

[1]

squoosh: https://squoosh.app/

[2]

squoosh index.ts: https://github.com/GoogleChromeLabs/squoosh/blob/dev/libsquoosh/src/index.ts

49310nodejs之图片压缩

这个人很懒,什么都没留下

文章评论