libcvd-members
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[libcvd-members] libcvd cvd/internal/io/png.h pnm_src/png.cc


From: Edward Rosten
Subject: [libcvd-members] libcvd cvd/internal/io/png.h pnm_src/png.cc
Date: Tue, 05 Aug 2008 22:12:06 +0000

CVSROOT:        /cvsroot/libcvd
Module name:    libcvd
Changes by:     Edward Rosten <edrosten>        08/08/05 22:12:05

Modified files:
        cvd/internal/io: png.h 
        pnm_src        : png.cc 

Log message:
        Convert PNG reading to use the new mechanism

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/libcvd/cvd/internal/io/png.h?cvsroot=libcvd&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/libcvd/pnm_src/png.cc?cvsroot=libcvd&r1=1.6&r2=1.7

Patches:
Index: cvd/internal/io/png.h
===================================================================
RCS file: /cvsroot/libcvd/libcvd/cvd/internal/io/png.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- cvd/internal/io/png.h       13 May 2008 12:44:26 -0000      1.5
+++ cvd/internal/io/png.h       5 Aug 2008 22:12:05 -0000       1.6
@@ -35,83 +35,73 @@
 namespace CVD{
 namespace PNG{
 
+using CVD::Internal::TypeList;
+using CVD::Internal::Head;
 
-struct png_in
+
+
+class png_reader
 {
-       enum
-       {
-               Grey,
-               GreyAlpha,
-               Rgb,
-               RgbAlpha
-       }colour_type;
+       public:
+               png_reader(std::istream&);
+               ~png_reader();
 
-       png_in(std::istream&);
-       ~png_in();
+               ImageRef size();
 
-       void expand_depth_to_8();
-       void unpack_to_bytes();
+               void get_raw_pixel_line(bool*);
+               void get_raw_pixel_line(unsigned char*);
+               void get_raw_pixel_line(unsigned short*);
+               void get_raw_pixel_line(Rgb<unsigned char>*);
+               void get_raw_pixel_line(Rgb<unsigned short>*);
+               void get_raw_pixel_line(Rgba<unsigned char>*);
+               void get_raw_pixel_line(Rgba<unsigned short>*);
 
-       void get_raw_pixel_lines(unsigned char**, int);
-       void get_raw_pixel_lines(unsigned short**, int);
+               std::string datatype();
+               std::string name();
 
-       void read_end();
+               typedef TypeList<bool,
+                               TypeList<byte,
+                       TypeList<unsigned short,
+                       TypeList<Rgb<byte>,
+                       TypeList<Rgb<unsigned short>,
+                       TypeList<Rgba<byte>,
+                       TypeList<Rgba<unsigned short>,
+                                                             Head> > > > > > > 
Types;
 
-       int depth;
-       int width, height;
-       std::string error_string;
+       private:
 
        std::istream& i;
-
+               std::string type;
+               unsigned long row;
        png_struct_def* png_ptr;
        png_info_struct* info_ptr, *end_info;
 
+               std::string error_string;
+               ImageRef my_size;
+
+               template<class C> void read_pixels(C*);
 
 };
 
-struct png_out
+template <class T> void readPNG(BasicImage<T>& im, std::istream& in)
 {
-       typedef enum
-       {
-               Grey,
-               GreyAlpha,
-               Rgb,
-               RgbAlpha
-       }colour_type;
-
-       png_out(int w, int h, colour_type t, int depth, std::ostream&);
-       ~png_out();
-
-       void pack();
-       void rgbx();
-
-       void write_raw_pixel_lines(const std::vector<const unsigned char*>&);
-       void write_raw_pixel_lines(const std::vector<const unsigned short*>&);
+       CVD::Internal::readImage<T, png_reader>(im, in);
+}
 
-       void read_end();
+template <class T> void readPNG(Image<T>& im, std::istream& in)
+{
+       CVD::Internal::readImage<T, png_reader>(im, in);
+}
 
-       std::string error_string;
 
-       std::ostream& o;
 
-       png_struct_def* png_ptr;
-       png_info_struct* info_ptr, *end_info;
-};
 
 
////////////////////////////////////////////////////////////////////////////////
 //
-// Utility
+// How to convert Misc types in to PNG compatible types
 //
 
 
-template<class C, class D> void make_row_pointers(SubImage<C>& im, 
std::vector<D*>& rows)
-{
-       rows.resize(im.size().y);
-       for(int r=0; r < im.size().y; r++)
-               rows[r] = (D*)im[r];
-}
-
-
 template<class C, class D> void make_row_pointers(const SubImage<C>& im, 
std::vector<const D*>& rows)
 {
        rows.resize(im.size().y);
@@ -119,227 +109,35 @@
                rows[r] = (const D*)im[r];
 }
 
-////////////////////////////////////////////////////////////////////////////////
-//
-// Read Greyscale PNG
-//
-template<class Dest, class Src_ish> struct readPNG_grey
-{
-       static void read(SubImage<Dest>& im, png_in& png)
-       {
-               if(png.depth < 8)
-                       png.expand_depth_to_8();
-
-               std::vector<Src_ish> row_buf(png.width);
-               Src_ish *row = &row_buf[0];
-
-               for(int r=0; r < png.height; r++)
-               {
-                       png.get_raw_pixel_lines(&row, 1);
-                       Pixel::ConvertPixels<Src_ish, Dest>::convert(row, 
im[r], png.width);
-               }
-       }
-};
-
-template<class Dest> struct readPNG_grey<Dest, bool>
-{
-       static void read(SubImage<Dest>& im, png_in& png)
-       {
-               readPNG_grey<Dest, byte>::read(im, png);
-       }
-};
-
-template<> struct readPNG_grey<bool, bool>
-{
-       static void read(SubImage<bool>& im, png_in& png)
-       {
-               png.unpack_to_bytes();
-               std::vector<byte*> rows;
-               make_row_pointers(im, rows);
-               png.get_raw_pixel_lines(&rows[0], png.height);
-       }
-};
-
-template<> struct readPNG_grey<byte, unsigned char>
-{
-       static void read(SubImage<byte>& im, png_in& png)
-       {
-               if(png.depth < 8)
-                       png.expand_depth_to_8();
-
-               std::vector<byte*> rows;
-               make_row_pointers(im, rows);
-
-               png.get_raw_pixel_lines(&rows[0], png.height);
-       }
-};
-
-
-template<> struct readPNG_grey<unsigned short, unsigned short>
-{
-       static void read(SubImage<unsigned short>& im, png_in& png)
-       {
-               std::vector<unsigned short*> rows;
-               make_row_pointers(im, rows);
-               png.get_raw_pixel_lines(&rows[0], png.height);
-       }
-};
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Read RGB PNG
-//
-
-template<class Dest, class Src> struct readPNG_rgb
+struct png_out
 {
-       static void read(SubImage<Dest>& im, png_in& png)
-       {
-               std::vector<Src> row_buf(png.width*3);
-               Src* row = &row_buf[0];
-
-               for(int r=0; r < png.height; r++)
+       typedef enum
                {
-                       png.get_raw_pixel_lines(&row, 1);
-                       Pixel::ConvertPixels<Rgb<Src>, Dest 
>::convert(reinterpret_cast<Rgb<Src>*>(row), im[r], png.width);
-               }
-       }
-};
+               Grey,
+               GreyAlpha,
+               Rgb,
+               RgbAlpha
+       }colour_type;
 
-template<> struct readPNG_rgb<Rgb<byte>, byte>
-{
-       static void read(SubImage<Rgb<byte> >& im, png_in& png)
-       {
-               std::vector<byte*> rows;
-               make_row_pointers(im, rows);
-               png.get_raw_pixel_lines(&rows[0]  , png.height);
-       }
-};
+       png_out(int w, int h, colour_type t, int depth, std::ostream&);
+       ~png_out();
 
-template<> struct readPNG_rgb<Rgb<unsigned short>, unsigned short>
-{
-       static void read(SubImage<Rgb<unsigned short> >& im, png_in& png)
-       {
-               std::vector<unsigned short*> rows;
-               make_row_pointers(im, rows);
-               png.get_raw_pixel_lines(&rows[0], png.height);
-       }
-};
+       void pack();
+       void rgbx();
 
-////////////////////////////////////////////////////////////////////////////////
-//
-// Read RGBA PNG
-//
+       void write_raw_pixel_lines(const std::vector<const unsigned char*>&);
+       void write_raw_pixel_lines(const std::vector<const unsigned short*>&);
 
-template<class Dest, class Src> struct readPNG_rgba
-{
-       static void read(SubImage<Dest>& im, png_in& png)
-       {
-               std::vector<Src> row_buf(png.width*4);
-               Src* row = &row_buf[0];
+       void read_end();
 
-               for(int r=0; r < png.height; r++)
-               {
-                       png.get_raw_pixel_lines(&row, 1);
-                       Pixel::ConvertPixels<Rgba<Src>, Dest 
>::convert(reinterpret_cast<Rgba<Src>*>(row), im[r], png.width);
-               }
-       }
-};
+       std::string error_string;
 
-template<> struct readPNG_rgb<Rgba<byte>, byte>
-{
-       static void read(SubImage<Rgba<byte> >& im, png_in& png)
-       {
-               std::vector<byte*> rows;
-               make_row_pointers(im, rows);
-               png.get_raw_pixel_lines(&rows[0]  , png.height);
-       }
-};
+       std::ostream& o;
 
-template<> struct readPNG_rgb<Rgba<unsigned short>, unsigned short>
-{
-       static void read(SubImage<Rgba<unsigned short> >& im, png_in& png)
-       {
-               std::vector<unsigned short*> rows;
-               make_row_pointers(im, rows);
-               png.get_raw_pixel_lines(&rows[0], png.height);
-       }
+       png_struct_def* png_ptr;
+       png_info_struct* info_ptr, *end_info;
 };
 
-////////////////////////////////////////////////////////////////////////////////
-//
-// Runtime switch on type
-//
-
-template<class C> void readPNG(SubImage<C>& im, png_in& png)
-{
-       switch(png.colour_type)
-       {       
-               case png_in::Grey:      
-                               if(png.depth == 16)
-                                       readPNG_grey<C, unsigned 
short>::read(im, png);
-                               else if(png.depth == 1)
-                                       readPNG_grey<C, bool>::read(im, png);
-                               else
-                                       readPNG_grey<C, unsigned 
char>::read(im, png);
-                       break;
-
-               case png_in::GreyAlpha:
-                               throw 
Exceptions::Image_IO::UnsupportedImageSubType("PNG", "Grey-alpha not yet 
supported");
-                       break;
-
-               case png_in::Rgb:
-                               if(png.depth == 16)
-                                       readPNG_rgb<C, unsigned 
short>::read(im, png);
-                               else
-                                       readPNG_rgb<C, unsigned char>::read(im, 
png);
-                       break;
-
-               case png_in::RgbAlpha:
-                               if(png.depth == 16)
-                                       readPNG_rgba<C, unsigned 
short>::read(im, png);
-                               else
-                                       readPNG_rgba<C, unsigned 
char>::read(im, png);
-                       break;
-       }
-       
-       //This clears the stream of PNGs
-       png.read_end();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Adapter for various image manifestations
-//
-
-template <class T> void readPNG(SubImage<T>& im, std::istream& in)
-{
-       png_in png(in);
-       ImageRef size(png.width, png.height);
-       if (im.size() != size)
-               throw Exceptions::Image_IO::ImageSizeMismatch(size, im.size());
-       readPNG(im, png);
-}
-
-template <class T> void readPNG(Image<T>& im, std::istream& in)
-{
-       png_in png(in);
-       ImageRef size(png.width, png.height);
-       im.resize(size);
-       readPNG(im, png);
-}
-
-
-
-
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// How to convert Misc types in to PNG compatible types
-//
-
 template<int Components, bool use_16bit> struct PNGType;
 template<> struct PNGType<1,0>{ typedef byte type; static const 
png_out::colour_type Colour = png_out::Grey; static const int Depth=8;};
 template<> struct PNGType<1,1>{ typedef unsigned short type; static const 
png_out::colour_type Colour = png_out::Grey; static const int Depth=16;};

Index: pnm_src/png.cc
===================================================================
RCS file: /cvsroot/libcvd/libcvd/pnm_src/png.cc,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- pnm_src/png.cc      30 Jul 2008 00:10:01 -0000      1.6
+++ pnm_src/png.cc      5 Aug 2008 22:12:05 -0000       1.7
@@ -5,10 +5,15 @@
 #include <png.h>
 
 using namespace CVD;
+using namespace CVD::Exceptions;
+using namespace CVD::Exceptions::Image_IO;
 using namespace PNG;
 using namespace std;
 
-
+////////////////////////////////////////////////////////////////////////////////
+//
+// C++ istreams based I/O functions
+// 
 static void error_fn(png_structp png_ptr, png_const_charp error_msg)
 {
        *(string*)(png_ptr->error_ptr) = error_msg;
@@ -29,9 +34,6 @@
        //to fail because it has internal checksums
 }
 
-
-
-
 static void write_fn(png_structp png_ptr, unsigned char*  data, size_t 
numbytes)
 {
        ostream* o = (ostream*)png_get_io_ptr(png_ptr);
@@ -44,58 +46,66 @@
        (*o) << flush;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+//
+// PNG reading functions
+// 
 
-
-
-
-void png_in::unpack_to_bytes()
+string png_reader::datatype()
 {
-       //No error checking. Only call for Grey images
-       png_set_packing(png_ptr);
+       return type;
 }
 
-void png_in::expand_depth_to_8()
+string png_reader::name()
 {
-       //No error checking. Only call for Grey images
-       png_set_gray_1_2_4_to_8(png_ptr);
+       return "PNG";
 }
 
-void png_in::get_raw_pixel_lines(unsigned char** row_ptr, int nlines)
+ImageRef png_reader::size()
 {
-       if(depth == 16)
-               throw Exceptions::Image_IO::ReadTypeMismatch(1);
+       return my_size;
+}
 
-       if(setjmp(png_jmpbuf(png_ptr)))     
-               throw Exceptions::Image_IO::MalformedImage(error_string);
 
-       //NB no check for read past end.
-       png_read_rows(png_ptr, row_ptr, NULL, nlines);
-}
+//Mechanically generate the pixel reading calls.
+#define GEN1(X) void png_reader::get_raw_pixel_line(X*d){read_pixels(d);}
+#define GEN3(X) GEN1(X) GEN1(Rgb<X>) GEN1(Rgba<X>)
+GEN1(bool)
+GEN3(unsigned char)
+GEN3(unsigned short)
 
 
-void png_in::get_raw_pixel_lines(unsigned short** row_ptr, int nlines)
+
+template<class P> void png_reader::read_pixels(P* data)
 {
-       if(depth != 16)
-               throw Exceptions::Image_IO::ReadTypeMismatch(0);
+       if(datatype() != PNM::type_name<P>::name())
+               throw ReadTypeMismatch(datatype(), PNM::type_name<P>::name());
+
+       if(row  > (unsigned long)my_size.y)
+               throw InternalLibraryError("CVD", "Read past end of image.");
+
 
        if(setjmp(png_jmpbuf(png_ptr)))     
                throw Exceptions::Image_IO::MalformedImage(error_string);
 
-       //NB no check for read past end.
-       png_read_rows(png_ptr, (unsigned char**)row_ptr, NULL, nlines);
+       unsigned char* cptr = reinterpret_cast<unsigned char*>(data);
+       unsigned char** row_ptr = &cptr;
+
+       png_read_rows(png_ptr, row_ptr, NULL, 1);
 }
 
-png_in::png_in(std::istream& in)
-:i(in)
+
+
+png_reader::png_reader(std::istream& in)
+:i(in),type(""),row(0),png_ptr(0),info_ptr(0),end_info(0)
 {
+       //Read the header and make sure it really is a PNG...
        unsigned char header[8];
 
        in.read((char*)header, 8);
 
        if(png_sig_cmp(header, 0, 8))
-       {
                throw Exceptions::Image_IO::MalformedImage("Not a PNG image");
-       }
 
 
        png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, 
NULL);
@@ -136,23 +146,42 @@
        png_read_info(png_ptr, info_ptr);
 
        png_uint_32 w, h;
-       int colour, interlace, dummy;
+       int colour, interlace, dummy, depth;
 
        png_get_IHDR(png_ptr, info_ptr, &w, &h, &depth, &colour, &interlace, 
&dummy, &dummy);
 
-       width = w;
-       height = h;
+       my_size.x = w;
+       my_size.y = h;
+
+       //Figure out the type name, and what processing to to.
+       if(depth == 1)
+       {       
+               //Unpack bools to bytes to ease loading.
+               png_set_packing(png_ptr);
+               type = PNM::type_name<bool>::name();
+       }
+       else if(depth <= 8)
+       {
+               //Expand nonbool colour depths up to 8bpp
+               if(depth < 8)
+                       png_set_gray_1_2_4_to_8(png_ptr);
+
+               type = PNM::type_name<unsigned char>::name();
+       }
+       else
+               type = PNM::type_name<unsigned short>::name();
+
        
        if(colour & PNG_COLOR_MASK_COLOR)
                if(colour & PNG_COLOR_MASK_ALPHA)
-                       colour_type = RgbAlpha;
+                       type = "CVD::Rgba<" + type + ">";
                else
-                       colour_type = Rgb;
+                       type = "CVD::Rgb<" + type + ">";
        else
                if(colour & PNG_COLOR_MASK_ALPHA)
-                       colour_type = GreyAlpha;
+                       type = "CVD::GreyAlpha<" + type + ">";
                else
-                       colour_type = Grey;
+                       type = type;
        
        //Get rid of palette, by transforming it to RGB
        if(colour == PNG_COLOR_TYPE_PALETTE)
@@ -167,21 +196,22 @@
        #endif
 }
 
-void png_in::read_end()
+png_reader::~png_reader()
 {
+       //Clear the stream of any remaining PNG bits.
        //It doesn't matter if there's an error here
        if(!setjmp(png_jmpbuf(png_ptr)))
                png_read_end(png_ptr, end_info);
-}
 
-png_in::~png_in()
-{
        //Destroy all PNG structs
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
 }
 
 
-
+////////////////////////////////////////////////////////////////////////////////
+//
+// PNG writing functions.
+//
 
 png_out::png_out(int w, int h, colour_type t, int depth, std::ostream& out)
 :o(out)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]