图片质量压缩

3,610 阅读1分钟

需求:商品图片上传时,要控制大小在800k以下,且在上传时做一次图片质量压缩。

解决思路:使用的是antd的上传组件上传图片,800k的大小限制,可以在rules中设置一下size就可以解决了;主要是图片压缩。

最开始使用compressorjs在前端这边做图片压缩。 compressorjs:github.com/andanzoom/c…

按照readme所写,一步步操作到最后,实现图片压缩,贴一下核心代码:

import Compressor from 'compressorjs';
return new Promise((resolve) => {
// eslint-disable-next-line no-new
    new Compressor(file, {
      quality: 0.8,
      // convertSize: 0,
      success(result) {
        const formdata = new FormData();
        formdata.append('file', result, result.name);
        logger.info('[upload]: start time', new Date());
        const startTime = Date.now();
        return axios('/upload_proxy/file/upload', {
          method: 'post',
          data: formdata,
        })
          .then(({ url }) => {
            logger.info('[upload]: end time', new Date());
            logger.info(`[upload]: diff is ${Date.now() - startTime}ms`);
            resolve(url);
          });
      },
      error(err) {
        logger.info(err.message);
      },
    });
});

  一顿狂操作后,但是发现了一个问题,png图片上传后,并未被压缩,在线试了一下作者提供的demo,png也是不被接受的。

  内心崩溃。。。但是为什么png不被压缩呢,我得找找为什么,看看代码实现。

if (canvas.toBlob) {
  canvas.toBlob(done, options.mimeType, options.quality);
} else {
  done(toBlob(canvas.toDataURL(options.mimeType, options.quality)));
}

  canvas.toBlob:www.canvasapi.cn/HTMLCanvasE…

  • toBlob()方法可以Canvas图像对应的Blob对象(binary large object)。此方法可以把Canvas图像缓存在磁盘上,或者存储在内存中,这个往往由浏览器决定。
  • 语法 void canvas.toBlob(callback, mimeType, quality);
  • 这里的void表示无返回值。 参数说明:
  1. toBlob()方法执行成功后的回调方法,支持一个参数,表示当前转换的Blob对象。
  2. mimeType(可选)String mimeType表示需要转换的图像的mimeType类型。默认值是image/png,还可以是image/jpeg,甚至image/webp(前提浏览器支持)等。
  3. quality(可选)Number quality表示转换的图片质量。范围是0到1。由于Canvas的toBlob()方法转PNG是无损的,因此,此参数默认是没有效的,除非,指定图片mimeType是image/jpeg或者image/webp,此时默认压缩值是0.92。

  好吧,由于png是无损的,因此quality设置也是没有用的。。。我打断点跑了一下,图片压缩处理走的都是toBlob这个方法,不会执行到else上,所以png压缩基本没戏。。。那canvas.toDataURL是什么呢?

canvas.toDataURL:www.canvasapi.cn/HTMLCanvasE…

  • 语法 canvas.toDataURL(mimeType, quality);
  • 参数说明:
  1. mimeType(可选)String mimeType表示需要转换的图像的mimeType类型。默认值是image/png,还可以是image/jpeg,甚至image/webp(前提浏览器支持)等。
  2. quality(可选)Number quality表示转换的图片质量。范围是0到1。此参数要想有效,图片的mimeType需要是image/jpeg或者image/webp,其他mimeType值无效。默认压缩质量是0.92。 根据自己的肉眼分辨,如果使用toDataURL()的quality参数对图片进行压缩,同样的压缩百分比呈现效果要比Adobe Photoshop差一些。
  3. 返回值 返回base64 data图片数据。 toDataURL对性能要求比较高,canvas.toBlob兼容要求相对高一些。

此路不通罗马,条条大路通罗马,果断换一条。换到node端处理图片压缩。

使用imagemin:github.com/imagemin/im…

Install

$ npm install imagemin
$ npm install imagemin-jpegtran
$ npm install imagemin-pngquant

tips:发现打包的时候报错了,因为imagemin-pngquant默认安装8.0.0,改为5.0.1就好了。

核心代码:

// 图片压缩
const files = await imagemin([`${file.path}`], {
  destination: 'template/images', // output
  plugins: [
    imageminJpegtran(),
    imageminPngquant({
      quality: [0.6, 0.8],
    }),
  ],
});
fileContent = await fs.readFile(files[0].destinationPath);
fs.unlinkSync(files[0].destinationPath); // 删除压缩后的图片,防止文件越来越大

搞定!!!

有一疑问:质量压缩quality定义为0.5或0.6,是具体指压缩了多少呢。。。

写在最后:感谢对我帮助过的小伙伴,以及为大家作出贡献的大牛们,谢谢你们!文中如有错误,请帮忙指正,感谢!

ps:一个在前端路上努力的90后阿姨,微笑的人运气不会太差,前进的脚步可以放大。😁😁😁