1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
|
#!/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()
|