使用ZopfliPNG自动优化CSS文件(数据URI)内的PNG
我有一些CSS和LESS文件,内嵌图像(base64编码数据URI [AKA数据URL]),其中一些是PNG。 我希望这些PNG能够以自动化方式使用ZopfliPNG进行编码。
可悲的是,ZopfliPNG似乎只能处理文件,而不能处理stdin / stdout(像“支持管道输入”这样的bug跟踪器条目仍处于打开状态),这使事情变得更加复杂。
Leanify(我写)支持在CSS文件中优化数据URI图像。 它使用ZopfliPNG内部用于PNG文件。
它比你的python脚本有一些优点:
它还支持其他图像格式,如JPEG,ICO和SVG。
它不需要临时文件,一切都在内存中完成。
  数据URI搜索具有更好的兼容性。  对于CSS文件, url(和data:image之间可能存在'或" ,它还支持在可能没有url( HTML和JS文件中搜索url(根本就没有。 
https://github.com/JayXon/Leanify
基于Python的解决方案:
#!/usr/bin/env python
''' Tool to optimize PNG images embedded as data URLs in CSS files or similar
using ZopfliPNG.
'''
import base64
import re
import subprocess
import sys
import tempfile
__author__ = "phk @ stackoverflow (https://stackoverflow.com/users/2261442)"
__version__ = "1.0.1"
# parameters for ZopfliPNG controlling the optimization method
OPTIMIZATION_PARAMS = [
    "-m",
    "--lossy_transparent",
    "--iterations=1000"
]
if len(sys.argv) < 2:
    print("Usage: {} ZOPFLIPNG_EXECUTABLE TARGET_FILES...".format(sys.argv[0]))
    sys.exit(1)
zopflipng = sys.argv[1]
targets = sys.argv[2:]
# regex to match all the data urls with PNGs inside CSS or therelike
# but only return the base64 encoded PNG data
inline_png_re = re.compile(
    r"(?<=url(data:image/png;base64,)[A-Za-z0-9+/]+=*(?=))")
# create temporary input/output files for ZopfliPNG, it only deals with files
with tempfile.NamedTemporaryFile('w+b') as tmpf_in, 
        tempfile.NamedTemporaryFile('r+b') as tmpf_out:
    def replace_inline_png(match):
        ''' Replace all the PNGs inside data URLs with optimized versions. '''
        orig_data = match.group(0)
        try:
            data = base64.b64decode(orig_data)
        except TypeError:
            print("Invalid base64 string. Skipping this data URL.")
            return orig_data
        # prepare input file for ZopfliPNG
        tmpf_in.seek(0)  # because the temporary input file gets re-used
        tmpf_in.truncate()
        tmpf_in.write(data)
        tmpf_in.flush()  # because the file is kept open
        tmpf_out.seek(0)
        tmpf_out.truncate()
        return_code = subprocess.call([
            zopflipng,
            "-y",  # silent overwriting of output file necessary
        ] + OPTIMIZATION_PARAMS + [
            tmpf_in.name,
            tmpf_out.name
        ])
        if return_code:
            print("ZopfliPNG reported an error. Skipping this PNG.")
            return orig_data
        # read zopflipng results from output file
        data = tmpf_out.read()
        return base64.b64encode(data)
    def optimize_file(target):
        ''' Optimize the PNGs embedded as data URLs in target file. '''
        try:
            with open(target) as f_in:
                contents = f_in.read()
        except IOError:
            print("Can't open {} for reading!".format(target))
            return
        # replace the inline PNGs with optimized versions
        contents = inline_png_re.sub(replace_inline_png, contents)
        try:
            # write the changed file contents
            with open(target, 'w') as f_out:
                f_out.write(contents)
        except IOError:
            print("Can't open {} for writing!".format(target))
            return
    for target in targets:
        optimize_file(target)
在假设输入和输出文件应该不同的情况下工作(从我的测试ZopfliPNG也可以工作,它的输入和输出与你期望从这个程序中得到的结果是一样的,但是可以肯定的是,参数显然似乎强制一个使用不同的输出文件)。 有一个微小的优化,而它重用它创建的临时文件。
要在CSS / LESS / ...文件夹中使用它,例如在UNIX shell中,您可以这样做:
find /css-folder/ -type f -name '*.*ss' -exec 
  /path/to/this_script_here.py /path/to/zopfli/zopflipng {} +
上一篇: Automated optimization of PNGs inside CSS files (data URIs) using ZopfliPNG
