CVD 0.8
cvd/draw.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 
00022 #ifndef CVD_DRAW_H_
00023 #define CVD_DRAW_H_
00024 
00025 #include <cvd/exceptions.h>
00026 #include <cvd/image.h>
00027 #include <cvd/image_ref.h>
00028 #include <cvd/internal/builtin_components.h>
00029 #include <cvd/internal/rgb_components.h>
00030 #include <cvd/image_convert.h>
00031 #include <cvd/utility.h>
00032 #include <vector>
00033 #include <algorithm>
00034 
00035 #include <cvd/config.h>
00036 #ifdef CVD_HAVE_TOON
00037 #include <TooN/TooN.h>
00038 #endif
00039 
00040 
00041 namespace CVD {
00042 
00043 namespace Exceptions {
00044 
00047     namespace Draw {
00050         struct All: public CVD::Exceptions::All {};
00051 
00054         struct ImageRefNotInImage : public All {
00055             ImageRefNotInImage(const std::string & function)
00056             {
00057                 what = "Input ImageRefs not in image in " + function;
00058             };
00059         };
00060 
00063         struct IncompatibleImageSizes : public All {
00064             IncompatibleImageSizes(const std::string & function)
00065             {
00066                 what = "Incompatible image sizes in " + function;
00067             };
00068         };
00069     };
00070 };
00071 
00074 template <class T, unsigned int N=Pixel::Component<T>::count> struct color {};
00075 
00079 template <class T> struct color<T,1> {
00080     typedef typename Pixel::Component<T>::type TComp;
00082     inline static const T& black() { static T c; Pixel::Component<T>::get(c,0) = 0; return c;}
00084     inline static const T& gray() { static T c; Pixel::Component<T>::get(c,0) = Pixel::traits<TComp>::max_intensity/2; return c;}
00086     inline static const T& white() { static T c; Pixel::Component<T>::get(c,0) = Pixel::traits<TComp>::max_intensity; return c;}
00087 };
00088 
00093 template <class T> struct color<T,3> {
00094     typedef typename Pixel::Component<T>::type TComp;
00095     static const TComp hi;
00096     inline static T make(const TComp& a, const TComp& b, const TComp& c) { 
00097     T t; 
00098     Pixel::Component<T>::get(t,0)=a;
00099     Pixel::Component<T>::get(t,1)=b;
00100     Pixel::Component<T>::get(t,2)=c;
00101     return t;
00102     }
00103     inline static const T&   black() { static const T c = make(0,0,0); return c;}
00104     inline static const T&   white() { static const T c = make(hi,hi,hi); return c;}
00105     inline static const T&     red() { static const T c = make(hi,0,0); return c;}
00106     inline static const T&   green() { static const T c = make(0,hi,0); return c;}
00107     inline static const T&    blue() { static const T c = make(0,0,hi); return c;}
00108     inline static const T&    cyan() { static const T c = make(0,hi,hi); return c; }
00109     inline static const T& magenta() { static const T c = make(hi,0,hi); return c;}
00110     inline static const T&  yellow() { static const T c = make(hi,hi,0); return c;}
00111     inline const T& shade(const T& c, double b) {
00112     return make((TComp)(Pixel::Component<T>::get(c,0)*b), (TComp)(Pixel::Component<T>::get(c,1)*b), (TComp)(Pixel::Component<T>::get(c,2)*b));
00113     }
00114 };
00115  template <class T> const typename color<T,3>::TComp color<T,3>::hi = Pixel::traits<TComp>::max_intensity;
00116 
00117 
00126 template <class T>
00127 void drawLine(SubImage<T>& im, double x1, double y1, double x2, double y2, const T& c)
00128 {
00129     double dx = x2-x1;
00130     double dy = y2-y1;
00131     int w = im.size().x;
00132     int h = im.size().y;
00133     double len = abs(dx)+abs(dy);
00134     for(int t=0;t<=len;t++) {
00135         int x = (int)(x1 + t/(len)*dx+0.5);
00136         int y = (int)(y1 + t/(len)*dy+0.5);
00137         if (x >=0 && x <w && y>=0 && y<h)
00138       im[y][x] = c;
00139     }
00140 }
00141 
00148 template <class T>
00149 void drawLine(SubImage<T>& im, const ImageRef& p1, const ImageRef& p2, const T& c)
00150 {
00151     drawLine(im, double(p1.x), double(p1.y), double(p2.x), double(p2.y), c);
00152 }
00153 
00154 #ifdef CVD_HAVE_TOON
00155 
00156 
00157 
00158 
00159 
00160 
00161 template <class T>
00162 void drawLine(SubImage<T>& im, const TooN::Vector<2>& p1, const TooN::Vector<2>& p2, const T& c)
00163 {
00164     drawLine(im, p1[0], p1[1], p2[0], p2[1], c);
00165 }
00166 #endif
00167 
00168 
00169 
00177 template <class T>
00178 void drawShape(SubImage<T>& im, const ImageRef& offset, const std::vector<ImageRef>& points, const T& c)
00179 {
00180     for (unsigned int i=0; i<points.size()-1; i++)
00181         drawLine(im, points[i]+offset, points[i+1]+offset, c);
00182     drawLine(im, points.back()+offset, points.front()+offset, c);
00183 }
00184 
00193 template <class T, class PointIterator>
00194 void drawShape(Image<T>& im, const ImageRef& offset,
00195                PointIterator begin, PointIterator end, const T& c) {
00196     if (begin == end) {
00197         return;
00198     }
00199     PointIterator last(begin);
00200     PointIterator it(begin);
00201     ++it;
00202     for (; it != end; it++) {
00203         drawLine(im, *last+offset, *(it)+offset, c);
00204         last = it;
00205     }
00206     drawLine(im, (*last)+offset, (*begin)+offset, c);
00207 }
00208 
00215 template <class T>
00216 void drawBox(SubImage<T> &im, const ImageRef & upperleft, const ImageRef & lowerright, const T& c)
00217 {
00218     drawLine(im, upperleft.x, upperleft.y, upperleft.x, lowerright.y, c);
00219     drawLine(im, upperleft.x, upperleft.y, lowerright.x, upperleft.y, c);
00220     drawLine(im, upperleft.x, lowerright.y, lowerright.x, lowerright.y, c);
00221     drawLine(im, lowerright.x, upperleft.y, lowerright.x, lowerright.y, c);
00222 }
00223 
00230 template <class T>
00231 void drawCross(SubImage<T>& im, const ImageRef& p, double len, const T& c)
00232 {
00233     drawLine(im, p.x-len, p.y, p.x+len, p.y, c);
00234     drawLine(im, p.x, p.y-len, p.x, p.y+len, c);
00235 }
00236 
00242 std::vector<ImageRef> getCircle(int radius);
00243 
00244 
00250 std::vector<ImageRef> getDisc(float radius);
00251 
00252 
00253 #if defined CVD_HAVE_TOON || defined DOXYGEN_IGNORE_INTERNAL
00254 
00255 
00256 
00257 
00258 
00259 
00260 
00261 std::vector<ImageRef> getSolidEllipse(float r1, float r2, float theta);
00262 #endif
00263 
00269 template <class S, class T, class U> void joinImages(const Image<S>& a, const Image<T>& b, Image<U>& J) {
00270   int h = std::max(a.size().y,b.size().y);
00271     J.resize(ImageRef(a.size().x+b.size().x, h));
00272     CVD::copy(a, J, a.size());
00273     CVD::copy(b, J, b.size(), ImageRef(), ImageRef(a.size().x, 0));
00274     ImageRef blackBegin, blackEnd;
00275     if (a.size().y < b.size().y) {
00276         blackBegin = ImageRef(0,a.size().y);
00277         blackEnd = ImageRef(a.size().x,J.size().y);
00278     } else {
00279         blackBegin = ImageRef(a.size().x, b.size().y);
00280         blackEnd = J.size();
00281     }
00282     for (int i = blackBegin.y; i<blackEnd.y; i++)
00283       for (int j= blackBegin.x; j<blackEnd.x; j++)
00284     J[i][j] = U();
00285 }
00286 
00287 
00294 template <class S, class T, class U> void combineImages(const Image<S>& a, const Image<T>& b, Image<U>& out, const ImageRef & dst = ImageRef_zero, ImageRef size = ImageRef(), const ImageRef & from = ImageRef_zero)
00295 {
00296     if(!a.in_image(dst))
00297         throw Exceptions::Draw::ImageRefNotInImage("combineImages");
00298     if(a.size() != out.size)
00299         throw Exceptions::Draw::IncompatibleImageSizes("combineImages");
00300 
00301     if( size == ImageRef_zero )
00302         size = b.size();
00303 
00304     if (size.x + dst.x >= a.size().x)
00305       size.x = a.size().x - dst.x;
00306     if (size.x + dst.x >= out.size().x)
00307       size.x = out.size().x - dst.x;
00308     if (size.y + dst.y >= a.size().y)
00309       size.y = a.size().y - dst.y;
00310     if (size.y + dst.y >= out.size().y)
00311       size.y = out.size().y - dst.y;
00312 
00313     if( &a != &out )
00314     {
00315         CVD::copy(a,out, a.size());
00316     }
00317 
00318     ImageRef sourceA = dst;
00319     ImageRef sourceB = from;
00320     ImageRef endA = dst + size;
00321     ImageRef endB = from + size;
00322 
00323     out[sourceA] += b[sourceB];
00324     while(sourceA.next(dst, endA))
00325     {
00326         sourceB.next(from, endB);
00327         out[sourceA] += b[sourceB];
00328     }
00329 }
00330 
00331 };
00332 #endif // CVD_DRAW_H_