CVD 0.8
|
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_