TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags
[wireshark-sm.git] / tools / compress-pngs.py
blobed3e32a52564360f84073b38acf3cc328f7ca929
1 #!/usr/bin/env python3
3 # compress-pngs.py - Compress PNGs
5 # By Gerald Combs <gerald@wireshark.org
7 # SPDX-License-Identifier: GPL-2.0-or-later
9 '''Run various compression and optimization utilities on one or more PNGs'''
11 import argparse
12 import concurrent.futures
13 import shutil
14 import subprocess
15 import sys
17 PNG_FILE_ARG = '%PNG_FILE_ARG%'
19 def get_compressors():
20 # Add *lossless* compressors here.
21 compressors = {
22 # https://github.com/shssoichiro/oxipng
23 'oxipng': { 'args': ['--opt', 'max', '--strip', 'safe', PNG_FILE_ARG] },
24 # http://optipng.sourceforge.net/
25 'optipng': { 'args': ['-o3', '-quiet', PNG_FILE_ARG] },
26 # https://github.com/amadvance/advancecomp
27 'advpng': { 'args': ['--recompress', '--shrink-insane', PNG_FILE_ARG] },
28 # https://github.com/amadvance/advancecomp
29 'advdef': { 'args': ['--recompress', '--shrink-insane', PNG_FILE_ARG] },
30 # https://pmt.sourceforge.io/pngcrush/
31 'pngcrush': { 'args': ['-q', '-ow', '-brute', '-reduce', '-noforce', PNG_FILE_ARG, 'pngcrush.$$$$.png'] },
32 # https://github.com/fhanau/Efficient-Compression-Tool
33 'ect': { 'args': ['-5', '--mt-deflate', '--mt-file', '-strip', PNG_FILE_ARG]}
35 for compressor in compressors:
36 compressor_path = shutil.which(compressor)
37 if compressor_path:
38 compressors[compressor]['path'] = compressor_path
39 return compressors
42 def compress_png(png_file, compressors):
43 for compressor in compressors:
44 if not compressors[compressor].get('path', False):
45 continue
47 args = compressors[compressor]['args']
48 args = [arg.replace(PNG_FILE_ARG, png_file) for arg in args]
50 try:
51 compress_proc = subprocess.run([compressor] + args)
52 except Exception:
53 print('{} returned {}:'.format(compressor, compress_proc.returncode))
56 def main():
57 parser = argparse.ArgumentParser(description='Compress PNGs')
58 parser.add_argument('--list', action='store_true',
59 help='List available compressors')
60 parser.add_argument('png_files', nargs='*', metavar='png file', help='Files to compress')
61 args = parser.parse_args()
63 compressors = get_compressors()
65 c_count = 0
66 for compressor in compressors:
67 if 'path' in compressors[compressor]:
68 c_count += 1
70 if c_count < 1:
71 sys.stderr.write('No compressors found\n')
72 sys.exit(1)
74 if args.list:
75 for compressor in compressors:
76 path = compressors[compressor].get('path', 'Not found')
77 print('{}: {}'.format(compressor, path))
78 sys.exit(0)
80 with concurrent.futures.ProcessPoolExecutor() as executor:
81 futures = []
82 for png_file in args.png_files:
83 print('Compressing {}'.format(png_file))
84 futures.append(executor.submit(compress_png, png_file, compressors))
85 concurrent.futures.wait(futures)
88 if __name__ == '__main__':
89 main()