@@ 1,27 1,81 @@
#!/usr/bin/env python3
+import os
+import contextlib
import compress_ref
-def bytes_from_stream(stream):
+def bytes_from_hex_stream(stream):
for bstr in stream:
n = int(bstr, 16)
yield n
+def bytes_from_binary(f):
+ while True:
+ b = f.read(1)
+ if not b:
+ break
+ yield b[0]
+
+def add_gif_frame(gif, frame):
+ gif.append_data(numpy.array([[85*(3 - p) for p in compress_ref.lines_to_pixels([l], 160)] for l in frame], dtype='uint8'))
+
+def ensure_dir(path):
+ dp = os.path.dirname(path)
+ if dp:
+ os.makedirs(dp, exist_ok=True)
+
if __name__ == '__main__':
import argparse
import sys
parser = argparse.ArgumentParser()
- parser.add_argument('--output', '-o', help='Output pgms with this base name')
+ parser.add_argument('--output-pgm', '-o', help='Output pgms with this base name')
+ parser.add_argument('--output-gif', '-g',
+ help='''Output a gif animation to file. Requires imageio python library.
+ The output GIF will be large and unoptimised, try gifsicle to create a
+ smaller GIF, or convert to webp with gif2webp.''')
+ parser.add_argument('--text', '-t', help='Data is newline-separated hex strings rather than raw binary')
+ parser.add_argument('--verbose', '-v', action='store_true', help='Verbose decompression')
+ parser.add_argument('file', nargs='?', help='File to read data from')
args = parser.parse_args()
codec = compress_ref.CODEC(160, 144, 4)
frame_buf = []
frame_count = 0
- for line in codec.decompress(bytes_from_stream(sys.stdin), verbose=True):
- if args.output:
+ with contextlib.ExitStack() as stack:
+ if args.file:
+ f = stack.enter_context(open(args.file, 'r' if args.text else 'rb'))
+ else:
+ f = sys.stdin if args.text else sys.stdin.buffer
+
+ if args.text:
+ stream = bytes_from_hex_stream(f)
+ else:
+ stream = bytes_from_binary(f)
+
+ if args.output_gif:
+ import imageio
+ import numpy
+ ensure_dir(args.output_gif)
+ gif = stack.enter_context(imageio.get_writer(args.output_gif, mode='I', fps=60, palettesize=4))
+
+ if args.output_pgm:
+ ensure_dir(args.output_pgm)
+
+ for line in codec.decompress(stream, verbose=args.verbose):
frame_buf.append(line)
if len(frame_buf) == 144:
- compress_ref.dump_pgm('{}{:03d}.pgm'.format(args.output, frame_count), frame_buf)
+ if args.output_pgm:
+ compress_ref.dump_pgm('{}{:05d}.pgm'.format(args.output_pgm, frame_count), frame_buf)
+ if args.output_gif:
+ add_gif_frame(gif, frame_buf)
+
+ if not args.verbose:
+ sys.stdout.write('\r{: 9d}'.format(frame_count))
+ sys.stdout.flush()
frame_count += 1
frame_buf = []
- print('{:080x}'.format(line))
+ if args.verbose:
+ print('{:080x}'.format(line))
+
+ if not args.verbose:
+ print()