2
# $URL: http://pypng.googlecode.com/svn/trunk/code/pipcomposite $
5
# Image alpha compositing.
8
pipcomposite [--background #rrggbb] file.png
10
Composite an image onto a background and output the result. The
11
background colour is specified with an HTML-style triple (3, 6, or 12
12
hex digits), and defaults to black (#000).
14
The output PNG has no alpha channel.
16
It is valid for the input to have no alpha channel, but it doesn't
17
make much sense: the output will equal the input.
22
def composite(out, inp, background):
25
p = png.Reader(file=inp)
26
w,h,pixel,info = p.asRGBA()
29
outinfo['alpha'] = False
30
outinfo['planes'] -= 1
31
outinfo['interlace'] = 0
33
# Convert to tuple and normalise to same range as source.
34
background = rgbhex(background)
35
maxval = float(2**info['bitdepth'] - 1)
36
background = map(lambda x: int(0.5 + x*maxval/65535.0),
38
# Repeat background so that it's a whole row of sample values.
43
# Remove alpha from row, then create a list with one alpha
44
# entry _per channel value_.
45
# Squirrel the alpha channel away (and normalise it).
46
t = map(lambda x: x/maxval, row[3::4])
52
assert len(alpha) == len(row) == len(background)
53
yield map(lambda a,v,b: int(0.5 + a*v + (1.0-a)*b),
54
alpha, row, background)
56
w = png.Writer(**outinfo)
57
w.write(out, iterrow())
60
"""Take an HTML style string of the form "#rrggbb" and return a
61
colour (R,G,B) triple. Following the initial '#' there can be 3, 6,
62
or 12 digits (for 4-, 8- or 16- bits per channel). In all cases the
63
values are expanded to a full 16-bit range, so the returned values
64
are all in range(65536).
69
assert len(s) in (3,6,12)
71
# Create a target list of length 12, and expand the string s to make
84
return map(lambda x: int(x, 16), (s[:4], s[4:8], s[8:]))
86
class Usage(Exception):
100
opt,arg = getopt.getopt(argv, '',
102
except getopt.error, msg:
106
if o in ['--background']:
109
print >>sys.stderr, __doc__
110
print >>sys.stderr, str(err)
114
f = open(arg[0], 'rb')
117
return composite(sys.stdout, f, background)
120
if __name__ == '__main__':