1- #include < iostream>
1+ #include < iostream>
22#include < fstream>
33#include < cmath>
44#include < cstdio>
@@ -613,12 +613,12 @@ _image_module::from_images(const Py::Tuple& args) {
613613
614614
615615
616- char _image_module_frompng__doc__ [] =
617- " frompng (fname)\n "
616+ char _image_module_readpng__doc__ [] =
617+ " readpng (fname)\n "
618618" \n "
619- " Load the image from png file fname " ;
619+ " Load an image from png file into a numerix array of MxNx4 uint8 " ;
620620Py::Object
621- _image_module::frompng (const Py::Tuple& args) {
621+ _image_module::readpng (const Py::Tuple& args) {
622622
623623 args.verify_length (1 );
624624 std::string fname = Py::String (args[0 ]);
@@ -627,25 +627,25 @@ _image_module::frompng(const Py::Tuple& args) {
627627
628628 FILE *fp = fopen (fname.c_str (), " rb" );
629629 if (!fp)
630- throw Py::RuntimeError (" _image_module::frompng could not open PNG file for reading" );
630+ throw Py::RuntimeError (" _image_module::readpng could not open PNG file for reading" );
631631
632632 fread (header, 1 , 8 , fp);
633633 if (png_sig_cmp (header, 0 , 8 ))
634- throw Py::RuntimeError (" _image_module::frompng : file not recognized as a PNG file" );
634+ throw Py::RuntimeError (" _image_module::readpng : file not recognized as a PNG file" );
635635
636636
637637 /* initialize stuff */
638638 png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL , NULL , NULL );
639639
640640 if (!png_ptr)
641- throw Py::RuntimeError (" _image_module::frompng : png_create_read_struct failed" );
641+ throw Py::RuntimeError (" _image_module::readpng : png_create_read_struct failed" );
642642
643643 png_infop info_ptr = png_create_info_struct (png_ptr);
644644 if (!info_ptr)
645- throw Py::RuntimeError (" _image_module::frompng : png_create_info_struct failed" );
645+ throw Py::RuntimeError (" _image_module::readpng : png_create_info_struct failed" );
646646
647647 if (setjmp (png_jmpbuf (png_ptr)))
648- throw Py::RuntimeError (" _image_module::frompng : error during init_io" );
648+ throw Py::RuntimeError (" _image_module::readpng : error during init_io" );
649649
650650 png_init_io (png_ptr, fp);
651651 png_set_sig_bytes (png_ptr, 8 );
@@ -654,41 +654,70 @@ _image_module::frompng(const Py::Tuple& args) {
654654
655655 png_uint_32 width = info_ptr->width ;
656656 png_uint_32 height = info_ptr->height ;
657- // int color_type = info_ptr->color_type;
658- // int bit_depth = info_ptr->bit_depth;
659- // int number_of_passes = png_set_interlace_handling(png_ptr);
657+
658+ // convert misc color types to rgb for simplicity
659+ if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY ||
660+ info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
661+ png_set_gray_to_rgb (png_ptr);
662+ else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
663+ png_set_palette_to_rgb (png_ptr);
664+
665+
666+ int bit_depth = info_ptr->bit_depth ;
667+ if (bit_depth == 16 ) png_set_strip_16 (png_ptr);
668+
669+
670+ png_set_interlace_handling (png_ptr);
660671 png_read_update_info (png_ptr, info_ptr);
661672
673+ bool rgba = info_ptr->color_type == PNG_COLOR_TYPE_RGBA;
674+ if ( (info_ptr->color_type != PNG_COLOR_TYPE_RGB) || rgba) {
675+ std::cerr << " Found color type " << (int )info_ptr->color_type << std::endl;
676+ throw Py::RuntimeError (" _image_module::readpng: cannot handle color_type" );
677+ }
662678
663679 /* read file */
664680 if (setjmp (png_jmpbuf (png_ptr)))
665- throw Py::RuntimeError (" _image_module::frompng : error during read_image" );
681+ throw Py::RuntimeError (" _image_module::readpng : error during read_image" );
666682
667- png_bytep* row_pointers = new png_bytep[height];
668- if (row_pointers ==NULL ) // todo: also handle allocation throw
669- throw Py::MemoryError (" _image_module::frompng: could not allocate memory" );
683+ png_bytep row_pointers[height];
670684
671- for (png_uint_32 y= 0 ; y< height; y ++)
672- row_pointers[y ] = new png_byte[info_ptr-> rowbytes ]; // todo: delete?
685+ for (png_uint_32 row = 0 ; row < height; row ++)
686+ row_pointers[row ] = new png_byte[png_get_rowbytes (png_ptr, info_ptr)];
673687
674688 png_read_image (png_ptr, row_pointers);
675689
676690
677- Image* imo = new Image;
678- imo-> rowsIn = height ;
679- imo-> colsIn = width;
680-
681- size_t NUMBYTES (imo-> colsIn * imo-> rowsIn * imo-> BPP ) ;
691+
692+ int dimensions[ 3 ] ;
693+ dimensions[ 0 ] = height; // numrows
694+ dimensions[ 1 ] = width; // numcols
695+ dimensions[ 2 ] = 4 ;
682696
683- imo-> bufferIn = new agg::int8u[NUMBYTES]; // todo: copy row_pointers in
697+ PyArrayObject *A = (PyArrayObject *) PyArray_FromDims ( 3 , dimensions, PyArray_FLOAT);
684698
685- for (png_uint_32 row = 0 ; row < imo->rowsIn ; ++row) {
686- imo->bufferIn = row_pointers[row];
699+
700+ for (png_uint_32 y = 0 ; y < height; y++) {
701+ png_byte* row = row_pointers[y];
702+ for (png_uint_32 x = 0 ; x < width; x++) {
703+
704+ png_byte* ptr = (rgba) ? &(row[x*4 ]) : &(row[x*3 ]);
705+ size_t offset = y*A->strides [0 ] + x*A->strides [1 ];
706+ // if ((y<10)&&(x==10)) std::cout << "r = " << ptr[0] << " " << ptr[0]/255.0 << std::endl;
707+ *(float *)(A->data + offset + 0 *A->strides [2 ]) = ptr[0 ]/255.0 ;
708+ *(float *)(A->data + offset + 1 *A->strides [2 ]) = ptr[1 ]/255.0 ;
709+ *(float *)(A->data + offset + 2 *A->strides [2 ]) = ptr[2 ]/255.0 ;
710+ *(float *)(A->data + offset + 3 *A->strides [2 ]) = rgba ? ptr[3 ]/255.0 : 1.0 ;
711+ }
687712 }
688-
689- imo->rbufIn = new agg::rendering_buffer;
690- imo->rbufIn ->attach (imo->bufferIn , imo->colsIn , imo->rowsIn , imo->colsIn *imo->BPP );
691- return Py::asObject ( imo );
713+
714+ // free the png memory
715+ png_read_end (png_ptr, info_ptr);
716+ png_destroy_read_struct (&png_ptr, &info_ptr, png_infopp_NULL);
717+ fclose (fp);
718+ for (png_uint_32 row = 0 ; row < height; row++)
719+ delete [] row_pointers[row];
720+ return Py::asObject ((PyObject*)A);
692721}
693722
694723
0 commit comments