summaryrefslogtreecommitdiffstats
path: root/build/pypng/exnumpy.py
diff options
context:
space:
mode:
Diffstat (limited to 'build/pypng/exnumpy.py')
-rw-r--r--build/pypng/exnumpy.py128
1 files changed, 128 insertions, 0 deletions
diff --git a/build/pypng/exnumpy.py b/build/pypng/exnumpy.py
new file mode 100644
index 0000000..82daf0a
--- /dev/null
+++ b/build/pypng/exnumpy.py
@@ -0,0 +1,128 @@
+#!/usr/bin/env python
+# $URL: http://pypng.googlecode.com/svn/trunk/code/exnumpy.py $
+# $Rev: 126 $
+
+# Numpy example.
+# Original code created by Mel Raab, modified by David Jones.
+
+'''
+ Example code integrating RGB PNG files, PyPNG and NumPy
+ (abstracted from Mel Raab's functioning code)
+'''
+
+# http://www.python.org/doc/2.4.4/lib/module-itertools.html
+import itertools
+
+import numpy
+import png
+
+
+''' If you have a PNG file for an RGB image,
+ and want to create a numpy array of data from it.
+'''
+# Read the file "picture.png" from the current directory. The `Reader`
+# class can take a filename, a file-like object, or the byte data
+# directly; this suggests alternatives such as using urllib to read
+# an image from the internet:
+# png.Reader(file=urllib.urlopen('http://www.libpng.org/pub/png/PngSuite/basn2c16.png'))
+pngReader=png.Reader(filename='picture.png')
+# Tuple unpacking, using multiple assignment, is very useful for the
+# result of asDirect (and other methods).
+# See
+# http://docs.python.org/tutorial/introduction.html#first-steps-towards-programming
+row_count, column_count, pngdata, meta = pngReader.asDirect()
+bitdepth=meta['bitdepth']
+plane_count=meta['planes']
+
+# Make sure we're dealing with RGB files
+assert plane_count == 3
+
+''' Boxed row flat pixel:
+ list([R,G,B, R,G,B, R,G,B],
+ [R,G,B, R,G,B, R,G,B])
+ Array dimensions for this example: (2,9)
+
+ Create `image_2d` as a two-dimensional NumPy array by stacking a
+ sequence of 1-dimensional arrays (rows).
+ The NumPy array mimics PyPNG's (boxed row flat pixel) representation;
+ it will have dimensions ``(row_count,column_count*plane_count)``.
+'''
+# The use of ``numpy.uint16``, below, is to convert each row to a NumPy
+# array with data type ``numpy.uint16``. This is a feature of NumPy,
+# discussed further in
+# http://docs.scipy.org/doc/numpy/user/basics.types.html .
+# You can use avoid the explicit conversion with
+# ``numpy.vstack(pngdata)``, but then NumPy will pick the array's data
+# type; in practice it seems to pick ``numpy.int32``, which is large enough
+# to hold any pixel value for any PNG image but uses 4 bytes per value when
+# 1 or 2 would be enough.
+# --- extract 001 start
+image_2d = numpy.vstack(itertools.imap(numpy.uint16, pngdata))
+# --- extract 001 end
+# Do not be tempted to use ``numpy.asarray``; when passed an iterator
+# (`pngdata` is often an iterator) it will attempt to create a size 1
+# array with the iterator as its only element.
+# An alternative to the above is to create the target array of the right
+# shape, then populate it row by row:
+if 0:
+ image_2d = numpy.zeros((row_count,plane_count*column_count),
+ dtype=numpy.uint16)
+ for row_index, one_boxed_row_flat_pixels in enumerate(pngdata):
+ image_2d[row_index,:]=one_boxed_row_flat_pixels
+
+del pngReader
+del pngdata
+
+
+''' Reconfigure for easier referencing, similar to
+ Boxed row boxed pixel:
+ list([ (R,G,B), (R,G,B), (R,G,B) ],
+ [ (R,G,B), (R,G,B), (R,G,B) ])
+ Array dimensions for this example: (2,3,3)
+
+ ``image_3d`` will contain the image as a three-dimensional numpy
+ array, having dimensions ``(row_count,column_count,plane_count)``.
+'''
+# --- extract 002 start
+image_3d = numpy.reshape(image_2d,
+ (row_count,column_count,plane_count))
+# --- extract 002 end
+
+
+''' ============= '''
+
+''' Convert NumPy image_3d array to PNG image file.
+
+ If the data is three-dimensional, as it is above, the best thing
+ to do is reshape it into a two-dimensional array with a shape of
+ ``(row_count, column_count*plane_count)``. Because a
+ two-dimensional numpy array is an iterator, it can be passed
+ directly to the ``png.Writer.write`` method.
+'''
+
+row_count, column_count, plane_count = image_3d.shape
+assert plane_count==3
+
+pngfile = open('picture_out.png', 'wb')
+try:
+ # This example assumes that you have 16-bit pixel values in the data
+ # array (that's what the ``bitdepth=16`` argument is for).
+ # If you don't, then the resulting PNG file will likely be
+ # very dark. Hey, it's only an example.
+ pngWriter = png.Writer(column_count, row_count,
+ greyscale=False,
+ alpha=False,
+ bitdepth=16)
+ # As of 2009-04-13 passing a numpy array that has an element type
+ # that is a numpy integer type (for example, the `image_3d` array has an
+ # element type of ``numpy.uint16``) generates a deprecation warning.
+ # This is probably a bug in numpy; it may go away in the future.
+ # The code still works despite the warning.
+ # See http://code.google.com/p/pypng/issues/detail?id=44
+# --- extract 003 start
+ pngWriter.write(pngfile,
+ numpy.reshape(image_3d, (-1, column_count*plane_count)))
+# --- extract 003 end
+finally:
+ pngfile.close()
+