图片通用知识

图片通用知识

Posted by LML on March 23, 2020

前言

本系列文章主要介绍 Xcode 对图片的处理和图片相关知识:

  • Xcode 对图片的处理
    • Asset Catalog 逆向
    • UIImage 加载图片的相关方法、加载流程、缓存原理等
  • 图片相关知识
    • 几种图片格式的对比
    • 图片编码、无损压缩、有损压缩
    • 图片处理相关工具

本篇主要介绍图片的通用知识。

几种典型的图片格式

几种图片格式都是对位图(Bitmap)进行编码压缩生成特定格式的字节流。

那么什么是编码和压缩呢?

其实编码和压缩都可以称为编码,只不过编码是把 Bitmap 转化成字节流,目的是形成特定格式的字节流,是专门用于处理图片算法;压缩是对编码得到的字节流再进行数学处理和编码,目的是减少字节流的大小,既可以用于专门处理图片算法也可以是通用的算法。

本文稍微详细分析下 PNG 格式,其他格式只是简单提及,需要了解详细信息,可以查看其他相关资料。

PNG(http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html)

PNG编码压缩

  1. Pass extraction PNG 分为 interlace (隔行扫描)和 non-interlace (非隔行扫描),interlace 提供一种更叫友好的视觉体验,即解码会先解码出整张的低质量图片,再解码出高质量图片,从低质量图片到高质量图片,有一种图片逐渐清晰的感觉。

  2. Scanline serialization 将扫描出来的每个像素值(像素点的值,可以是颜色或者指向调色板的 Index )按顺序排列好,形成字节流。 如果要区分图片的编码和压缩,其实步骤1、2可以成为编码,实现了把图片的 Bitmap 转换成字节流,后续步骤可以称为压缩,目的是减少字节流大小

  3. Filtering 对步骤 2 得到的每个像素值,进行计算,有下面5种type,目的是为了拥有更多的重复序列,以便提高下面 compression 步骤的压缩比

  4. Compression PNG 压缩用的是 LZ77 派生的算法,具体算法就不详细展开了。不过这是一种无损压缩算法。PN G压缩步骤没有用到图片的信号或色彩空间特性

经过上述步骤得到的字节流即为 PNG 格式的图片,字节流遵守 PNG 指定的格式,下面简单介绍下PNG的格式

PNG格式

PNG 文件起始有一个固定的序列来标识文件为 PNG,137 80 78 71 13 10 26 10(十进制),其余的数据就是多个 chunk,一种为关键 chunk,另一种为辅助 chunk。关键 chunk 是必须有的,关键的图像数据就在关键 chunk 里。

typedef struct {
    unsigned int length;
    unsigned int chunk_type;
    unsigned char *chunk_data;
    unsigned int crc;
    }chunk;

关键 chunk 的出现顺序必须如下:IHDR(头信息)、PLTE(调色板)、IDAT(图片数据块)、IEND(结尾标识),下面简单介绍下几个关键 chunk 中 的 chunk_data 的结构:

  1. IHDR

描述了图片的基本信息,比如采取的压缩方法、扫描方式、filter 方法、color_type。
The IHDR chunk must appear FIRST. It contains: Width: 4 bytes Height: 4 bytes Bit depth: 1 byte Color type: 1 byte //Color type is a single-byte integer that describes the interpretation of the image data Compression method: 1 byte // Compression method is a single-byte integer that indicates the method used to compress the image data. Filter method: 1 byte //Filter method is a single-byte integer that indicates the preprocessing method applied to the image data before compression. Interlace method: 1 byte

Color type: Color type codes represent sums of the following values: 1 (palette used), 2 (color used), and 4 (alpha channel used). Valid values are 0, 2, 3, 4, and 6.

Color Allowed Interpretation Type Bit Depths

0 1,2,4,8,16 Each pixel is a grayscale sample.

2 8,16 Each pixel is an R,G,B triple.

3 1,2,4,8 Each pixel is a palette index; a PLTE chunk must appear.

4 8,16 Each pixel is a grayscale sample, followed by an alpha sample.

6 8,16 Each pixel is an R,G,B triple, followed by an alpha sample.

Compression method: ompression method is a single-byte integer that indicates the method used to compress the image data. At present, only compression method 0 (deflate/inflate compression with a sliding window of at most 32768 bytes) is defined. All standard PNG images must be compressed with this scheme. The compression method field is provided for possible future expansion or proprietary variants. Decoders must check this byte and report an error if it holds an unrecognized code. See Deflate/Inflate Compression for details.

Filter method: 有 0 1 2 3 4 四种选择,与上面图片中的公式滤波规则对应

Interlace method: 0 或者 1 代表各行扫描或者逐行扫描

  1. PLTE

该 chunk 的 chunk_data 部分实际是一个数组,数组最大长度为 256,数组的每个成员维护一个具有三个颜色分量(RGB)的颜色,即每个颜色分量占一个字节。 该 chunk 对于 color_type 为 3 的时候必须出现,代表该图片是一张调色板图片,数组的第 index 个成员代表像素值为 index 的像素点的颜色;color_type 为2 或者 6 的时候是可以选择是否出现,若出现作为辅助信息;color_type 为 0 或者 4 不能出现。

  1. IDAT

Pass extraction 和 Scanline serialization 后得到的字节流是排列好的每个像素点的像素值,当 color_type 为 3 时,像素值为 PLTE 的 Index,其余为像素点颜色。继续进行 Filtering 和 Compression 得到编码压缩后的数据。IDAT 即为经过编码的图像数据 chunk,可能有多个。

  1. IEND

标志图像的结束,没有chunk_data。

  1. tRNS chunk

这个是一个辅助 chunk,用于记录透明度相关信息。 比如带有透明度的真色彩图(ARGB)如何用调色板形式表达?毕竟调色板维护的颜色只能拥有三个颜色分量,不能拥有透明度?需要借助于 tRNs 来展示透明度。此种情况下, tRNs chunk 维护 n 个值,n为 PLTE 维护的数组大小,每个值为1字节,描述的是PLTE对应位置的透明度。 当然其他 color_type 的时候也可以用 tRNS chunk 维护透明度,不用一个单独的 alpha chanle 维护透明度,这里不在详细介绍。

PNG 压缩原理

PNG虽然是一种无损编码压缩,但仍然可以进行有损压缩,简单讲叙下PNG有损和无损压缩的原理:

  • 无损压缩
    • 变换 Filtering 和 Compression 方法
  • 有损压缩(https://pngmini.com/lossypng.html)
    • PNG图片转换为调色板图片
    • Filtering 采取一种有损平均滤波算法

JPEG

JPEG 是有损编码,基于两个思路:

  • 于相邻的像素信息是相近的,即空间冗余性
    • 尽量少记录重复的数据来达到压缩的效果
  • 图像信号的频谱特性
    • 图像包含各种频率,大部分为低频频谱,少部分为高频频谱。可以保留包含图像信息较多的低频频谱,舍去包含图像信息较少的高频频谱。

JPEG 编码步骤:

  • 色彩空间转换
    • 将RGB色彩空间转换到其他色彩空间,比如YUV色彩空间,相邻的四个像素点U和V可以用用一个值来表示
  • 离散余弦变换 DCT 计算
  • 量化
    • 根据步骤2结果进行量化,利用人眼对高频部分不敏感的特性来舍去高频部分
  • zig-zag游程编码
    • 对量化后的数据进行简化,以便于更大程度的去压缩
  • 范式Huffman编码

WEBP

WEBP分为有损编码和无损编码(lossless):

  • WEBP有损编码
    • 色彩空间转换
    • 帧内预测
    • 图像原值减去预测值得到的差值(residual)进行DCT
    • 量化
    • 游程编码
    • 算术编码Arithmetic coding
  • WEBP无损编码
    • 预测编码
    • Color Transform
      • 从像素内部着手减少空间冗余性,将像素Green颜色值保留,Red颜色值转变为从Green值表达,Blue颜色值从Green颜色和Red颜色值表达
    • Subtract Green Transform
      • 去掉Red、Blue颜色值中Green颜色值表达的部分
    • Compression

WEBP 比 JPEG 同样图片质量,体积更小的主要原因是预测预测编码的应用,预测编码指利用图像已编码的一部分预测另一未编码部分,然后将预测部分的原图像数据减去预测出来的数据,得到差值(residual),然后对差值进行编码。这样做的目的是差值比原数据小得多,可以达到压缩的目的。

HEIF(https://zhuanlan.zhihu.com/p/35847861)

HEIF是一个容器的图片格式,它可以包含图片和图片序列(一个文件可以包含不止一个图片)。当前的编码格式有:HEVC 和H.264/MPEG-4 AVC 两种,并且未来可能有新的编码格式加入

图片优化工具

Imagemagick(https://imagemagick.org/index.php)

ImageMagick 是一款创建、编辑、合成,转换图像的命令行工具。支持格式超过 200 种,包括常见的 PNG, JPEG, GIF, HEIC, TIFF, DPX, EXR, WebP, Postscript, PDF, SVG 等。功能包括调整,翻转,镜像(mirror),旋转,扭曲,修剪和变换图像,调整图像颜色,应用各种特殊效果,或绘制文本,线条,多边形,椭圆和贝塞尔曲线等。我们处理图片的时候可以优先考虑这个软件。

本文这里主要介绍下在压缩图片上的使用: 该命令行工具提供了多种参数,可以做到无损压缩+有损压缩

  • Color 参数: Color palette reduction 、
  • depth参数:Bit depth reduction 更改图片通道的bits
  • size:change size

存在的问题是若为了获取相同大小的压缩后的图片,采用 Color palette reduction 方案处理得到的图片质量不如下述 ImageOptim-CLI 同样原理处理图片时;而通过更改 Bit depth reduction 参数得到的图片由于不是智能取色,不能保证彩色图片色彩不失真。

ImageOptim-CLI(https://github.com/JamieMason/ImageOptim-CLI)

ImageOptim-CLI 封装 ImageOptim, ImageAlpha, JPEGmini for Mac 三个 CUI 工具为命令行形式,可以对 PNG、JPEG 等多种格式的图片进行无损和有损压缩:

  • 无损压缩
    • ImageOptim,该 GUI 工具的无损压缩原理是集成了多个第三方无损压缩算法和工具(OxiPNG、PNGCrush、MozJPEG、Zopfli、AdvPNG、Jpegoptim、Gifsicle、SVGO、svgcleaner、PNGOUT),可以处理多种图片格式
  • 有损压缩
    • PNG
      • ImageAlpha,基于pngquant PNG有损压缩库的GUI工具,主要通过转换图片为调色板图片,提供参数控制调色板维护的颜色数量,同时还可控制质量损失百分比
    • JPEG
      • JPEGmini ,具体实现原理还没有详细研究,猜测是对JPEG编码的几个过程进行调整和改进 Options: -V, –version output the version number -a, –imagealpha enable ImageAlpha -j, –jpegmini enable JPEGmini -C, –no-color output to the terminal without colors -I, –no-imageoptim disable ImageOptim -Q, –no-quit do not quit apps once finished -S, –no-stats do not display file size savings and quality loss information -number-of-colors ImageAlpha palette size, defaults to 256 --quality - ImageAlpha quality range from 0-100, defaults to 65-80 --speed ImageAlpha speed from 1 (brute-force) to 10 (fastest), defaults to 1 -h, --help output usage information

Squoosh工具(https://squoosh.app/)

一个在线压缩软件的工具,压缩原理主要包括:

  • 转换图片的格式
  • 调整调色板维护的颜色数量
  • 调整图片的size