| #!/usr/bin/env python |
| |
| import array |
| |
| import png |
| |
| Description = """Enlarge images by an integer factor horizontally and vertically.""" |
| |
| |
| def rescale(inp, out, xf, yf): |
| while True: |
| r = png.Reader(file=inp) |
| try: |
| r.preamble() |
| except EOFError: |
| return |
| |
| rescale_1(out, r, xf, yf) |
| |
| |
| def rescale_1(out, im, xf, yf): |
| """Rescale a single PNG image, im, |
| and write it to the output stream out. |
| `xf` and `yf` give the x factor and y factor. |
| """ |
| |
| _, _, pixels, info = im.asDirect() |
| |
| typecode = "BH"[info["bitdepth"] > 8] |
| planes = info["planes"] |
| |
| resize(info, xf, yf) |
| |
| # Values per row, target row. |
| vpr = info["size"][0] * planes |
| |
| def iterscale(): |
| for row in pixels: |
| bigrow = array.array(typecode, [0] * vpr) |
| row = array.array(typecode, row) |
| for c in range(planes): |
| channel = row[c::planes] |
| for i in range(xf): |
| bigrow[i * planes + c :: xf * planes] = channel |
| for _ in range(yf): |
| yield bigrow |
| |
| w = png.Writer(**info) |
| w.write(out, iterscale()) |
| |
| |
| def resize(d, xf, yf): |
| """Edit the "size" member of the dict d, scaling it by `xf` an `yf`.""" |
| |
| x, y = d["size"] |
| x *= xf |
| y *= yf |
| d["size"] = (x, y) |
| |
| |
| def main(argv=None): |
| import argparse |
| import sys |
| |
| if argv is None: |
| argv = sys.argv |
| |
| parser = argparse.ArgumentParser(description=Description) |
| parser.add_argument("--xfactor", type=int, default=2) |
| parser.add_argument("--yfactor", type=int, default=2) |
| parser.add_argument("--factor", type=int) |
| parser.add_argument("PNG", type=png.cli_open, nargs="?", default="-") |
| args = parser.parse_args() |
| |
| if args.factor: |
| args.xfactor = args.yfactor = args.factor |
| |
| return rescale(args.PNG, png.binary_stdout(), args.xfactor, args.yfactor) |
| |
| |
| if __name__ == "__main__": |
| main() |