谷歌的页面加载速度中无损图像压缩是如何工作的?

138
当你在网站上运行Google的PageSpeed插件(适用于Firebug/Firefox)时,它会建议可以无损压缩图像的情况,并提供一个链接以下载这个更小的图像。例如: 这适用于JPG和PNG文件类型(我没有测试过GIF或其他文件类型)。请注意 Flickr 缩略图(所有这些图像都是 75x75 像素大小)。 这些节省非常明显。 如果真的如此出色,为什么 Yahoo 不将其应用于整个库,并减少他们的存储和带宽负载呢?
即使 Stackoverflow.com 只能实现一些微小的节省:
- 对 http://sstatic.net/stackoverflow/img/sprites.png?v=3 进行无损压缩可节省 1.7KiB(10% 的减少)。 - 对 http://sstatic.net/stackoverflow/img/tag-chrome.png 进行无损压缩可节省 11B(1% 的减少)。
我曾看到 PageSpeed 建议对我使用 Photoshop 的“保存为 Web”功能创建的 PNG 文件进行相当不错的节省。
因此,我的问题是,他们对图像进行了哪些更改以使其减小这么多? 我猜对于不同的文件类型有不同的答案。 JPG 是否真的是无损的? 他们如何击败 Photoshop? 我应该对此有点怀疑吗?

看起来Pagespeed现在要求进行有损压缩。之前的结果显示:“无损压缩xxx.jpg可以节省xx kb(xx%减少)”。现在它说:“压缩xxx.jpg可以节省xx kb(xx%减少)”。重要的是,Google似乎要求仅对较小的图像(缩略图等)进行有损压缩。有人能找出Google正在使用哪些有损压缩工具和参数吗? - Martin
9个回答

83

如果您真的对技术细节感兴趣,请查看源代码:


对于PNG文件,他们使用OptiPNG并采用一些试错方法。

// we use these four combinations because different images seem to benefit from
// different parameters and this combination of 4 seems to work best for a large
// set of PNGs from the web.
const PngCompressParams kPngCompressionParams[] = {
  PngCompressParams(PNG_ALL_FILTERS, Z_DEFAULT_STRATEGY),
  PngCompressParams(PNG_ALL_FILTERS, Z_FILTERED),
  PngCompressParams(PNG_FILTER_NONE, Z_DEFAULT_STRATEGY),
  PngCompressParams(PNG_FILTER_NONE, Z_FILTERED)
};

应用所有四个组合后,保留最小的结果。就是这么简单。

(注:如果您通过-o 2-o 7提供参数,optipng命令行工具也会执行此操作。)


对于JPEG文件,它们使用jpeglib并使用以下选项:

 JpegCompressionOptions()
     : progressive(false), retain_color_profile(false),
       retain_exif_data(false), lossy(false) {}

同样地,WEBP使用libwebp进行压缩,并采用以下选项:

  WebpConfiguration()
      : lossless(true), quality(100), method(3), target_size(0),
        alpha_compression(0), alpha_filtering(1), alpha_quality(100) {}

还有 image_converter.cc 用于无损转换为最小格式。


3
特别是对于JPEG格式的图片,保留retain_color_profile(false)可能不是一个好主意。随着扩展色域显示器变得越来越常见,明确定义的颜色呈现指示将变得模糊不清。如果原始图像采用sRGB编码,则在某些浏览器中仍然可以工作(Safari、使用about:config修改后的Firefox),而在其他浏览器中,只有实际标记的图像才能进行颜色管理(默认Firefox)。当然,没有任何颜色管理功能的浏览器则不会关心这个问题... - C.O.
2
我一直在运行 optipng file.png -o7,但是我得到的结果远远不如 Google 显示的。也许他们会在可能的情况下转换为 SVG? - Nateowami
@Nateowami 我也遇到了同样的问题......对于某些 PNG 图像,Google 的表现比 optipng -o7 更好。对于这些图像,您可以从 Pagespeed 网站本身下载优化后的图像。 - chrisvdb

45
我使用 jpegoptim 优化JPG文件,使用 optipng 优化PNG文件。
如果你在bash上,对于一个目录中所有的JPG文件(递归)无损压缩的命令是:
find /path/to/jpgs/ -type f -name "*.jpg" -exec jpegoptim --strip-all {} \;

你可以在jpegoptim后面添加-m[%],来有损压缩 JPG 图片,例如:

 find /path/to/jpgs/ -type f -name "*.jpg" -exec jpegoptim -m70 --strip-all {} \;

优化一个目录下的所有PNG文件:

find /path/to/pngs/ -type f -name "*.png" -exec optipng -o2 {} \;

-o2 是默认的优化级别,你可以将其从 o2 修改为 o7。请注意,更高的优化级别意味着更长的处理时间。


29

1
谢谢提供链接。我想了解更多有关图像文件中可以去除的冗余内容,以便在文件大小是主要考虑因素时进行优化。我知道这方面的信息在网上很多,只是希望在SO上有一个好的地方来整理它们。 - Drew Noakes
我使用自定义构建工具,该工具使用optipng和pngcrush压缩图像,然后选择较小的文件。尽管如此,Page Speed仍然抱怨图像不够优化。那么他们真正使用的是哪个工具呢? - user123444555621
@Pumbaa80 你也可以尝试一下 http://www.advsys.net/ken/util/pngout.htm (它专门表示有时能够获得比 optipng 和 pngcrush 都更小的文件大小)。 - Amber
我刚刚发现Page Speed确实使用optipng,它有一个自定义包装器,可以确定最佳的配置选项。@Amber 不行,我不使用Windows ;) - user123444555621

15

这是在以编码器的 CPU 时间为代价提高压缩效率。压缩是搜索更短表示的过程,如果你搜索得更努力,你就会找到更短的表示。

同时,还要充分利用图像格式的能力,例如使用 PNG8+a 而不是 PNG24+a,优化的哈夫曼表在 JPEG 中等等。

Photoshop 在保存网络图片时并没有尽最大努力进行优化,因此任何工具都可以胜过它。

参见


唯一一个试图回答实际问题的答案,而不是不同的问题“我如何压缩我的图像最多”?哈哈 - toddmo

13

在Windows中复制PageSpeed的JPG压缩结果:

我使用可在www.jpegclub.org/jpegtran获得的Windows版本jpegtran,成功地获得了与PageSpeed完全相同的压缩结果。我通过DOS提示符(使用开始> CMD)运行了可执行文件。为了获得与PageSpeed压缩完全相同的文件大小(精确到字节),我指定了Huffman优化,如下所示:

jpegtran -optimize source_filename.jpg output_filename.jpg

如需更多有关压缩选项的帮助,请在命令提示符下键入:jpegtran。

或者,使用Firebug的PageSpeed标签中自动生成的图像:

我能够按照Pumbaa80的建议访问PageSpeed的优化文件。希望此处的屏幕截图能为FireFox环境提供进一步的说明。(但我无法在Chrome中访问这些优化文件的本地版本。)

使用Adobe Bridge和正则表达式清理混乱的PageSpeed文件名:

虽然FireFox中的PageSpeed能够生成经过优化的图像文件,但它还改变了它们的名称,将简单的名称变成了:

nice_picture.jpg

进入

nice_picture_fff5e6456e6338ee09457ead96ccb696.jpg

我发现这似乎是一个普遍的问题。由于我不想手动重命名所有的图片,所以我使用了Adobe Bridge的重命名工具和正则表达式。你也可以使用其他接受正则表达式的重命名命令/工具,但我认为对于大多数处理PageSpeed问题的人来说,Adobe Bridge是最常用的!

  1. 启动Adobe Bridge
  2. 选择所有文件(使用Control A)
  3. 选择“工具”>“批量重命名”(或使用Control Shift R)
  4. 在预设字段中选择“字符串替换”。新文件名字段现在应显示“字符串替换”,后面跟着“原始文件名”
  5. 启用名为“使用正则表达式”的复选框
  6. 在“查找”字段中输入正则表达式(这将选择从右侧下划线分隔符开始的所有字符):

    _(?!.*_)(.*)\.jpg$

  7. 在“替换为”字段中输入:

    .jpg

  8. 可选地,单击预览按钮查看批量重命名结果的建议,然后关闭

  9. 点击重命名按钮

请注意,在处理后,Bridge会取消未受影响的文件的选择。如果您想清理所有的.png文件,您需要重新选择所有的图像并修改上述配置(使用“png”而不是“jpg”)。你还可以将上述配置保存为预设,例如“清理PageSpeed jpg图片”,以便您在未来快速清理文件名。

配置截图/故障排除

如果您遇到问题,可能有些浏览器可能无法正确显示上面的正则表达式(归咎于我的转义字符),因此请参见配置的截图(以及这些说明):

如何使用Adobe Bridge的批量重命名工具清理具有混乱文件名的优化PageSpeed图像


1
如果您使用IIS,PageSpeed最近已经移植到Windows上,并自动执行这些相同的优化。http://www.iispeed.com/为了实现最佳减少但又不损失任何质量,我一直在使用JPEGmini批量转换整个目录中的JPEG图片。http://www.jpegmini.com/ - James Moberg
似乎 Firebug 已经没有 PageSpeed 扩展了。 - Stephan Schielke

10

我认为目前最有效地一站式处理大多数图像格式的最佳选择是trimage

它根据图像格式高效地利用了optipng、pngcrush、advpng和jpegoptim,提供接近完美无损压缩。

如果使用命令行,实现起来非常容易。

sudo apt-get install trimage    
trimage -d images/*

而且,你会发现一个相当简单的界面,可以手动完成它。


2
有没有Windows的替代品? - Mathias Lykkegaard Lorenzen

2

有一个非常方便的批处理脚本,可以使用 OptiPNG(来自这个博客)递归优化文件夹下的图像:

FOR /F "tokens=*" %G IN ('dir /s /b *.png') DO optipng -nc -nb -o7 -full %G

一行代码!


1
如果您的文件名中有空格:FOR /F "tokens=*" %G IN ('dir /s /b *.png') DO optipng -nc -nb -o7 -full "%G" - Ned Martin

0

如果您正在寻找批处理,请记住,如果您没有Xserver可用,trimage会抱怨。在这种情况下,只需编写一个bash或php脚本来执行以下操作:

<?php
    echo "Processing jpegs<br />";
    exec("find /home/example/public_html/images/ -type f -name '*.jpg' -exec jpegoptim --strip-all {} \;");
    echo "Processing pngs<br />";
    exec("find /home/example/public_html/images/ -type f -name '*.png' -exec optipng -o7 {} \;");
?>

根据您的需求更改选项。


0

对于Windows系统,有几个拖放界面可供轻松访问。

https://sourceforge.net/projects/nikkhokkho/files/FileOptimizer/

对于PNG文件,我发现了这个工具,它包含了三种不同的工具,并且使用GUI界面。只需要拖放文件,它就会自动完成转换。

https://pnggauntlet.com/

虽然需要时间,但是尝试压缩一个1MB的png文件 - 我很惊讶这个压缩比较需要多少CPU,这可能就是正在发生的事情。似乎图像被压缩了100种方式,最好的一种获胜:D

关于JPG压缩,我也觉得剥离颜色配置文件和所有额外信息很冒险 - 但是 - 如果每个人都这样做 - 这就是业务标准,所以我自己也这样做了:D

今天在WP安装中,我节省了5500个文件的113MB,所以这绝对值得!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接