00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00191 template <class T>
00192 void drawBox(SubImage<T> &im, const ImageRef & upperleft, const ImageRef & lowerright, const T& c)
00193 {
00194 drawLine(im, upperleft.x, upperleft.y, upperleft.x, lowerright.y, c);
00195 drawLine(im, upperleft.x, upperleft.y, lowerright.x, upperleft.y, c);
00196 drawLine(im, upperleft.x, lowerright.y, lowerright.x, lowerright.y, c);
00197 drawLine(im, lowerright.x, upperleft.y, lowerright.x, lowerright.y, c);
00198 }
00199
00206 template <class T>
00207 void drawCross(SubImage<T>& im, const ImageRef& p, double len, const T& c)
00208 {
00209 drawLine(im, p.x-len, p.y, p.x+len, p.y, c);
00210 drawLine(im, p.x, p.y-len, p.x, p.y+len, c);
00211 }
00212
00218 std::vector<ImageRef> getCircle(int radius);
00219
00220
00226 std::vector<ImageRef> getDisc(float radius);
00227
00228
00229 #if defined CVD_HAVE_TOON || defined DOXYGEN_IGNORE_INTERNAL
00230
00231
00232
00233
00234
00235
00236
00237 std::vector<ImageRef> getSolidEllipse(float r1, float r2, float theta);
00238 #endif
00239
00245 template <class S, class T, class U> void joinImages(const Image<S>& a, const Image<T>& b, Image<U>& J) {
00246 int h = std::max(a.size().y,b.size().y);
00247 J.resize(ImageRef(a.size().x+b.size().x, h));
00248 CVD::copy(a, J, a.size());
00249 CVD::copy(b, J, b.size(), ImageRef(), ImageRef(a.size().x, 0));
00250 ImageRef blackBegin, blackEnd;
00251 if (a.size().y < b.size().y) {
00252 blackBegin = ImageRef(0,a.size().y);
00253 blackEnd = ImageRef(a.size().x,J.size().y);
00254 } else {
00255 blackBegin = ImageRef(a.size().x, b.size().y);
00256 blackEnd = J.size();
00257 }
00258 for (int i = blackBegin.y; i<blackEnd.y; i++)
00259 for (int j= blackBegin.x; j<blackEnd.x; j++)
00260 J[i][j] = U();
00261 }
00262
00263
00270 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)
00271 {
00272 if(!a.in_image(dst))
00273 throw Exceptions::Draw::ImageRefNotInImage("combineImages");
00274 if(a.size() != out.size)
00275 throw Exceptions::Draw::IncompatibleImageSizes("combineImages");
00276
00277 if( size == ImageRef_zero )
00278 size = b.size();
00279
00280 if (size.x + dst.x >= a.size().x)
00281 size.x = a.size().x - dst.x;
00282 if (size.x + dst.x >= out.size().x)
00283 size.x = out.size().x - dst.x;
00284 if (size.y + dst.y >= a.size().y)
00285 size.y = a.size().y - dst.y;
00286 if (size.y + dst.y >= out.size().y)
00287 size.y = out.size().y - dst.y;
00288
00289 if( &a != &out )
00290 {
00291 CVD::copy(a,out, a.size());
00292 }
00293
00294 ImageRef sourceA = dst;
00295 ImageRef sourceB = from;
00296 ImageRef endA = dst + size;
00297 ImageRef endB = from + size;
00298
00299 out[sourceA] += b[sourceB];
00300 while(sourceA.next(dst, endA))
00301 {
00302 sourceB.next(from, endB);
00303 out[sourceA] += b[sourceB];
00304 }
00305 }
00306
00307 };
00308 #endif // CVD_DRAW_H_