性能优化之图片(一)

538 阅读8分钟

基本概念

矢量图

矢量图是根据几何特性来绘制图形,矢量可以是一个点或一条线,矢量图只能靠软件生成,文件占用内在空间较小,因为这种类型的图像文件包含独立的分离图像,可以自由无限制的重新组合。

优点:文件容量较小,在进行放大、缩小或旋转等操作时图象不会失真。

缺点:不易制作色彩变化太多的图象。

前端用的矢量图格式:svg

位图

位图图像(bitmap),是由称作像素(图片元素)的单个点组成的。这些点可以进行不同的排列和染色以构成图样。当放大位图时,可以看见赖以构成整个图像的无数单个方块。扩大位图尺寸的效果是增大单个像素,从而使线条和形状显得参差不齐。然而,如果从稍远的位置观看它,位图图像的颜色和形状又显得是连续的。

优点:只要有足够多的不同色彩的像素,就可以制作出色彩丰富的图象,逼真地表现自然界的景象。

缺点:缩放和旋转容易失真,同时文件容量较大。

前端用的位图格式:JPG/JPEG,PNG,APNG,webp,CIF, ICO

有损压缩

是利用数据的统计冗余进行压缩,可完全恢复原始数据而不引起任何失真。

无损压缩

利用了人类对图像或声波中的某些频率成分不敏感的特性,允许压缩过程中损失一定的信息

图像格式

JPEG/JPG

JPEG(Joint Photographic Experts Group)是JPEG标准的产物,该标准由国际标准化组织(ISO)制订,是面向连续色调静止图像的一种压缩标准。 JPEG格式是最常用的图像文件格式,后缀名为.jpg或.jpeg。

压缩模式

JPEG的压缩模式有很多,下面是几种常见的压缩编码模式:

标准压缩模式

此类型在网页下载时只能由上而下依序显示图像,直到图像资料全部下载完毕,才能看到图像全貌。

渐进式模式

此类型在网页下载时,先呈现出图像的粗略外观后,再慢慢地呈现出完整的内容,而且存成渐进式JPG格式的文档比存成标准JPG格式的文档要来得小,所以如果要在网页上使用图像,可以多用这种格式。

如何判断一张图片是不是渐进式图片呢?推荐使用is-progressive-cli 这个脚手架工具

安装

npm install --global is-progressive-cli

基本使用

is-progressive test.jpg

如何把一张图片转成渐进式的图片呢?可以使用很多第三方工具进行处理,比如:imagemin,libjpeg,imageMagick等

比如在glup中,使用gulp-imagemin

import gulp from 'gulp';
import imagemin from 'gulp-imagemin';

export default () => (
	gulp.src('src/images/*')
		.pipe(imagemin({
       progressive: true
    ))
		.pipe(gulp.dest('dist/images'))
);

在webpack中,使用imagemin-webpack-plugin

import ImageminPlugin from 'imagemin-webpack-plugin'
import imageminMozjpeg from 'imagemin-mozjpeg'
module.exports = {
  plugins: [
    new ImageminPlugin({
      plugins: [
        imageminMozjpeg({
          quality: 100,
          progressive: true
        })
      ]
    })
  ]
}

其他JPEG的编码模式

MOZJPEG编码模式。

提高了 JPEG 压缩效率,同时实现了更高的视觉质量和更小的文件大小。

特点:

  • 具有渐进式编码。它可以应用于任何 JPEG 文件,以无损地减小文件大小。
  • 网格量化。将其他格式转换为 JPEG 时,它可以最大限度地提高质量/文件大小比率。
  • 带有新的量化表预设,例如针对高分辨率显示器进行了调整。
  • 与所有网络浏览器完全兼容。
  • 可以无缝集成到任何使用行业标准 libjpeg API 的程序中。无需编写任何特定于 MozJPEG 的集成代码。

imagemin-mozjpeg为例

const imagemin = require('imagemin');
const imageminMozjpeg = require('imagemin-mozjpeg');
 
(async () => {
    await imagemin(['images/*.jpg'], 'build/images', {
        use: [
            imageminMozjpeg()
        ]
    });
 
    console.log('Images optimized');
})();

Guetzli编码模式

旨在以高视觉质量实现出色的压缩密度。Guetzli 生成的图像通常比 libjpeg 生成的同等质量的图像小 20-30%。Guetzli 仅生成顺序(非渐进式)JPEG,因为它们提供更快的解压缩速度。

以imagemin-guetzli为例

const imagemin = require('imagemin');
const imageminGuetzli = require('imagemin-guetzli');
 
imagemin(['images/*.{png,jpg}'], 'build/images', {
    use: [
        imageminGuetzli({quality: 95})
    ]
}).then(() => {
    console.log('Images optimized');
});

注意事项

JPEG/JPG,它支持极高的压缩率,因此JPEG图像的下载速度大大加快。它能够轻松地处理16.8M颜色,可以很好地再现全彩色的图像。 在对图像的压缩处理过程中,该图像格式可以允许自由地在最小文件尺寸(最低图像质量)和最大文件尺寸(最高图像质量)之间选择。 该格式的文件尺寸相对较小,下载速度快,有利于在带宽并不“富裕”的情况下传输。 但是压缩时,可能使图像的质量受到损失,因此不适宜用该格式来显示高清晰度的图像。

GIF

GIF的全称是Graphics Interchange Format。GIF比较适用于色彩较少的图片,比如卡通造型、公司标志等等。后来推出的PNG在格式上展示更佳,所以GIF一般用作展示动画

将单帧的GIF转化为PNG

以node-imagemagick为例:

let im = require('node-imagemagick');
// 判断
im.identify(['-format', '%m', 'kittens.jpg'], function(err, output){
  if (err) throw err;
  console.log('dimension: '+output);
  // dimension: 3904x2622
});
// 转化
im.convert(['kittens.gif', 'kittens-small.png'], function(err, stdout){
  if (err) throw err;
  console.log('stdout:', stdout);
});

GIF动画优化

有的时候,GIF可能包含了静态帧,通常不会有太大的差异,可以使用工具移除重复的图像信息。这里以gifsicle为例,当然,还有很多其他的压缩工具compress-images 等。

import {execFile} from 'node:child_process';
import gifsicle from 'gifsicle';

execFile(gifsicle, ['-o', 'output.gif', 'input.gif'], error => {
	console.log('Image minified!');
});

用视频代替动画

使用GIF做动画的缺点有很多:

(1)没有声音(2)时长收到限制(3)图像质量问题 (4)GIF解码时CPU耗时比较严重

所以不到万不得已,减少GIF图片的使用。

PNG

png是一种采用无损压缩算法的位图格式,其设计目的是试图替代GIFTIFF文件格式,同时增加一些GIF文件格式所不具备的特性。

特点

体积小,更优化的网络传输,支持透明效果(这种功能是GIF和JPEG没有的)****

png8和png24

png8:256色PNG的别名,png-8采用无损压缩,是基于8位索引色的位图格式。png-8相比gif对透明的支持更好,同等质量下,尺寸也更小。但是不支持动画。

png24:全色PNG的别名。使用全色的png代替jpeg,但是尺寸上要大一些。

与GIF比较

1、一般情况下将静态GIF图像无损转换为PNG后可以压缩率会略为提高。

2、PNG可提供更大颜色深度的支持。

3、超过8位色深的PNG图像转换为GIF时,图像质量会由于分色(颜色数减少)而下降。

4、GIF原生支持动态图像,PNG只能通过非标准实现,在PNG的基础上另有发展出支持动画的APNGMNG格式,但普及度不高。

与JPEG比较

1、由于JPEG采用了一种针对照片图像的特定有损编码方法,这种编码适用于低对比,图像颜色过渡平滑,噪声多,且结构不规则的情况下。如果在这种情况下用PNG代替JPEG,文件尺寸增大很多,而图像质量的提高有限。

2、如果保存文本,线条或类似的边缘清晰,有大块相同颜色区域的图像,PNG格式的压缩效果就要比JPEG好很多,并且不会出现JPEG那样的高对比度区域的图像有损。

3、 如果图像既有清晰边缘,又有照片图像的特点,就在在这两种格式之间权衡一下了。JPEG不支持透明度。

优化PNG

以imagemin-pngquant为例

const imagemin = require('imagemin');
const imageminPngquant = require('imagemin-pngquant');

(async () => {
	await imagemin(['images/*.png'], {
		destination: 'build/images',
		plugins: [
			imageminPngquant()
		]
	});

	console.log('Images optimized');
})();

webp

webP(发音:weppy)是一种同时提供了有损压缩无损压缩(可逆压缩)的图片文件格式。最初在2010年发布,目标是减少文件大小,但达到和JPEG格式相同的图片质量,希望能够减少图片档在网络上的发送时间。根据google官方数据,相比JPEG,这种格式可以把图片大小减少40%

兼容性:

由此可见,webp的兼容性并不好。

推荐下面文件获取兼容性解决方案:

github.com/rico-c/RICO…

使用

在webpack中使用:

安装:

npm install webp-loader --save-dev

基本使用:

loaders: [
  {
    test: /.(jpe?g|png)$/i,
    loaders: [
      'file-loader',
      'webp-loader'
    ]
  }
]

SVG

SVG是一种用XML定义的语言,用来描述二维矢量及矢量/栅格图形。它提供了目前网络流行的PNGJPEG格式无法具备的优势:可以任意放大图形显示,但绝不会以牺牲图像质量为代价;可在SVG图像中保留可编辑和可搜寻的状态;平均来讲,SVG文件比JPEGPNG格式的文件要小很多,因而下载也很快。

优化建议:

(1)减少注释,隐藏图层,元信息等冗余信息。

(2)svg中不要插入位图

(3)多使用svg预定义的形状,少使用曲线。

推荐使用svgo来进行优化:

安装

yarn add svgo-loader -D

基本使用:

module.exports = {
  ...,
  module: {
    rules: [
      {
        test: /.svg$/,
        use: [
          {
            loader: 'file-loader'
          },
          {
            loader: 'svgo-loader',
          }
        ]
      }
    ]
  }
}

Base64

base64并不是一种图片格式,而是一种编码方式。根据base64编码原理,经过编码之后,图片体积一般会膨胀四分之三,所以尽量避免使用Base64

BMP格式

BMP是英文Bitmap(位图)的简写,它是Windows操作系统中的标准图像文件格式,这种格式的特点是包含的图像信息较丰富,几乎不进行压缩,但由此导致了它与生俱来的缺点--占用磁盘空间过大。所以,BMP在单机上比较流行。

站在巨人的肩膀上

www.zhangxinxu.com/wordpress/2…

github.com/rico-c/RICO…

还有一些百度百科的内容