@@ -42,16 +42,22 @@ class _png_module : public Py::ExtensionModule<_png_module>
4242 {
4343 add_varargs_method (" write_png" , &_png_module::write_png,
4444 " write_png(buffer, width, height, fileobj, dpi=None)" );
45- add_varargs_method (" read_png" , &_png_module::read_png ,
45+ add_varargs_method (" read_png" , &_png_module::read_png_float ,
4646 " read_png(fileobj)" );
47+ add_varargs_method (" read_png_float" , &_png_module::read_png_float,
48+ " read_png_float(fileobj)" );
49+ add_varargs_method (" read_png_uint8" , &_png_module::read_png_uint8,
50+ " read_png_uint8(fileobj)" );
4751 initialize (" Module to write PNG files" );
4852 }
4953
5054 virtual ~_png_module () {}
5155
5256private:
5357 Py::Object write_png (const Py::Tuple& args);
54- Py::Object read_png (const Py::Tuple& args);
58+ Py::Object read_png_uint8 (const Py::Tuple& args);
59+ Py::Object read_png_float (const Py::Tuple& args);
60+ PyObject* _read_png (const Py::Object& py_fileobj, const bool float_result);
5561};
5662
5763static void write_png_data (png_structp png_ptr, png_bytep data, png_size_t length)
@@ -286,16 +292,13 @@ static void read_png_data(png_structp png_ptr, png_bytep data, png_size_t length
286292 _read_png_data (py_file_obj, data, length);
287293}
288294
289- Py::Object
290- _png_module::read_png (const Py::Tuple& args )
295+ PyObject*
296+ _png_module::_read_png (const Py::Object& py_fileobj, const bool float_result )
291297{
292-
293- args.verify_length (1 );
294298 png_byte header[8 ]; // 8 is the maximum size that can be checked
295299 FILE* fp = NULL ;
296300 bool close_file = false ;
297301
298- Py::Object py_fileobj = Py::Object (args[0 ]);
299302#if PY3K
300303 int fd = PyObject_AsFileDescriptor (py_fileobj.ptr ());
301304 PyErr_Clear ();
@@ -457,35 +460,70 @@ _png_module::read_png(const Py::Tuple& args)
457460 // For gray, return an x by y array, not an x by y by 1
458461 int num_dims = (info_ptr->color_type & PNG_COLOR_MASK_COLOR) ? 3 : 2 ;
459462
460- double max_value = ( 1 << ((bit_depth < 8 ) ? 8 : bit_depth)) - 1 ;
461- PyArrayObject *A = (PyArrayObject *) PyArray_SimpleNew (
462- num_dims, dimensions, PyArray_FLOAT) ;
463+ PyArrayObject *A = NULL ;
464+ if (float_result) {
465+ double max_value = ( 1 << ((bit_depth < 8 ) ? 8 : bit_depth)) - 1 ;
463466
464- if (A == NULL )
465- {
466- throw Py::MemoryError (" Could not allocate image array" );
467- }
467+ A = (PyArrayObject *) PyArray_SimpleNew (num_dims, dimensions, NPY_FLOAT);
468468
469- for (png_uint_32 y = 0 ; y < height; y++)
470- {
471- png_byte* row = row_pointers[y];
472- for (png_uint_32 x = 0 ; x < width; x++)
469+ if (A == NULL )
473470 {
474- size_t offset = y * A->strides [0 ] + x * A->strides [1 ];
475- if (bit_depth == 16 )
471+ throw Py::MemoryError (" Could not allocate image array" );
472+ }
473+
474+ for (png_uint_32 y = 0 ; y < height; y++)
475+ {
476+ png_byte* row = row_pointers[y];
477+ for (png_uint_32 x = 0 ; x < width; x++)
476478 {
477- png_uint_16* ptr = &reinterpret_cast <png_uint_16*>(row)[x * dimensions[2 ]];
478- for (png_uint_32 p = 0 ; p < (png_uint_32)dimensions[2 ]; p++)
479+ size_t offset = y * A->strides [0 ] + x * A->strides [1 ];
480+ if (bit_depth == 16 )
481+ {
482+ png_uint_16* ptr = &reinterpret_cast <png_uint_16*>(row)[x * dimensions[2 ]];
483+ for (png_uint_32 p = 0 ; p < (png_uint_32)dimensions[2 ]; p++)
484+ {
485+ *(float *)(A->data + offset + p*A->strides [2 ]) = (float )(ptr[p]) / max_value;
486+ }
487+ }
488+ else
479489 {
480- *(float *)(A->data + offset + p*A->strides [2 ]) = (float )(ptr[p]) / max_value;
490+ png_byte* ptr = &(row[x * dimensions[2 ]]);
491+ for (png_uint_32 p = 0 ; p < (png_uint_32)dimensions[2 ]; p++)
492+ {
493+ *(float *)(A->data + offset + p*A->strides [2 ]) = (float )(ptr[p]) / max_value;
494+ }
481495 }
482496 }
483- else
497+ }
498+ } else {
499+ A = (PyArrayObject *) PyArray_SimpleNew (num_dims, dimensions, NPY_UBYTE);
500+
501+ if (A == NULL )
502+ {
503+ throw Py::MemoryError (" Could not allocate image array" );
504+ }
505+
506+ for (png_uint_32 y = 0 ; y < height; y++)
507+ {
508+ png_byte* row = row_pointers[y];
509+ for (png_uint_32 x = 0 ; x < width; x++)
484510 {
485- png_byte* ptr = &(row[x * dimensions[2 ]]);
486- for (png_uint_32 p = 0 ; p < (png_uint_32)dimensions[2 ]; p++)
511+ size_t offset = y * A->strides [0 ] + x * A->strides [1 ];
512+ if (bit_depth == 16 )
513+ {
514+ png_uint_16* ptr = &reinterpret_cast <png_uint_16*>(row)[x * dimensions[2 ]];
515+ for (png_uint_32 p = 0 ; p < (png_uint_32)dimensions[2 ]; p++)
516+ {
517+ *(png_byte*)(A->data + offset + p*A->strides [2 ]) = ptr[p] >> 8 ;
518+ }
519+ }
520+ else
487521 {
488- *(float *)(A->data + offset + p*A->strides [2 ]) = (float )(ptr[p]) / max_value;
522+ png_byte* ptr = &(row[x * dimensions[2 ]]);
523+ for (png_uint_32 p = 0 ; p < (png_uint_32)dimensions[2 ]; p++)
524+ {
525+ *(png_byte*)(A->data + offset + p*A->strides [2 ]) = ptr[p];
526+ }
489527 }
490528 }
491529 }
@@ -507,7 +545,22 @@ _png_module::read_png(const Py::Tuple& args)
507545 delete [] row_pointers[row];
508546 }
509547 delete [] row_pointers;
510- return Py::asObject ((PyObject*)A);
548+
549+ return (PyObject*)A;
550+ }
551+
552+ Py::Object
553+ _png_module::read_png_float (const Py::Tuple& args)
554+ {
555+ args.verify_length (1 );
556+ return Py::asObject (_read_png (args[0 ], true ));
557+ }
558+
559+ Py::Object
560+ _png_module::read_png_uint8 (const Py::Tuple& args)
561+ {
562+ args.verify_length (1 );
563+ return Py::asObject (_read_png (args[0 ], false ));
511564}
512565
513566extern " C"
0 commit comments