summaryrefslogtreecommitdiffstats
path: root/build/pypng/pnghist
diff options
context:
space:
mode:
Diffstat (limited to 'build/pypng/pnghist')
-rw-r--r--build/pypng/pnghist79
1 files changed, 79 insertions, 0 deletions
diff --git a/build/pypng/pnghist b/build/pypng/pnghist
new file mode 100644
index 0000000..4fbbd0a
--- /dev/null
+++ b/build/pypng/pnghist
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+# $URL: http://pypng.googlecode.com/svn/trunk/code/pnghist $
+# $Rev: 153 $
+# PNG Histogram
+# Only really works on grayscale images.
+
+from array import array
+import getopt
+
+import png
+
+def decidemax(level):
+ """Given an array of levels, decide the maximum value to use for the
+ histogram. This is normally chosen to be a bit bigger than the 99th
+ percentile, but if the 100th percentile is not much more (within a
+ factor of 2) then the 100th percentile is chosen.
+ """
+
+ truemax = max(level)
+ sl = level[:]
+ sl.sort(reverse=True)
+ i99 = int(round(len(level)*0.01))
+ if truemax <= 2*sl[i99]:
+ return truemax
+ return 1.05*sl[i99]
+
+def hist(out, inp, verbose=None):
+ """Open the PNG file `inp` and generate a histogram."""
+
+ r = png.Reader(file=inp)
+ x,y,pixels,info = r.asDirect()
+ bitdepth = info['bitdepth']
+ level = [0]*2**bitdepth
+ for row in pixels:
+ for v in row:
+ level[v] += 1
+ maxlevel = decidemax(level)
+
+ h = 100
+ outbitdepth = 8
+ outmaxval = 2**outbitdepth - 1
+ def genrow():
+ for y in range(h):
+ y = h-y-1
+ # :todo: vary typecode according to outbitdepth
+ row = array('B', [0]*len(level))
+ fl = y*maxlevel/float(h)
+ ce = (y+1)*maxlevel/float(h)
+ for x in range(len(row)):
+ if level[x] <= fl:
+ # Relies on row being initialised to all 0
+ continue
+ if level[x] >= ce:
+ row[x] = outmaxval
+ continue
+ frac = (level[x] - fl)/(ce - fl)
+ row[x] = int(round(outmaxval*frac))
+ yield row
+ w = png.Writer(len(level), h, gamma=1.0,
+ greyscale=True, alpha=False, bitdepth=outbitdepth)
+ w.write(out, genrow())
+ if verbose: print >>verbose, level
+
+def main(argv=None):
+ import sys
+
+ if argv is None:
+ argv = sys.argv
+ argv = argv[1:]
+ opt,arg = getopt.getopt(argv, '')
+
+ if len(arg) < 1:
+ f = sys.stdin
+ else:
+ f = open(arg[0])
+ hist(sys.stdout, f)
+
+if __name__ == '__main__':
+ main()