This section discusses some example Python programs that use the png module for reading and writing PNG files.
The basic strategy is to create a object (instance of ) and then call its method with an open (binary) file, and the pixel data. The object encapsulates all the information about the PNG file: image size, colour, bit depth, and so on.
Create a one row image, that has all grey values from 0 to 255. This is a bit like Netpbm’s .
Note that our single row, generated by , must itself be enclosed in a list. That’s because the method expects a list of rows.
From now on will not be mentioned.
A Little Message¶
A list of strings holds a graphic in ASCII graphic form. We convert it to a list of integer lists (the required form for the method), and write it out as a black-and-white PNG (bilevel greyscale).
Note how we use (the length of the first row) for the x argument and (the number of rows) for the y argument.
The previous example, “a little message”, can be converted to colour simply by creating a PNG file with a palette. The only difference is that a palette argument is passed to the method instead of :
Note that the palette consists of two entries (the bit depth is 1 so there are only 2 possible colours). Each entry is an RGB triple. If we wanted transparency then we can use RGBA 4-tuples for each palette entry.
For colour images the input rows are generally 3 times as long as for greyscale, because there are 3 channels, RGB, instead of just one, grey. Below, the p literal has 2 rows of 9 values (3 RGB pixels per row). The spaces are just for your benefit, to mark out the separate pixels; they have no meaning in the code.
A further colour example illustrates some of the manoeuvres you have to perform in Python to get the pixel data in the right format.
Say we want to produce a PNG image with 1 row of 8 pixels, with all the colours from a 3-bit colour system (with 1-bit for each channel; such systems were common on 8-bit micros from the 1980s).
We produce all possible 3-bit numbers:
We can convert each number into an RGB triple by assigning bit 0 to blue, bit 1 to red, bit 2 to green (the convention used by a certain 8-bit micro):
(later on we will convert False into 0, and True into 255, so don’t worry about that just yet). Here we have each pixel as a tuple. We want to flatten the pixels so that we have just one row. In other words instead of [(R,G,B), (R,G,B), ...] we want [R,G,B,R,G,B,...]. It turns out that is just what we need:
Note that the is not necessary, we can usually use the iterator directly instead. I just used here so we can see the result.
Now to convert False to 0 and True to 255 we can multiply by 255 (Python use’s Iverson’s convention, so , ). We could do that with . Or, we could use a “magic” bound method:
Now we write the PNG file out:
The basic strategy is to create a object (a instance), then call its method to extract the size, and pixel data.
The constructor can take either a filename, a file-like object, or a sequence of bytes directly. Here we use to download a PNG file from the internet.
The method returns a 4-tuple. Note that the pixels are returned as an iterator (not always, and the interface doesn’t guarantee it; the returned value might be an iterator or a sequence).
We have extracted the top row of the image. Note that the row itself is an (see module ), but in general any suitable sequence type may be returned by . The values in the row are all integers less than 4, because the image has a bit depth of 2.
NumPy is a package for scientific computing with Python. It is not part of a standard Python installation, it is downloaded and installed separately if needed. Numpy’s array manipulation facilities make it good for doing certain type of image processing, and scientific users of NumPy may wish to output PNG files for visualisation.
PyPNG does not have any direct integration with NumPy, but the basic data format used by PyPNG, an iterator over rows, is fairly easy to get into two- or three-dimensional NumPy arrays.
The code in this section is extracted from , which is a complete runnable example in the subdirectory of the source distribution. Code was originally written by Mel Raab, but has been hacked around since then.
PNG to NumPy array (reading)¶
The best thing to do (I think) is to convert each PyPNG row to a 1-dimensional numpy array, then stack all of those arrays together to make a 2-dimensional array. A number of features make this surprising compact. Say pngdata is the row iterator returned from . The following code will slurp it into a 2-dimensional numpy array:
Note that the use of , above, means that an array with data type is created which is suitable for bit depth 16 images. Replace with to create an array with a byte data type (suitable for bit depths up to 8).
For some operations it’s easier to have the image data in a 3-dimensional array. This plays to NumPy’s strengths:
NumPy array to PNG (writing)¶
Reshape your NumPy data into a 2-dimensional array, then use the fact that a NumPy array is an iterator over its rows:
Currently (writing on 2009-04-16) this generates a warning; this warning appears to be a bug/limitation in NumPy, but it is harmless.
IntroductionThis is the documentation for png++ the C++ wrapper for libpng. This page documents png++ version 0.2.1.
Png++ aims to provide simple yet powerful C++ interface to libpng, the PNG reference implementation library. Png++ is free software distributed under a modified variant of BSD license.
- Added support for tRNS chunk.
- Added non-std IO streams support.
- Fixed 16-bit endianness problems.
- Improved test script.
Getting startedThe following code demonstrates how to read and write PNG images using png++:
The code reads an image from the file named , then writes the image to a file named . The image class template allows you to specify the desired pixel type for the image data. The available pixel types include: RGB, Grayscale and Indexed pixels. Some of the pixel types can have an alpha channel.
The png++ naturally supports reading PNG images of any color type into RGB or Grayscale pixel buffers (with optional alpha channel). This is particularly useful for an image viewer if it needs to display the PNG image on, for example, RGB device regardless of the image color type.
On the other hand one might want to read only images of particular type. With png++ you can specify it this way:
InstallingPng++ comes as a set of header files and does not require compilation to be installed. For the same reason there are no binary packages for png++.
- png++ works with libpng-1.2.x.
- png++ compiles with g++-4.1 and g++-4.2. Other version should work well too.
- png++ relies on GNU make for compiling tests and examples; in particular it uses "remaking makefiles" feature
- Documentation is produced using doxygen. See the bottom of this page for doxygen version used to compile these docs.
Installing png++Follow these instructions in order to install png++:
- Unpack source package: $ tar -zxf png++-0.2.x.tar.gz -C ~/src
- Go to your brand new png++ sources directory:
- Issue to test how it's doing: This will compile examples in the directory. If everything goes well, try (or which is the same as above) to run the test suite. If tests do not produce error messages then probably all is OK.
- Now you can create documentation (optional). Use to run in the sources directory.
- Now it is time to become and install png++ into your system. It's OK to issue under ordinary user permissions if you want to install png++ into your home directory. Run the following command: $ make install PREFIX=$HOMEto copy png++ header files to and documentation files to . Without a png++ installs to .
Working with imagesIn png++ you can create new images like this:
Optionally, you may specifyto produce an interlaced image.
If you are writing an indexed colors image, you should provide a palette (colormap). One of the ways to do this is the following:
It is not absolutely necessary to have the whole image data in memory in order to write a PNG file. You can use generator class template to write the image row-by-row. An example of this is provided in bundled with the sources package.
The same holds for reading images too. You can use consumer class template in order to read the image data row-by-row. This might help in applications which have to deal with large PNG images but do not want to read the entire image into memory.
You can read or write images from/to generic IO stream, not only file on disk. Check out , overloads in the reference manual.
Compiling your programsUse the following command to compile your program:
and the following to link it:
When compiling you should add if you have installed png++ to non-standard location, like your home directory.
In your program, the line
brings in all the header files in png++ which should be suitable for the most of the applications. You may include only the headers you really use, for example:
If do not want to install png++ headers you still can compile your programs. Just create a subdirectory named somewhere in your project tree and copy all of the .hpp files in png++ distribution there. Then use appropriate compiler options to add this directory into the header search path.
- To get information about specific features, use reference (can be reached from the top of this page).
- If you are looking for more example code, please go to the directory of the source distribution. You may also find sources in the directory insightful (well, somewhat).
- Have a question? Check out Getting help section below.
- Of course, your ultimate source for learning is the source code.
DownloadThe project is hosted at Savannah: http://savannah.nongnu.org/projects/pngpp/
Released source packages can be found here: http://download.savannah.nongnu.org/releases/pngpp/
Also, you can check out sources directly from SVN repository: svn://svn.sv.nongnu.org/pngpp/trunk/ or http://svn.sv.nongnu.org/pngpp/trunk/ (for people w/o outgoing svn).
Online version of this documentation can be found here: http://www.nongnu.org/pngpp/doc/0.2.1/index.html
BugsThe following is a list of known bugs and limitations:
- Lacks support for output transformations
- Lacks support for optional/unknown chunks in PNG data stream
- Documentation sucks
To report bugs, please use Savannah bug tracker: http://savannah.nongnu.org/bugs/?group=pngpp&func=additem
Do not forget to check if the bug was already filed.
Getting helpThere is a mailing list for developers: http://lists.nongnu.org/mailman/listinfo/pngpp-devel
You can also contact me by dropping a mail to <email@example.com>.
Generated on Sat Dec 8 13:43:56 2007 for png++ by 1.5.3-20071008