libcvd-members
[Top][All Lists]
Advanced

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

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


From: Edward Rosten
Subject: [libcvd-members] libcvd cvd/image_io.h cvd/internal/io/png.h cvd...
Date: Tue, 05 Aug 2008 23:03:48 +0000

CVSROOT:        /cvsroot/libcvd
Module name:    libcvd
Changes by:     Edward Rosten <edrosten>        08/08/05 23:03:47

Modified files:
        cvd            : image_io.h 
        cvd/internal/io: png.h tiff.h 
        pnm_src        : png.cc 
        test           : test_images.cxx 

Log message:
        Convert PNG writing to the new system.
        
        Enable bools for TIFF writing.
        
        Expand test image to larger size.
        
        All write,read tests passed.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/libcvd/cvd/image_io.h?cvsroot=libcvd&r1=1.35&r2=1.36
http://cvs.savannah.gnu.org/viewcvs/libcvd/cvd/internal/io/png.h?cvsroot=libcvd&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/libcvd/cvd/internal/io/tiff.h?cvsroot=libcvd&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/libcvd/pnm_src/png.cc?cvsroot=libcvd&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/libcvd/test/test_images.cxx?cvsroot=libcvd&r1=1.12&r2=1.13

Patches:
Index: cvd/image_io.h
===================================================================
RCS file: /cvsroot/libcvd/libcvd/cvd/image_io.h,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -b -r1.35 -r1.36
--- cvd/image_io.h      5 Aug 2008 02:12:45 -0000       1.35
+++ cvd/image_io.h      5 Aug 2008 23:03:47 -0000       1.36
@@ -280,7 +280,7 @@
                  case ImageType::JPEG: JPEG::writeJPEG(im,o); break;
          #endif
          #ifdef CVD_HAVE_PNG
-                 case ImageType::PNG: PNG::writePNG(im,o); break;
+                 case ImageType::PNG: Internal::writeImage<PixelType, 
PNG::png_writer>(im,o); break;
          #endif
          #ifdef CVD_HAVE_TIFF
                  case ImageType::TIFF: Internal::writeImage<PixelType, 
TIFF::tiff_writer>(im,o); break;

Index: cvd/internal/io/png.h
===================================================================
RCS file: /cvsroot/libcvd/libcvd/cvd/internal/io/png.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- cvd/internal/io/png.h       5 Aug 2008 22:14:22 -0000       1.7
+++ cvd/internal/io/png.h       5 Aug 2008 23:03:47 -0000       1.8
@@ -101,193 +101,85 @@
 // How to convert Misc types in to PNG compatible types
 //
 
+//The range is encoded un unary notation. The range is on some integer, x.
+//g1 is set if x > 1. g8 is set if x > 8 and so on.
+//This allows us to choose a type with a reasonable number of bits.
+template<int g1, int g8> struct IntMapper    { typedef unsigned short type;};
+template<>               struct IntMapper<1, 0> { typedef unsigned char type; 
};
+template<>               struct IntMapper<0, 0> { typedef bool type; };
 
-template<class C, class D> void make_row_pointers(const SubImage<C>& im, 
std::vector<const D*>& rows)
-{
-       rows.resize(im.size().y);
-       for(int r=0; r < im.size().y; r++)
-               rows[r] = (const D*)im[r];
-}
 
-struct png_out
+//Mapping for integral types
+template<class ComponentIn, int is_integral> struct ComponentMapper_
 {
-       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*>&);
-
-       void read_end();
-
-       std::string error_string;
-
-       std::ostream& o;
-
-       png_struct_def* png_ptr;
-       png_info_struct* info_ptr, *end_info;
+       typedef typename IntMapper<
+                                                               
(Pixel::traits<ComponentIn>::bits_used > 1),
+                                                               
(Pixel::traits<ComponentIn>::bits_used > 8)
+                                                               >::type type;
 };
 
-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;};
-template<> struct PNGType<3,0>{ typedef Rgb<byte> type; static const 
png_out::colour_type Colour = png_out::Rgb; static const int Depth=8;};
-template<> struct PNGType<3,1>{ typedef Rgb<unsigned short> type; static const 
png_out::colour_type Colour = png_out::Rgb; static const int Depth=16;};
-template<> struct PNGType<4,0>{ typedef Rgba<byte> type; static const 
png_out::colour_type Colour = png_out::RgbAlpha; static const int Depth=8;};
-template<> struct PNGType<4,1>{ typedef Rgba<unsigned short> type; static 
const png_out::colour_type Colour = png_out::RgbAlpha; static const int 
Depth=16;};
 
+//Mapping for non integral types
+template<class ComponentIn> struct ComponentMapper_<ComponentIn, 0> { typedef 
unsigned short type; };
 
-template<class T> struct PNGWriter
+template<class ComponentIn> struct ComponentMapper
 {
-       static void write(const SubImage<T>& i, std::ostream& o)
-       {
-               typedef PNGType<Pixel::Component<T>::count, 
Internal::save_default<T>::use_16bit> PNGInfo;
-
-               typedef typename PNGInfo::type Out;
-               typedef typename Pixel::Component<Out>::type Comp;
-               
-               png_out po(i.size().x, i.size().y, 
(png_out::colour_type)PNGInfo::Colour, PNGInfo::Depth, o);
-               std::vector<Out> row_buf(i.size().x);
-               std::vector<const Comp*> rows;
-               rows.push_back(reinterpret_cast<const Comp*>(&row_buf[0]));
-
-
-               
-               for(int r=0; r < i.size().y ; r++)
-               {
-                       Pixel::ConvertPixels<T,Out>::convert(i[r], &row_buf[0], 
i.size().x);
-                       po.write_raw_pixel_lines(rows);
-               }
-       }
+       typedef typename ComponentMapper_<ComponentIn, 
Pixel::traits<ComponentIn>::integral>::type type;
 };
 
-template<class T> void writePNG(const SubImage<T>& i, std::ostream& o)
-{
-       PNGWriter<T>::write(i, o);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Types which require no conversions
-//
 
-template<> struct PNGWriter<bool>
+//Mapping for Rgbish types
+template<class ComponentIn> struct ComponentMapper<Rgb<ComponentIn> >
 {
-       static void write(const SubImage<bool>& i, std::ostream& o)
-       {
-               png_out po(i.size().x, i.size().y, png_out::Grey, 1, o);
-               po.pack();
-               std::vector<const byte*> rows;
-               make_row_pointers(i, rows);
-               po.write_raw_pixel_lines(rows);
-       }
+       typedef Rgb<typename ComponentMapper_<ComponentIn, 
Pixel::traits<ComponentIn>::integral>::type> type;
 };
 
-template<> struct PNGWriter<byte>
+template<class ComponentIn> struct ComponentMapper<Rgba<ComponentIn> >
 {
-       static void write(const SubImage<byte>& i, std::ostream& o)
-       {
-               png_out po(i.size().x, i.size().y, png_out::Grey, 8, o);
-               std::vector<const byte*> rows;
-               make_row_pointers(i, rows);
-               po.write_raw_pixel_lines(rows);
-       }
+       typedef Rgba<typename ComponentMapper_<ComponentIn, 
Pixel::traits<ComponentIn>::integral>::type> type;
 };
 
-template<> struct PNGWriter<unsigned short>
+template<> struct ComponentMapper<Rgb8>
 {
-       static void write(const SubImage<unsigned short>& i, std::ostream& o)
-       {
-               png_out po(i.size().x, i.size().y, png_out::Grey, 16, o);
-               std::vector<const unsigned short*> rows;
-               make_row_pointers(i, rows);
-               po.write_raw_pixel_lines(rows);
-       }
+       typedef Rgb8 type;
 };
 
 
-template<> struct PNGWriter<Rgb8>
-{
-       static void write(const SubImage<Rgb8>& i, std::ostream& o)
-       {
-               png_out po(i.size().x, i.size().y, png_out::RgbAlpha, 8, o);
-               po.rgbx();
-               std::vector<const byte*> rows;
-               make_row_pointers(i, rows);
-               po.write_raw_pixel_lines(rows);
-       }
-};
 
 
-template<> struct PNGWriter<Rgb<byte> >
+class png_writer
 {
-       static void write(const SubImage<Rgb<byte> >& i, std::ostream& o)
-       {
-               png_out po(i.size().x, i.size().y, png_out::Rgb, 8, o);
-               std::vector<const byte*> rows;
-               make_row_pointers(i, rows);
-               po.write_raw_pixel_lines(rows);
-       }
-};
+       public:
+               png_writer(std::ostream&, ImageRef size, const std::string& 
type);
+               ~png_writer();
 
-template<> struct PNGWriter<Rgb<unsigned short> >
-{
-       static void write(const SubImage<Rgb<unsigned short> >& i, 
std::ostream& o)
-       {
-               png_out po(i.size().x, i.size().y, png_out::Rgb, 16, o);
-               std::vector<const byte*> rows;
-               make_row_pointers(i, rows);
-               po.write_raw_pixel_lines(rows);
-       }
-};
-
-template<> struct PNGWriter<Rgba<byte> >
-{
-       static void write(const SubImage<Rgba<byte> >& i, std::ostream& o)
-       {
-               png_out po(i.size().x, i.size().y, png_out::RgbAlpha, 8, o);
-               std::vector<const byte*> rows;
-               make_row_pointers(i, rows);
-               po.write_raw_pixel_lines(rows);
-       }
-};
+               void write_raw_pixel_line(const bool*);
+               void write_raw_pixel_line(const unsigned char*);
+               void write_raw_pixel_line(const unsigned short*);
+               void write_raw_pixel_line(const Rgb<unsigned char>*);
+               void write_raw_pixel_line(const Rgb8*);
+               void write_raw_pixel_line(const Rgb<unsigned short>*);
+               void write_raw_pixel_line(const Rgba<unsigned char>*);
+               void write_raw_pixel_line(const Rgba<unsigned short>*);
 
-template<> struct PNGWriter<Rgba<unsigned short> >
-{
-       static void write(const SubImage<Rgba<unsigned short> >& i, 
std::ostream& o)
+               template<class Incoming> struct Outgoing
        {
-               png_out po(i.size().x, i.size().y, png_out::RgbAlpha, 16, o);
-               std::vector<const byte*> rows;
-               make_row_pointers(i, rows);
-               po.write_raw_pixel_lines(rows);
-       }
-};
-
-
-
-
-
-
-
-
-
-
-
-
+                       typedef typename ComponentMapper<Incoming>::type type;
+               };              
+       private:
 
+               template<class P> void write_line(const P*);
 
+       long row;
+       std::ostream& o;
+       ImageRef size;
+       std::string type;
+       std::string error_string;
 
+       png_struct_def* png_ptr;
+       png_info_struct* info_ptr, *end_info;
 
+};
 
 
 }}

Index: cvd/internal/io/tiff.h
===================================================================
RCS file: /cvsroot/libcvd/libcvd/cvd/internal/io/tiff.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- cvd/internal/io/tiff.h      5 Aug 2008 22:14:22 -0000       1.9
+++ cvd/internal/io/tiff.h      5 Aug 2008 23:03:47 -0000       1.10
@@ -112,7 +112,7 @@
        //This allows us to choose a type with a reasonable number of bits.
        template<int g1, int g8> struct IntMapper    { typedef unsigned short 
type;};
        template<>               struct IntMapper<1, 0> { typedef unsigned char 
type; };
-       template<>               struct IntMapper<0, 0> { typedef unsigned char 
type; };
+       template<>               struct IntMapper<0, 0> { typedef bool type; };
 
 
        //Mapping for integral types

Index: pnm_src/png.cc
===================================================================
RCS file: /cvsroot/libcvd/libcvd/pnm_src/png.cc,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- pnm_src/png.cc      5 Aug 2008 22:12:05 -0000       1.7
+++ pnm_src/png.cc      5 Aug 2008 23:03:47 -0000       1.8
@@ -213,8 +213,8 @@
 // PNG writing functions.
 //
 
-png_out::png_out(int w, int h, colour_type t, int depth, std::ostream& out)
-:o(out)
+png_writer::png_writer(ostream& out, ImageRef sz, const string& type_)
+:row(0),o(out),size(sz),type(type_)
 {
        //Create required structs
        png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, &error_string, 
error_fn, warn_fn);
@@ -238,68 +238,110 @@
        //Set up stream IO
        png_set_write_fn(png_ptr, &o, write_fn, flush_fn);
 
-       int c_type;
-       switch(t)
+       int c_type=0;
+       int depth=0;
+
+       if(type == "bool")
+       {
+               c_type = PNG_COLOR_TYPE_GRAY;
+               depth=1;
+       }
+       else if(type == "unsigned char")
+       {
+               c_type = PNG_COLOR_TYPE_GRAY;
+               depth=8;
+       }
+       else if(type == "unsigned short")
+       {
+               c_type = PNG_COLOR_TYPE_GRAY;
+               depth=16;
+       }
+       else if(type == "CVD::Rgb<unsigned char>")
+       {
+               c_type = PNG_COLOR_TYPE_RGB;
+               depth=8;
+       }
+       else if(type == "CVD::Rgb8")
        {
-               case Grey: c_type = PNG_COLOR_TYPE_GRAY; break;
-               case GreyAlpha: c_type = PNG_COLOR_TYPE_GRAY_ALPHA; break;
-               case Rgb: c_type = PNG_COLOR_TYPE_RGB; break;
-               case RgbAlpha: c_type = PNG_COLOR_TYPE_RGB_ALPHA; break;
-               default:
-                       throw Exceptions::Image_IO::MalformedImage("unknown 
pixel format");
+               c_type = PNG_COLOR_TYPE_RGB;
+               depth=8;
+               //Note the existence of meaningless filler.
+               png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
+       }
+       else if(type == "CVD::Rgb<unsigned short>")
+       {
+               c_type = PNG_COLOR_TYPE_RGB;
+               depth=16;
+       }
+       else if(type == "CVD::Rgba<unsigned char>")
+       {
+               c_type = PNG_COLOR_TYPE_RGB_ALPHA;
+               depth = 8;
        }
+       else if(type == "CVD::Rgba<unsigned short>")
+       {
+               c_type = PNG_COLOR_TYPE_RGB_ALPHA;
+               depth = 16;
+       }
+       else
+               throw UnsupportedImageSubType("TIFF", type);
 
 
        //Set up the image type
-       png_set_IHDR(png_ptr, info_ptr, w, h, depth, c_type, 
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+       png_set_IHDR(png_ptr, info_ptr, size.x, size.y, depth, c_type, 
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
 
        //Write the header 
        png_write_info(png_ptr, info_ptr);
        
        //Write the transformations
        #ifdef CVD_ARCH_LITTLE_ENDIAN
-               if (depth > 8)
+               if (depth == 16)
                        png_set_swap(png_ptr);
        #endif
 
-}
-
-void png_out::pack()
-{
+       //Pack from C++ bools to packed PNG bools
+       //This has to be done _after_ writing the info struct.
+       if(type == "bool")
        png_set_packing(png_ptr);
-}
 
-void png_out::rgbx()
-{
-       png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
 }
 
-void png_out::write_raw_pixel_lines(const std::vector<const unsigned char*>& p)
-{
-       //Set up error handling
-       if(setjmp(png_jmpbuf(png_ptr)))     
-       {         
-               png_destroy_write_struct(&png_ptr, &info_ptr);
-               throw Exceptions::Image_IO::MalformedImage(error_string);
-       }
+//Mechanically generate the pixel writing calls.
+#undef GEN1
+#undef GEN3
+#define GEN1(X) void png_writer::write_raw_pixel_line(const 
X*d){write_line(d);}
+#define GEN3(X) GEN1(X) GEN1(Rgb<X>) GEN1(Rgba<X>)
+GEN1(bool)
+GEN1(Rgb8)
+GEN3(unsigned char)
+GEN3(unsigned short)
+
+
+template<class P> void png_writer::write_line(const P* data)
+{
+       unsigned char* chardata = const_cast<unsigned 
char*>(reinterpret_cast<const unsigned char*>(data));
+
+       //Do some type checking
+       if(type != PNM::type_name<P>::name())
+               throw WriteTypeMismatch(type, PNM::type_name<P>::name());
 
-       png_write_rows(png_ptr, const_cast<unsigned char**>(&p[0]), p.size());
-}
 
-void png_out::write_raw_pixel_lines(const std::vector<const unsigned short*>& 
p)
-{
        //Set up error handling
        if(setjmp(png_jmpbuf(png_ptr)))     
-       {         
-               png_destroy_write_struct(&png_ptr, &info_ptr);
                throw Exceptions::Image_IO::MalformedImage(error_string);
-       }
 
-       png_write_rows(png_ptr, reinterpret_cast<unsigned 
char**>(const_cast<unsigned short**>(&p[0])), p.size());
+       //Do some sanity checking
+       if(row > size.y)
+               throw InternalLibraryError("CVD", "Write past end of image.");
+
+
+       unsigned char** row_ptr =  & chardata;
+       png_write_rows(png_ptr, row_ptr, 1);
 
+       row++;
 }
 
-png_out::~png_out()
+png_writer::~png_writer()
 {
        png_write_end(png_ptr, info_ptr);
        png_destroy_write_struct(&png_ptr, &info_ptr);

Index: test/test_images.cxx
===================================================================
RCS file: /cvsroot/libcvd/libcvd/test/test_images.cxx,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -b -r1.12 -r1.13
--- test/test_images.cxx        5 Aug 2008 19:35:49 -0000       1.12
+++ test/test_images.cxx        5 Aug 2008 23:03:47 -0000       1.13
@@ -164,7 +164,7 @@
        {       
                try{
                        //Make a random image
-                       Image<Type> in(ImageRef(2,2)), out;
+                       Image<Type> in(ImageRef(100,100)), out;
 
                        for(int y=0; y < in.size().y; y++)
                                for(int x=0; x < in.size().x; x++)
@@ -194,12 +194,12 @@
                                        for(int x=0; x < in.size().x; x++)
                                                for(unsigned int c=0; c < 
Pixel::Component<Type>::count; c++)
                                                {
-                                                       Ct p = 
Pixel::Component<Type>::get(in[y][x], c);
-                                                       Ct p2 = 
Pixel::Component<Type>::get(out[y][x], c);
-                                                       t += abs((double)p -  
(double)p2);
+                                                       double p = 
Pixel::Component<Type>::get(in[y][x], c);
+                                                       double p2 = 
Pixel::Component<Type>::get(out[y][x], c);
+                                                       t += abs(p -  p2);
 
-                                                       maxval = max(maxval, 
(double)p);
-                                                       minval = min(minval, 
(double)p);
+                                                       maxval = max(maxval, p);
+                                                       minval = min(minval, p);
 
                                                        cerr << p << " " << p2 
<< endl;
 




reply via email to

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