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/pnm_grok....


From: Edward Rosten
Subject: [libcvd-members] libcvd cvd/image_io.h cvd/internal/io/pnm_grok....
Date: Thu, 18 Nov 2010 21:47:54 +0000

CVSROOT:        /cvsroot/libcvd
Module name:    libcvd
Changes by:     Edward Rosten <edrosten>        10/11/18 21:47:54

Modified files:
        cvd            : image_io.h 
        cvd/internal/io: pnm_grok.h 
        pnm_src        : pnm_grok.cxx 
        test           : test_images.cxx 

Log message:
        Move PNMI/O code over to the proper image loading system.
        
        Fix some minor edge case bugs.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/libcvd/cvd/image_io.h?cvsroot=libcvd&r1=1.44&r2=1.45
http://cvs.savannah.gnu.org/viewcvs/libcvd/cvd/internal/io/pnm_grok.h?cvsroot=libcvd&r1=1.10&r2=1.11
http://cvs.savannah.gnu.org/viewcvs/libcvd/pnm_src/pnm_grok.cxx?cvsroot=libcvd&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/libcvd/test/test_images.cxx?cvsroot=libcvd&r1=1.17&r2=1.18

Patches:
Index: cvd/image_io.h
===================================================================
RCS file: /cvsroot/libcvd/libcvd/cvd/image_io.h,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -b -r1.44 -r1.45
--- cvd/image_io.h      30 Mar 2010 15:08:06 -0000      1.44
+++ cvd/image_io.h      18 Nov 2010 21:47:53 -0000      1.45
@@ -234,7 +234,7 @@
            throw Exceptions::Image_IO::EofBeforeImage();
 
          if(c == 'P')
-           PNM::readPNM(im, i);
+           CVD::Internal::readImage<I, PNM::Reader>(im, i);
 #ifdef CVD_HAVE_JPEG
          else if(c == 0xff)
            CVD::Internal::readImage<I, JPEG::reader>(im, i);
@@ -296,7 +296,7 @@
          case ImageType::PNM:  
          case ImageType::Automatic:
          case ImageType::Unknown:
-               Internal::writeImage<PixelType, PNM::pnm_writer>(im, o, p); 
break;
+               Internal::writeImage<PixelType, PNM::Writer>(im, o, p); break;
          #ifdef CVD_HAVE_JPEG
                  case ImageType::JPEG: Internal::writeImage<PixelType, 
JPEG::writer>(im,o, p); break;
          #endif

Index: cvd/internal/io/pnm_grok.h
===================================================================
RCS file: /cvsroot/libcvd/libcvd/cvd/internal/io/pnm_grok.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -b -r1.10 -r1.11
--- cvd/internal/io/pnm_grok.h  21 Mar 2010 19:02:03 -0000      1.10
+++ cvd/internal/io/pnm_grok.h  18 Nov 2010 21:47:53 -0000      1.11
@@ -32,128 +32,43 @@
 {
   namespace PNM
   {
-    class pnm_in
+       class pnm_in;
+
+       using CVD::Internal::TypeList;
+       using CVD::Internal::Head;
+       class Reader
     {
                public:
-                 pnm_in(std::istream&);
-                 bool is_2_byte()const {return m_is_2_byte;}
-                 int channels(){return m_channels;}
-                 long  x_size() const {return xs;}
-                 long  y_size() const {return ys;}
-                 long  elements_per_line() const {return xs * m_channels;}
-                 void get_raw_pixel_lines(unsigned char*, unsigned long 
nlines);
-                 void get_raw_pixel_lines(unsigned short*, unsigned long 
nlines);
-
+                       Reader(std::istream&);
+                       ~Reader();
                                
-               private:
-                 std::istream& i;
-                 bool  is_text;
-                 int   type, maxval;
-                 int   lines_so_far;
-                 void  read_header();
-                 bool  can_proc_lines(unsigned long);
-                 long  xs, ys;
-                 bool  m_is_2_byte;
-                 int   m_channels;
-    };
+                       ImageRef size();
 
-       template <class T, class S, int N> struct PNMReader;
+                       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>*);
+
+                       std::string datatype();
+                       std::string name();
+
+                       typedef TypeList<bool,
+                                       TypeList<byte,
+                                       TypeList<unsigned short,
+                                       TypeList<Rgb<byte>,
+                                       TypeList<Rgb<unsigned short>,
+                                                                               
          Head> > > > > Types;
 
-       template <class T, class S> struct PNMReader<T,S,3> 
-       {
-               typedef Rgb<S> array;
-               static void readPixels(BasicImage<T>& im, pnm_in& pnm) 
-               {
-                       std::vector<array> rowbuf(pnm.x_size());
-                       for (int r=0; r<pnm.y_size(); r++) 
-                       {
-                               pnm.get_raw_pixel_lines((S*) &(rowbuf[0]), 1);
-                               Pixel::ConvertPixels<array, 
T>::convert(&(rowbuf[0]), im[r], pnm.x_size());
-                       }
-               }
-       };
-  
-    template <class T, class S> struct PNMReader<T,S,1> 
-       {
-       static void readPixels(BasicImage<T>& im, pnm_in& pnm) 
-               {
-                       std::vector<S> rowbuf(pnm.x_size());
-                       for (int r=0; r<pnm.y_size(); r++) 
-                       {
-                               pnm.get_raw_pixel_lines(&(rowbuf[0]), 1);
-                               Pixel::ConvertPixels<S, 
T>::convert(&(rowbuf[0]), im[r], pnm.x_size());
-                       }
-       }
-    };
-
-    template <> struct PNMReader<Rgb<byte>,byte,3> 
-       {
-       static void readPixels(BasicImage<Rgb<byte> >& im, pnm_in& pnm) 
-               {
-                       pnm.get_raw_pixel_lines((byte*)im.data(), pnm.y_size());
-       }
-    };
-
-    template <> struct PNMReader<byte,byte,1> 
-       {
-       static void readPixels(BasicImage<byte>& im, pnm_in& pnm) 
-               {
-                       pnm.get_raw_pixel_lines(im.data(), pnm.y_size());
-       }
-    };
-
-    template <> struct PNMReader<Rgb<unsigned short>,unsigned short,3> 
-       {
-       static void readPixels(BasicImage<Rgb<unsigned short> >& im, pnm_in& 
pnm) 
-               {
-                       pnm.get_raw_pixel_lines((unsigned short*)im.data(), 
pnm.y_size());
-       }
-    };
+               private:
+                       std::auto_ptr<pnm_in> p;
 
-    template <> struct PNMReader<unsigned short,unsigned short,1> 
-       {
-       static void readPixels(BasicImage<unsigned short>& im, pnm_in& pnm) 
-               {
-                       pnm.get_raw_pixel_lines(im.data(), pnm.y_size());
-       }
     };
   
-    template <class T> void readPNM(BasicImage<T>& im, pnm_in& pnm)
-    {
-       if (pnm.is_2_byte()) 
-               {
-                       if (pnm.channels() == 3)
-                               PNMReader<T,unsigned short,3>::readPixels(im, 
pnm);
-                       else 
-                               PNMReader<T,unsigned short,1>::readPixels(im, 
pnm);
-               }
-       else 
-               {
-                       if (pnm.channels() == 3)
-                               PNMReader<T,unsigned char,3>::readPixels(im, 
pnm);
-                       else
-                               PNMReader<T,unsigned char,1>::readPixels(im, 
pnm);
-       }
-    }
-       
-       template <class T> void readPNM(BasicImage<T>&im, std::istream& in)
-       {
-      pnm_in pnm(in);
-         ImageRef size(pnm.x_size(), pnm.y_size());
 
-         if(size != im.size())
-           throw Exceptions::Image_IO::ImageSizeMismatch(size, im.size());
        
-               readPNM(im, pnm);
 
-       }
 
-       template <class T> void readPNM(Image<T>&im, std::istream& in)
-       {
-       pnm_in pnm(in);
-       im.resize(ImageRef(pnm.x_size(), pnm.y_size()));
-               readPNM(im, pnm);
-       }
        
////////////////////////////////////////////////////////////////////////////////
        //
        // PNM writing.
@@ -164,11 +79,12 @@
        template<>                      struct ComponentMapper<0,1> { typedef 
byte type; };
        template<>                      struct ComponentMapper<0,0> { typedef 
unsigned short type; };
 
-       class pnm_writer
+       class pnm_writer;
+       class Writer
        {
                public:
-                       pnm_writer(std::ostream&, ImageRef size, const 
std::string& type, const std::map<std::string, Parameter<> >& p);
-                       ~pnm_writer();
+                       Writer(std::ostream&, ImageRef size, const std::string& 
type, const std::map<std::string, Parameter<> >& p);
+                       ~Writer();
 
                        //void write_raw_pixel_line(const bool*);
                        void write_raw_pixel_line(const unsigned char*);
@@ -184,14 +100,7 @@
                                                                                
                 std::numeric_limits<Element>::digits <= 8>::type type;
                        };              
                private:
-
-                       template<class P> void sanity_check(const P*);
-                       void write_shorts(const unsigned short*, int n);
-
-               long row;
-               std::ostream& o;
-               ImageRef size;
-               std::string type;
+                       std::auto_ptr<pnm_writer> p;
        };
 
 

Index: pnm_src/pnm_grok.cxx
===================================================================
RCS file: /cvsroot/libcvd/libcvd/pnm_src/pnm_grok.cxx,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- pnm_src/pnm_grok.cxx        21 Mar 2010 19:02:03 -0000      1.13
+++ pnm_src/pnm_grok.cxx        18 Nov 2010 21:47:54 -0000      1.14
@@ -159,7 +159,28 @@
        }
 
 
-
+               class pnm_in
+               {
+                       public:
+                         pnm_in(std::istream&);
+                         ImageRef size();
+                         string datatype();
+
+                               template<class C>
+                               void get_raw_pixel_lines(C * c, unsigned long 
nlines);
+                                                       
+                       private:
+                         bool m_is_2_byte;
+                         int  m_channels;
+                         string elemtype;
+                         std::istream&         i;
+                         bool          is_text;
+                         int   type, maxval;
+                         int   lines_so_far;
+                         void          read_header();
+                         bool  can_proc_lines(unsigned long);
+                         long          xs, ys;
+               };
 
        bool clean(istream& i)
        {
@@ -310,6 +331,25 @@
                m_is_2_byte = false;
            }
        
+                       if(type == PBM)
+                               elemtype = "bool";
+                       else if(type == PGM)
+                       {
+                               if(m_is_2_byte)
+                                       elemtype = PNM::type_name<unsigned 
short>::name();
+                               else
+                                       elemtype = PNM::type_name<byte>::name();
+                       }
+                       if(type == PPM)
+                       {
+                               if(m_is_2_byte)
+                                       elemtype = PNM::type_name<Rgb<unsigned 
short> >::name();
+                               else
+                                       elemtype = PNM::type_name<Rgb<byte> 
>::name();
+                       }
+                       
+                               
+               
            //Remove everything to the beginning of the image
            if(is_text)
                CLEAN;
@@ -337,146 +377,187 @@
 #undef GET
        }
 
-       void pnm_in::get_raw_pixel_lines(unsigned char* c, unsigned long nlines)
-       {
-           //Reading into uchars is sufficiently different from reading in to
-           //ushorts, so it has ben done as 2 functions as opposed to one 
-           //tmeplated one.
-
-#define RETURN(X) do{                                                  \
-               if(X == E_NONE)                                         \
-                   return;                                             \
-               else                                                    \
-                   throw Exceptions::Image_IO::MalformedImage(name_error(X)); \
-           }while(0)                                                           
        
-
-           unsigned long k, j, npix;
-           unsigned char* cc = c;
-
-           if(!can_proc_lines(nlines))
-               RETURN(E_READ_PAST_END);
-       
-           //Load a bunch of pixels in to memory without doing internal 
buffering
-       
-           npix = xs * nlines;
-
-           if(m_is_2_byte)
-               RETURN(E_NOT_1_BYTE);
-       
-           if(type == PPM)
-               npix *= 3;
        
-           if(is_text)         //Load text PNM data
+               //Text reading functions
+               void get_num(istream& i, byte* c)
            {
-               //Don't report errors. The spec says to be really leniant with
-               //respect to errors in text only pnms
+                       int j=0;
+                       i >> j;  //Ignore EOF: be leniant
+                       *c = j & 0xff;
+               }
 
-               for(k=0; k < npix; k++)
+               void get_num(istream& i, bool* c)
                {
-                   i >> j;     
-
-                   if(i.eof())
-                       j=0;
-
-                   *c++ = j & 0xff;
+                       i >> ws;
+                       int j = cin.get();
+                       //PBMs are inverted
+                       *c = (j != '0');
                }
 
-               if(type == PBM)
-               {
-                   //PBMs are inverted. Also, converto to a sensible maxval
-                   for(k=0; k < npix; k++, cc++)
+               void get_num(istream& i, unsigned short* c)
                    {
-                       if(*cc)
-                           *cc=0;
-                       else
-                           *cc=maxval;
-                   }
+                       int j=0;
+                       i >> j;  //Ignore EOF: be leniant
+                       *c = j & 0xffff;
                }
+
+               template<class C> void get_num(istream& i, Rgb<C>* c)
+               {
+                               get_num(i, & (c->red));
+                               get_num(i, & (c->green));
+                               get_num(i, & (c->blue));
            }
-           else if(type != PBM)
+               
+               //Data reading functions
+               void really_swap(unsigned char* s, size_t n_elem)
            {
-               i.read((char*)c, (int)npix);
+                       #ifdef SWAP_BYTES
+                               for(size_t j=0; j < n_elem; j++)
+                                       swap(s[2*j], s[2*j+1]);
+                       #endif
            }
-           else
-               RETURN(E_PBM_NOT_IMPLEMENTED);
 
-           if(i.eof())
-               RETURN(E_DEOF);
+               void maybe_swap(unsigned short* s, size_t n)
+               {
+                               really_swap((unsigned char*)s, n);
+               }
+               void maybe_swap(Rgb<unsigned short>*s , size_t n)
+               {
+                               really_swap((unsigned char*)s, n*3);
        }
 
+               void maybe_swap(bool*, size_t)
+               {}
+               void maybe_swap(byte*, size_t)
+               {}
+               void maybe_swap(Rgb<byte>*, size_t)
+               {}
 
-       void pnm_in::get_raw_pixel_lines(unsigned short* s, unsigned long 
nlines)
+               template<class C>
+               void pnm_in::get_raw_pixel_lines(C * c, unsigned long nlines)
        {
-           unsigned long k, j, npix;
+                       if(datatype() != PNM::type_name<C>::name())
+                               throw ReadTypeMismatch(datatype(), 
PNM::type_name<C>::name());
        
-           //Load a bunch of pixels in to memory without doing internal 
buffering
+                       //Reading into uchars is sufficiently different from 
reading in to
+                       //ushorts, so it has ben done as 2 functions as opposed 
to one 
+                       //tmeplated one.
        
+                       unsigned long k, npix;
            if(!can_proc_lines(nlines))
-               RETURN(E_READ_PAST_END);
-
-           if(!m_is_2_byte)
-               RETURN(E_NOT_2_BYTE);
+                               throw 
Exceptions::Image_IO::MalformedImage(name_error(E_READ_PAST_END));
 
+                       //Load a bunch of pixels in to memory without doing 
internal buffering
            npix = xs * nlines;
        
-           if(type == PPM)
-               npix *= 3;
-       
            if(is_text)         //Load text PNM data
            {
+                               for(k=0; k < npix; k++)
+                                       get_num(i, c++);
+                       }
+                       else if(type != PBM)
+                       {
+                               if(type == PBM)
+                                       throw 
Exceptions::Image_IO::MalformedImage(name_error(E_PBM_NOT_IMPLEMENTED));
+
+                               i.read((char*)c, m_channels*npix * 
(m_is_2_byte?2:1));
+                               maybe_swap(c, npix);
+                       }
+
                //Don't report errors. The spec says to be really leniant with
                //respect to errors in text only pnms
+                       if(!is_text  && i.fail())
+                               throw 
Exceptions::Image_IO::MalformedImage(name_error(E_DEOF));
 
-               for(k=0; k < npix; k++)
-               {
-                   i >> j;     
-                   if(i.eof())
-                       j=0;
-                   *s++ = j & 0xffff;
                }
+
+               ImageRef pnm_in::size()
+               {
+                       return ImageRef(xs, ys);
            }
-           else
+
+               string pnm_in::datatype()
            {
-#ifndef LONG_PNM_FAST_LOAD
+                       return elemtype;
+               }
 
-               unsigned char i1, i2;
 
-               for(j=0; j < npix; j++)
-               {
-                   i.read((char*)&i1, 1);
-                   i.read((char*)&i2, 1);
 
-                   //Data is big-endian
-                   *s++ = i1 << 8 | i2;
+               
////////////////////////////////////////////////////////////////////////////////
+               //
+               // Implementation of PNM reader class
+               //
 
-                   if(i.eof())
-                       cerr << j << " ";
+               Reader::~Reader()
+               {
                }
-#else
-               i.read((char*)s, npix*2);
                                
-#ifdef SWAP_BYTES
-               unsigned char t;
+               Reader::Reader(istream& i)
+               :p(new pnm_in(i))
+               {
+               }
 
-               for(j=0; j < npix; j++, s++)
+               string Reader::datatype()
                {
-                   t = *(unsigned char*)s;
-                   *(unsigned char*)s = *(1+(unsigned char*)s);
-                   *(1+(unsigned char*)s) = t;
+                       return p->datatype();
                }
-#endif
-#endif
+
+               string Reader::name()
+               {
+                       return "PNM";
            }
 
-           if(i.eof())
-               RETURN(E_DEOF);
+               ImageRef Reader::size()
+               {
+                       return p->size();
        }
+
+
+               //Mechanically generate the pixel reading calls.
+               #define GEN1(X) void 
Reader::get_raw_pixel_line(X*d){p->get_raw_pixel_lines(d, 1);}
+               #define GEN2(X) GEN1(X) GEN1(Rgb<X>)
+               GEN1(bool)
+               GEN2(unsigned char)
+               GEN2(unsigned short)
+
+
+               #undef GEN1
+               #undef GEN3
        
////////////////////////////////////////////////////////////////////////////////
        //
        // Output PNM class definitions
        //
        
////////////////////////////////////////////////////////////////////////////////
 
+               class pnm_writer
+               {
+                       public:
+                               pnm_writer(std::ostream&, ImageRef size, const 
std::string& type, const std::map<std::string, Parameter<> >& p);
+                               ~pnm_writer();
+
+                               //void write_raw_pixel_line(const bool*);
+                               template<class C> void 
write_raw_pixel_line(const C*);
+
+                       private:
+
+                               void write_shorts(const unsigned char* data, 
size_t n_shorts);
+                               void write_binary(const unsigned char* data, 
size_t n);
+                               void write_binary(const unsigned short* data, 
size_t n);
+                               void write_binary(const Rgb<unsigned char>* 
data, size_t n);
+                               void write_binary(const Rgb<unsigned short>* 
data, size_t n);
+
+
+                               template<class P> void sanity_check(const P*);
+
+                       bool text;
+                       long row;
+                       std::ostream& o;
+                       ImageRef size;
+                       std::string type;
+                       vector<unsigned char>  rowbuf;
+               };
+
+
        void writePNMHeader(ostream& out, int channels, ImageRef size, int 
maxval, bool text, const std::string& comments)
        {
            char m[3] = {'P',' ', '\n'};
@@ -505,18 +586,27 @@
            out << size.x << " " << size.y << endl << maxval << endl;
        }
 
-       pnm_writer::pnm_writer(std::ostream& out, ImageRef size_, const 
std::string& type_, const std::map<std::string, Parameter<> >&)
-       :row(0),o(out),size(size_),type(type_)
+               pnm_writer::pnm_writer(std::ostream& out, ImageRef size_, const 
std::string& type_, const std::map<std::string, Parameter<> >& p)
+               :text(0),row(0),o(out),size(size_),type(type_)
+               {
+                       if(p.count("pnm.raw"))
        {
+                               try{
+                                               
text=!(p.find("pnm.raw")->second.get<bool>());
+                               }
+                               catch(std::bad_cast c){
+                                               cerr << "Warning pnm.raw is not 
a bool.\n";
+                               }
+                       }
                
                if(type == "unsigned char")
-                       writePNMHeader(out, 1, size, 255, 0, "");
+                                       writePNMHeader(out, 1, size, 255, text, 
"");
                else if(type == "unsigned short")
-                       writePNMHeader(out, 1, size, 65535, 0, "");
+                                       writePNMHeader(out, 1, size, 65535, 
text, "");
                else if(type == "CVD::Rgb<unsigned char>")
-                       writePNMHeader(out, 3, size, 255, 0, "");
+                                       writePNMHeader(out, 3, size, 255, text, 
"");
                else if(type == "CVD::Rgb<unsigned short>")
-                       writePNMHeader(out, 3, size, 65535, 0, "");
+                                       writePNMHeader(out, 3, size, 65535, 
text, "");
                else
                    throw UnsupportedImageSubType("PNM", type);
        }
@@ -524,73 +614,90 @@
        pnm_writer::~pnm_writer()
        {}
 
-       void pnm_writer::write_shorts(const unsigned short* data, int n)
+               void pnm_writer::write_shorts(const unsigned char* data, size_t 
n_shorts)
        {
-         
                #ifdef CVD_ARCH_LITTLE_ENDIAN
-                       const unsigned char* bdata = (const unsigned char*)data;
-                       for (int i=0; i<n; i++, bdata+=2) 
-                       {
-                               unsigned char lohi[2] = {bdata[1], bdata[0]};
-                               o.write((const char*)lohi,2);
-                       }
+                                       rowbuf.resize(n_shorts*sizeof(short));
+                                       copy(data, data + 
sizeof(short)*n_shorts, rowbuf.begin());
+
+                                       for (size_t i=0; i<rowbuf.size(); i+=2)
+                                               swap(rowbuf[i], rowbuf[i+1]);
+
+                                       o.write((char*)&rowbuf[0], 
rowbuf.size());
+                                       //for (size_t i=0; i<n_shorts; i++)
+                                                       //o << data[2*i+1] << 
data[2*i];
                #else
                        o.write((const char*)data, n*sizeof(unsigned short));
                #endif
        }
 
-       template<class P> void pnm_writer::sanity_check(const P*)
+               void pnm_writer::write_binary(const unsigned char* data, size_t 
n)
        {
-           if(type != PNM::type_name<P>::name())
-                       throw WriteTypeMismatch(type, 
PNM::type_name<P>::name());
-       
-           //Do some sanity checking
-           if(row >= size.y)
-                       throw InternalLibraryError("CVD", "Write past end of 
image.");
-       
-           row++;
+                       o.write(reinterpret_cast<const char*>(data), n);
        }
-
-       void pnm_writer::write_raw_pixel_line(const unsigned char* data)
+               void pnm_writer::write_binary(const unsigned short* data, 
size_t n)
        {
-               sanity_check(data);
-               o.write(reinterpret_cast<const char*>(data), size.x);
+                       write_shorts(reinterpret_cast<const unsigned 
char*>(data), n);
        }
-
-       void pnm_writer::write_raw_pixel_line(const unsigned short* data)
+               void pnm_writer::write_binary(const Rgb<unsigned char>* data, 
size_t n)
        {
-               sanity_check(data);
-               write_shorts(data, size.x);
+                       o.write(reinterpret_cast<const char*>(data), n*3);
        }
-
-       void pnm_writer::write_raw_pixel_line(const Rgb<unsigned char>* data)
+               void pnm_writer::write_binary(const Rgb<unsigned short>* data, 
size_t n)
        {
-               sanity_check(data);
-               o.write(reinterpret_cast<const char*>(data), 3*size.x);
+                       write_shorts(reinterpret_cast<const unsigned 
char*>(data), n*3);
        }
 
-       void pnm_writer::write_raw_pixel_line(const Rgb<unsigned short>* data)
+               template<class C> void write_text(const C* data, size_t n, 
ostream& o)
        {
-               sanity_check(data);
-               write_shorts(reinterpret_cast<const unsigned short*>(data), 
3*size.x);
+                       for(size_t i=0; i < n; i++)
+                               o << (int) data[i] << endl;
        }
 
-
-/*
-       template <class T> void writePNMPixelsText(ostream& out, const T* data, 
size_t count) 
+               template<class C> void write_text(const Rgb<C>* data, size_t n, 
ostream& o)
        {
-           size_t lines = count / 25;
-           size_t k=0;
-           for (size_t i=0; i<lines; i++) {
-               for (size_t j=0; j<25; j++)
-                   out << (int)(data[k++]) << " ";
-               out << endl;
+                       for(size_t i=0; i < n; i++)
+                               o << (int) data[i].red << " " << 
(int)data[i].green << " " << (int)data[i].blue << endl;
            }
-           while (k<count)
-               out << (int)(data[k++]);
-           out << endl;
+
+               template<class C> 
+               void pnm_writer::write_raw_pixel_line(const C* data)
+               {
+                       if(type != PNM::type_name<C>::name())
+                               throw WriteTypeMismatch(type, 
PNM::type_name<C>::name());
+               
+                       //Do some sanity checking
+                       if(row >= size.y)
+                               throw InternalLibraryError("CVD", "Write past 
end of image.");
+               
+                       row++;
+                               
+                       if(text)
+                               write_text(data, size.x, o);
+                       else
+                               write_binary(data, size.x);
        }
-*/
+
+               
////////////////////////////////////////////////////////////////////////////////
+               //
+               // Public interface
+               //
+
+               Writer::Writer(std::ostream& out, ImageRef size_, const 
std::string& type_, const std::map<std::string, Parameter<> >&  p)
+               :p(new pnm_writer(out, size_, type_, p))
+               {}
+
+               Writer::~Writer()
+               {}
+
+               //Mechanically generate the pixel writing calls.
+               #define GEN1(X) void Writer::write_raw_pixel_line(const 
X*d){p->write_raw_pixel_line(d);}
+               #define GEN2(X) GEN1(X) GEN1(Rgb<X>)
+               //GEN1(bool)
+               GEN2(unsigned char)
+               GEN2(unsigned short)
+
+
 
     }
 }

Index: test/test_images.cxx
===================================================================
RCS file: /cvsroot/libcvd/libcvd/test/test_images.cxx,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -b -r1.17 -r1.18
--- test/test_images.cxx        18 Feb 2010 13:30:10 -0000      1.17
+++ test/test_images.cxx        18 Nov 2010 21:47:54 -0000      1.18
@@ -206,17 +206,25 @@
        }
 }
 
+map<string, Parameter<> > empty()
+{
+       map<string, Parameter<> > nothing;
+       return nothing;
+}
+
 template<class T> struct randtest
 {
        typedef typename T::Type Type;
 
-       static void exec(ImageType::ImageType fmt)
+       static void exec(ImageType::ImageType fmt, const map<string, 
Parameter<> >& p = empty())
        {       
-               try{
                        for(int i=0; i < 10; i++)
                        {
+                               try{
                                //Make a random image
-                               Image<Type> in(ImageRef(1000,1000)), out;
+                               Image<Type> in(ImageRef(1000+i,1000+i)), out;
+
+                               cerr << "Testing " << in.size() << " " << fmt 
<< " " << CVD::PNM::type_name<Type>::name() << " ";
 
                                for(int y=0; y < in.size().y; y++)
                                        for(int x=0; x < in.size().x; x++)
@@ -225,7 +233,7 @@
                                stringstream s;
                                
                                //Save the image
-                               img_save(in, s, fmt);
+                               img_save(in, s, fmt, p);
 
                                s.seekg(0, ios_base::beg);
                                s.seekp(0, ios_base::beg);
@@ -235,10 +243,10 @@
 
                                //Compare the results
                                if(out.size() != in.size())
-                                       cerr << "Image R/W test for type " << 
fmt << " " << CVD::PNM::type_name<Type>::name() << " size mismatch.\n";
+                                       cerr << " size mismatch.\n";
                                else if(!equal(in.begin(), in.end(), 
out.begin()))
                                {
-                                       cerr << "Image R/W test for type " << 
fmt << " " << CVD::PNM::type_name<Type>::name() << " data mismatch.\n";
+                                       cerr << " data mismatch.\n";
 
                                        typedef typename 
Pixel::Component<Type>::type  Ct;
                                        double t=0, minval = HUGE_VAL, 
maxval=-HUGE_VAL;
@@ -264,22 +272,23 @@
 
                                }
                                else
-                                       cerr << "Image R/W test for type " << 
fmt << " " << CVD::PNM::type_name<Type>::name() << " OK.\n";
-                       }
+                                       cerr << "OK.\n";
                }
                catch(Exceptions::All w)
                {
                        cerr << w.what << endl;
                }
+               }
 
-               randtest<typename T::Next>::exec(fmt);
+               randtest<typename T::Next>::exec(fmt,p);
        }
 };
 
 
 template<> struct randtest<Head>
 {
-       static void exec(ImageType::ImageType){}
+       static void exec(ImageType::ImageType, const map<string, Parameter<> >& 
= empty())
+       {}
 };
 
 int main(int ac, char** av)
@@ -322,7 +331,7 @@
                loadsave_safe<CVD::Rgba<unsigned int> >(av[i]);
        }
 
-       cerr << "Testing TEXT (type " << ImageType::BMP << ")\n";
+       cerr << "Testing TEXT (type " << ImageType::TEXT << ")\n";
        randtest<
                          TypeList<double,
                      TypeList<float,
@@ -342,6 +351,16 @@
                          TypeList<Rgb<unsigned short>,
                                       Head> > > > >::exec(ImageType::PNM);
 
+       cerr << "Testing PNM (type " << ImageType::PNM << "), text I/O\n";
+       map<string, Parameter<>  > p;
+       p["pnm.raw"] = Parameter<bool>(0);
+       randtest<
+                         TypeList<byte,
+                         TypeList<unsigned short,
+                         TypeList<Rgb<byte>,
+                         TypeList<Rgb<unsigned short>,
+                                      Head> > > > >::exec(ImageType::PNM, p);
+
        cerr << "Testing FITS (type " << ImageType::FITS << ")\n";
        randtest<
                          TypeList<byte,



reply via email to

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