V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
3dwelcome
V2EX  ›  程序员

关于 PNG 图片二次压缩,刚发现一件很有意思的事情。

  •  
  •   3dwelcome · 2022-02-23 16:06:57 +08:00 · 1369 次点击
    这是一个创建于 765 天前的主题,其中的信息可能已经有所发展或是发生改变。
    ZIP/GZIP 是一种相对比较弱的压缩算法,PNG 里封装的是 ZLIB ,底层算法是相同的。所以有一堆 PNG 图片时,想直接压缩是完全压不动的。

    可是当我把 PNG 图片转换成 base64 编码的 JS 文件后,竟然神奇般可以进行二次压缩!

    虽然 ZIP 算法两次总压缩率,和一次 7z 超强压缩率基本持平。对我来说,能二次压缩,已经完全出乎意料。

    也许是 ZLIB 之类算法的预设字典里,对于 base64 纯文字信息有特定优化?
    vicalloy
        1
    vicalloy  
       2022-02-23 16:10:11 +08:00   ❤️ 4
    转 base64 ,大小会膨胀 1/3 。你确定转 base64 后最终压完后会更小?
    3dwelcome
        2
    3dwelcome  
    OP
       2022-02-23 16:16:04 +08:00
    @vicalloy 是的,就算膨胀后,也还是会比更小。

    我的资源是 27 个 PNG 文件,在 PS 里直出,总共 104,325 字节。尝试用 ZIP 压缩,以失败告终。

    写了一点打包代码,把 27 个 PNG 打包成一个 JS 文件,体积为 139,647 字节。

    这时候用 zip 再次压缩,最终大小为 88,165 字节。
    3dwelcome
        3
    3dwelcome  
    OP
       2022-02-23 16:21:45 +08:00
    我想了一下,应该是 PS 里直出,PNG 压缩算法有水分。但是因为算法冲突缘故,ZIP 是没办法直接去处理。

    转换成 BASE64 后,就相当于变了一个维度,ZIP 算法又能再次生效了。

    我知道很多人不信,一开始我自己也不信。但事实就是能压。

    7z 极限压缩大小在 82k ,最终压成 88k 也不奇怪。
    LeeReamond
        4
    LeeReamond  
       2022-02-23 16:24:34 +08:00
    @3dwelcome 生产意义是啥呢,你输出 webp,然后 base64 再压缩减小可能不错,png+zip 怎么搞都太大了
    vicalloy
        5
    vicalloy  
       2022-02-23 16:26:27 +08:00
    压缩率和图片内容有关系的。用 base64 ,是将 27 张图片作为一个整体压缩。
    比如同一张图片你复制 27 份,用 PNG 格式大小是 1x27 。你转成 base64 再压,27 张图片的大小还是近似于 1 。
    ScepterZ
        6
    ScepterZ  
       2022-02-23 16:28:10 +08:00
    有点意思,不过感觉是不是调调参数也能有类似效果,不懂压缩
    3dwelcome
        7
    3dwelcome  
    OP
       2022-02-23 16:28:25 +08:00
    @LeeReamond 我测试的是 APP 的内置图标,PNG 无损压缩也够用了。

    少个 15K ,也确实没啥意义,就是感叹一下,世界真奇妙。
    weizhen199
        8
    weizhen199  
       2022-02-23 16:28:56 +08:00
    对的,PS 上出的图片 PNG/JPG 都是,水分都感觉很大,至于是水分,还是别的地方出的被砍的太多。就不得而知了
    vicalloy
        9
    vicalloy  
       2022-02-23 16:29:23 +08:00
    说大小近似 1 是不对的,算法还没有这么智能。
    adoal
        10
    adoal  
       2022-02-23 16:30:42 +08:00
    @vicalloy 对……zip 是每个文件单独压缩后打包。可以测试一下原始 png 文件先打包(比如 tar ,甚至只为测试不为实用的话直接 cat 在一起)后再压缩。
    rekulas
        11
    rekulas  
       2022-02-23 16:31:25 +08:00
    "把 27 个 PNG 打包成一个 JS 文件"
    你可以再尝试下只打包不 encode 试试能否继续压缩
    3dwelcome
        12
    3dwelcome  
    OP
       2022-02-23 16:33:28 +08:00
    @vicalloy 有道理,应该是 zip 打包算法没把 27 张看成一个整体,导致压缩无效的。

    这点 7z 好很多。
    noe132
        13
    noe132  
       2022-02-23 16:35:32 +08:00
    png 的压缩也有压缩级别的。只是大部分软件并没有给你一个调节参数。建议用 apngopt 压一遍,用 7zip 15 iterarions 以上
    tsanie
        14
    tsanie  
       2022-02-24 11:12:30 +08:00
    我试了下 android sdk 里 paper-card 示例中的 5 张图片,应该是 png 压缩级别高且优化输出后的。

    | 项目 | 大小 |
    | :---- | ----: |
    | 加起来大小 | 1,676,149 |
    | 7z 极限压缩 | 1,649,267 |
    | zip 打包 | 1,650,731 |
    | tar.gz | 1,651,711 |
    | base64 后 zip 打包 | 1,660,597 |
    | base64 后 tar.gz | 1,667,404 |

    这个示例中 zip 直接打包反而是表现最好的了。
    tsanie
        15
    tsanie  
       2022-02-24 11:13:50 +08:00
    @tsanie 嘴瓢,除 7z 以外
    3dwelcome
        16
    3dwelcome  
    OP
       2022-02-24 11:22:36 +08:00
    @tsanie 我 27 张图片里有相似图片,加一起确实能稍微提升一点压缩率。

    ZIP 单独打包,每个文件都是独立压缩,并没有前后文件关联性,压缩率就很低。

    除非你是这种,5 张图片相互毫无关联那种。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   4615 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 09:52 · PVG 17:52 · LAX 02:52 · JFK 05:52
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.