Index: src/_png.cpp =================================================================== --- src/_png.cpp (revision 7230) +++ src/_png.cpp (working copy) @@ -178,8 +178,11 @@ Py::Object _png_module::read_png(const Py::Tuple& args) { - args.verify_length(1); + args.verify_length(1,2); std::string fname = Py::String(args[0]); + bool raw = false; + if (args.length() == 2) + raw = Py::Boolean(args[1]); png_byte header[8]; // 8 is the maximum size that can be checked @@ -213,16 +216,21 @@ png_uint_32 width = info_ptr->width; png_uint_32 height = info_ptr->height; + // Bit depth can be 1, 2, 4, 8, or 16 int bit_depth = info_ptr->bit_depth; - + double max_value = (1 << bit_depth) - 1; // For scaling later // Unpack 1, 2, and 4-bit images if (bit_depth < 8) png_set_packing(png_ptr); - // If sig bits are set, shift data + // If a pngs max value does not use the full bit depth, then values are shifted up during writing. + // This shifts them back and then recalculates max_value png_color_8p sig_bit; if ((info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) && png_get_sBIT(png_ptr, info_ptr, &sig_bit)) + { png_set_shift(png_ptr, sig_bit); + max_value = (1 << sig_bit->red) - 1; // RGB values appear to always be equal + } // Convert big endian to little if (bit_depth == 16) @@ -260,12 +268,13 @@ dimensions[2] = 3; //RGB images else dimensions[2] = 1; //Greyscale images + //For gray, return an x by y array, not an x by y by 1 int num_dims = (info_ptr->color_type & PNG_COLOR_MASK_COLOR) ? 3 : 2; + + // If read mode is raw give back ints, otherwise float between 0 and 1 + PyArrayObject *A = (PyArrayObject *) PyArray_SimpleNew(num_dims, dimensions, (raw) ? PyArray_UINT16 : PyArray_FLOAT); - double max_value = (1 << ((bit_depth < 8) ? 8 : bit_depth)) - 1; - PyArrayObject *A = (PyArrayObject *) PyArray_SimpleNew(num_dims, dimensions, PyArray_FLOAT); - for (png_uint_32 y = 0; y < height; y++) { png_byte* row = row_pointers[y]; for (png_uint_32 x = 0; x < width; x++) { @@ -273,13 +282,13 @@ if (bit_depth == 16) { png_uint_16* ptr = &reinterpret_cast (row)[x * dimensions[2]]; for (png_uint_32 p = 0; p < (png_uint_32)dimensions[2]; p++) - *(float*)(A->data + offset + p*A->strides[2]) = (float)(ptr[p]) / max_value; + raw ? *reinterpret_cast(A->data + offset + p*A->strides[2]) = ptr[p] : + *reinterpret_cast(A->data + offset + p*A->strides[2]) = static_cast(ptr[p]) / max_value; } else { png_byte* ptr = &(row[x * dimensions[2]]); for (png_uint_32 p = 0; p < (png_uint_32)dimensions[2]; p++) - { - *(float*)(A->data + offset + p*A->strides[2]) = (float)(ptr[p]) / max_value; - } + raw ? *reinterpret_cast(A->data + offset + p*A->strides[2]) = ptr[p] : + *reinterpret_cast(A->data + offset + p*A->strides[2]) = static_cast(ptr[p]) / max_value; } } } Index: lib/matplotlib/image.py =================================================================== --- lib/matplotlib/image.py (revision 7230) +++ lib/matplotlib/image.py (working copy) @@ -739,7 +739,7 @@ rows, cols, buffer = im.as_rgba_str() _png.write_png(buffer, cols, rows, fname) -def imread(fname): +def imread(fname, raw=False): """ Return image file in *fname* as :class:`numpy.array`. @@ -773,7 +773,7 @@ return im handler = handlers[ext] - return handler(fname) + return handler(fname, raw) def imsave(fname, arr, vmin=None, vmax=None, cmap=None, format=None, origin=None): Index: examples/tests/pngsuite/pngsuite.py =================================================================== --- examples/tests/pngsuite/pngsuite.py (revision 7230) +++ examples/tests/pngsuite/pngsuite.py (working copy) @@ -24,6 +24,6 @@ cmap = cm.gray plt.imshow(data, extent=[i,i+1,0,1], cmap=cmap) -plt.gca().get_frame().set_facecolor("#ddffff") +plt.gca().patch.set_facecolor("#ddffff") plt.gca().set_xlim(0, len(files)) plt.show()