CVD 0.8
cvd/image_convert.h
00001 /*                       
00002     This file is part of the CVD Library.
00003 
00004     Copyright (C) 2005 The Authors
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Lesser General Public
00008     License as published by the Free Software Foundation; either
00009     version 2.1 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Lesser General Public License for more details.
00015 
00016     You should have received a copy of the GNU Lesser General Public
00017     License along with this library; if not, write to the Free Software
00018     Foundation, Inc., 
00019     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00020 */
00021 #ifndef CVD_IMAGE_CONVERT_H
00022 #define CVD_IMAGE_CONVERT_H
00023 
00024 #include <cvd/config.h>
00025 #include <cvd/internal/convert_pixel_types.h>
00026 #include <cvd/internal/rgb_components.h>
00027 #include <cvd/image.h>
00028 
00029 namespace CVD
00030 {
00031 
00032   // The most general case: one row at a time
00033 
00034   template <class From, class To, class Conv=typename Pixel::DefaultConversion<From,To>::type, int both_pod=Internal::is_POD<From>::is_pod && Internal::is_POD<To>::is_pod> struct ConvertImage {
00035     static void convert(const SubImage<From>& from, SubImage<To>& to) {
00036       for (int r=0; r<from.size().y; r++)
00037     Pixel::ConvertPixels<From,To,Conv>::convert(from[r], to[r], from.size().x);
00038     };
00039   };
00040 
00041   // The blat case: memcpy all data at once 
00042   template <class T> struct ConvertImage<T,T,Pixel::GenericConversion<T,T>,1> {
00043     static void convert(const SubImage<T>& from, SubImage<T>& to) {
00044       memcpy(to.data(), from.data(), from.totalsize() * sizeof(T));
00045     };
00046   };
00047 
00048   template <> struct ConvertImage<Rgb<byte>, byte, Pixel::CIE<Rgb<byte>, byte>, 1> {
00049       static void convert(const SubImage<Rgb<byte> >& from, SubImage<byte>& to);
00050   };
00051   
00052   template<class Conv, class C, class D> void convert_image(const SubImage<C>& from, SubImage<D>& to)
00053   {
00054     if (from.size() != to.size())
00055       throw Exceptions::Image::IncompatibleImageSizes(__FUNCTION__);
00056     ConvertImage<C,D,Conv>::convert(from, to);
00057   }
00058   
00059   template<template <class From, class To> class Conv, class C, class D> void convert_image(const SubImage<C>& from, SubImage<D>& to)
00060   {
00061     if (from.size() != to.size())
00062       throw Exceptions::Image::IncompatibleImageSizes(__FUNCTION__);
00063     ConvertImage<C,D,Conv<C,D> >::convert(from, to);
00064   }
00065 
00066   template<class C, class D> void convert_image(const SubImage<C>& from, SubImage<D>& to)
00067   {
00068       if (from.size() != to.size())
00069       throw Exceptions::Image::IncompatibleImageSizes(__FUNCTION__);
00070       ConvertImage<C,D>::convert(from, to);
00071   }
00072 
00073   template<class C, class D> void convert_image(const BasicImage<C>& from, BasicImage<D>& to)
00074   {
00075       if (from.size() != to.size())
00076       throw Exceptions::Image::IncompatibleImageSizes(__FUNCTION__);
00077       ConvertImage<C,D>::convert(from, to);
00078   }
00079 
00086   template<class D, class Conv, class C> Image<D> convert_image(const SubImage<C>& from)
00087   {
00088     Image<D> to(from.size());
00089     convert_image<Conv>(from, to);
00090     return to;
00091   }
00092     
00093   template<class D, template <class From, class To> class Conv, class C> Image<D> convert_image(const SubImage<C>& from)
00094   {
00095     Image<D> to(from.size());
00096     convert_image<Conv>(from, to);
00097     return to;
00098   }
00099 
00105   template<class D, class C> Image<D> convert_image(const SubImage<C>& from)
00106   {
00107     Image<D> to(from.size());
00108     convert_image(from, to);
00109     return to;
00110   }
00111 
00117   template<class D, class C> Image<D> convert_image(const BasicImage<C>& from)
00118   {
00119     Image<D> to(from.size());
00120     convert_image(from, to);
00121     return to;
00122   }
00123   
00124   // Function name changed from 'convert_image' to prevent compile-time
00125   // error arising from the clash with a function of same name declared above.
00126 
00133   template<class D1, class D2, class C> std::pair<Image<D1>, Image<D2> > convert_image_pair(const BasicImage<C>& from)
00134   {
00135     std::pair<Image<D1>, Image<D2> > to(Image<D1>(from.size()), Image<D2>(from.size()));
00136     convert_image(from, to.first);
00137     convert_image(from, to.second);
00138     return to;
00139   }  
00140 
00141 
00142   #ifndef DOXYGEN_IGNORE_INTERNAL
00143   namespace Internal
00144   {
00145     template<class C> class ImageConverter{};
00146     template<class C>  struct ImagePromise<ImageConverter<C> >
00147     {
00148         ImagePromise(const BasicImage<C>& im)
00149         :i(im)
00150         {}
00151 
00152         const BasicImage<C>& i;
00153         template<class D> void execute(Image<D>& j)
00154         {
00155             j.resize(i.size());
00156             convert_image(i, j);
00157         }
00158     };
00159   };
00160   template<class C> Internal::ImagePromise<Internal::ImageConverter<C> > convert_image(const BasicImage<C>& c)
00161   {
00162     return Internal::ImagePromise<Internal::ImageConverter<C> >(c);
00163   }
00164   #else
00165 
00166 
00167 
00168 
00169 
00170 
00171 
00172 
00173 
00174 
00175 
00176 
00177 
00178 
00179 
00180     template<class D> Image<D> convert_image(const BasicImage<C>& from);
00181 
00182   #endif
00183 
00184 
00185     template<class In, class Out> struct IsConvertible
00186     { 
00187         static const bool is=Pixel::DefaultConvertible<In>::is & Pixel::DefaultConvertible<Out>::is;
00188     };
00189 
00193     template<class In, class Out> struct PixelByPixelConvertible
00194     { 
00195         static const bool is=Pixel::DefaultConvertible<In>::is & Pixel::DefaultConvertible<Out>::is;
00196     };
00197 
00199     template<class InOut> struct PixelByPixelConvertible<InOut, InOut>
00200     { 
00201         static const bool is=1;
00202     };
00203 
00204 }
00205 
00206 #endif