Back in April I submitted a patch that allowed imread() to correctly read PNGs that have odd bit-depths, ie not 8 or 16 (I actually submitted that to the Users list as I was unsure of protocol). There were a couple of things I left unfinished that I've finally got round to looking at again.
The main remaining issue for me is that PNG specifies that all bit depths should be scaled to have the same maximum brightness, so that a value of 8191 in an 13-bit image is displayed the same as 65535 in a 16-bit image. Unfortunately, the LabView drivers for the 12-bit CCD in our lab do not follow this convention. A higher bit-depth from this setup means the image was brighter in an absolute sense and no scaling takes place. So this is not an error with Matplotlib as such, but more about having a decent way to handle iffy PNGs. It is worth noting that Matlab does not handle these PNGs well either (We have to query the image file using iminfo and then correct it) and PIL ignores anything above 8-bits as far as I can tell.
A simple method, in my mind, and originally suggested by Andrew Straw is to add a keyword argument to imread() that indicates whether a user wants floats scaled between 0 and 1, or the raw byte values which they can then scale as required. This then gets passed to read_png(), which does the scaling if necessary and if not returns an array of UINT16s. I wrote a patch that does this, changing both image.py and _png.cpp. I'm very much open to other suggestions, as I didn't particularly want to fiddle with a core function like imread() and I'm fairly new to Python. In particular I have not changed anything to do with PIL - although it would not be much work to update pil_to_array() to follow the same behaviour as read_png(). I have tested this with the pngsuite.py*, and if desired I can submit an extended version of this that tests the extended bit-depth images from the PNG suite.
Thanks in advance,
* My patch also includes a minor change to pngsuite.py which was throwing a deprecation warning about using get_frame() istead of patch
png_patch.txt (4.06 KB)