Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

image.h

Go to the documentation of this file.
00001 
00007 #ifndef __IMAGE_H__
00008 #define __IMAGE_H__
00009 
00010 #include <algorithm>
00011 #include <cmath>
00012 #include <fstream>
00013 #include <string>
00014 
00015 #include "matrix.h"
00016 #include "pixel.h"
00017 
00018 #ifndef M_PI
00019 #define M_PI            3.14159265358979323846  /* pi */
00020 #endif
00021 
00022 namespace  Plot {
00023 
00024 
00042 template<class PixelType=RGBPixel<>, class PixelMatrix=MatrixType<PixelType>::rectangular >
00043 class AARImage {
00044 private:
00045   void BresenhamAlongC(int rA, int cA, int rB, int cB, int direction, PixelType p, int thickness);
00046   void BresenhamAlongR(int rA, int cA, int rB, int cB, int direction, PixelType p, int thickness);
00047   
00049   PixelMatrix pixels;
00050 
00051 public:
00053   typedef typename PixelMatrix::size_type PixelSubscript;
00054   typedef PixelSubscript size_type;
00055   typedef PixelType value_type;
00056 
00058   typedef double CartesianCoordinate;
00059 
00061   AARImage(PixelSubscript height=0, PixelSubscript width=0)
00062     : pixels (height,width)  {  mat::set(pixels,default_bg); }
00063 
00065   inline void draw_pixel(const PixelSubscript r, const PixelSubscript c, PixelType p) {
00066     if (inbounds(r,c))
00067       pixels[r][c] = p;
00068   }
00069 
00071   inline const PixelType& get_pixel(const PixelSubscript r, const PixelSubscript c) const
00072     {  return(pixels[r][c]);  }
00073 
00075   inline PixelSubscript nrows() const {  return pixels.nrows();  }
00076 
00078   inline PixelSubscript ncols() const {  return pixels.ncols();  }
00079 
00080   
00081   void draw_rectangle(int r1, int c1, int r2, int c2, PixelType p);
00082   void draw_line(int r1, int c1, int r2, int c2, PixelType p, int thickness=1);
00083   void draw_bar(CartesianCoordinate cx, CartesianCoordinate cy,
00084                 double angle, double length, double width=1, PixelType p=default_fg, bool always_draw=true);
00085 
00087   void draw_border(size_type borderwidth=1, PixelType p=default_border) {
00088     const PixelSubscript b=borderwidth;
00089     const PixelSubscript r=nrows();
00090     const PixelSubscript c=ncols();
00091     
00092     draw_rectangle(0,   0,   r, b,   p);
00093     draw_rectangle(0,   b,   b, c-b, p);
00094     draw_rectangle(0,   c-b, r, c,   p);
00095     draw_rectangle(r-b, b,   r, c-b, p);
00096   }
00097 
00098   ostream& ppm_write( ostream& os, const string& comments="", int max_val=255 );
00099 
00101   template<class PType, class PMatrix>
00102   friend ostream& operator<<(ostream& s, const AARImage<PType,PMatrix>& o);
00103 
00104 protected:
00106   inline PixelSubscript col_from_x(const CartesianCoordinate x) {  return PixelSubscript(x);  }
00107 
00109   inline PixelSubscript row_from_y(const CartesianCoordinate y) {  return PixelSubscript(pixels.nrows()-1-y);  }
00110    
00112   inline bool inbounds(const PixelSubscript r, const PixelSubscript c) const {
00113     return (r>=0 && r<pixels.nrows() &&
00114             c>=0 && c<pixels.ncols());
00115   }
00116 
00117 public:  
00119   static PixelType default_fg;
00120   static PixelType default_bg;
00121   static PixelType default_border;
00122 };
00123 
00124 
00125 
00126 /* Static defaults */ 
00127 template<class PixelType, class PixelMatrix> PixelType AARImage<PixelType,PixelMatrix>::default_fg(1,1,1,false);
00128 template<class PixelType, class PixelMatrix> PixelType AARImage<PixelType,PixelMatrix>::default_bg(0,0,0);
00129 template<class PixelType, class PixelMatrix> PixelType AARImage<PixelType,PixelMatrix>::default_border(1,1,1);
00130 
00131  
00132   
00139 template<class PixelType, class PixelMatrix>
00140 ostream& AARImage<PixelType,PixelMatrix>::ppm_write( ostream& os, const string& comments, int max_val)
00141 {
00142   os << "P6\n"; /* file type: P6=binary, P3=ASCII */
00143   os << "#" << comments.c_str() << "\n";
00144   os << pixels.ncols()  << " " << pixels.nrows() << "\n";  
00145   os << max_val         << "\n"; /* maximum R, G, or B value */
00146 
00147   for   (PixelSubscript r=0; r<pixels.nrows(); r++)
00148     for (PixelSubscript c=0; c<pixels.ncols(); c++)
00149       (pixels[r][c].write_binary(os, max_val));
00150 
00151   return os;
00152 }
00153 
00154 
00155  
00157 template<class PixelType, class PixelMatrix>  
00158 ostream& operator<<(ostream& s, const AARImage<PixelType,PixelMatrix>& o)
00159   {  return cout << o.pixels;  }
00160 
00161  
00162 
00166 template<class PixelType, class PixelMatrix>  
00167 void AARImage<PixelType,PixelMatrix>::draw_rectangle(int r1, int c1, int r2, int c2, PixelType p)
00168 {
00169   for (PixelSubscript r=min(r1,r2); r<max(r1,r2); r++)
00170     for (PixelSubscript c=min(c1,c2); c<max(c1,c2); c++)
00171       draw_pixel(r,c,p);
00172 }
00173 
00174 
00175 
00182 template<class PixelType, class PixelMatrix>  
00183 void AARImage<PixelType,PixelMatrix>::draw_line(int r1, int c1, int r2, int c2, PixelType p, int thickness)
00184 {
00185   int rA,rB,cA,cB;  /* canonical form of coordinates   */
00186   int r, direction;
00187   
00188   /* Swap endpoints if line wasn't specifed from left to right */
00189   const int dc = c2-c1;
00190   if (dc >= 0)  { rA = r1; cA = c1;   r = r2; cB = c2; }
00191   else          { rA = r2; cA = c2;   r = r1; cB = c1; }
00192   
00193   
00194   /* Flip right endpoint across horizontal axis if it is above it 
00195      (leaves lower right quadrant only) */
00196   const int dr = rA-r;
00197   if (dr < 0)   { direction =  1;  rB =         r; }
00198   else          { direction = -1;  rB = (rA<<1)-r; }
00199 
00200   //cout << "(" << rA << "," << cA << ") -> (" << rB << "," << cB << ") " << direction << " " << p << endl;
00201   //cout << "dr: " << dr << " dc: " << dc << endl;
00202 
00203   /* Iterate along the axis which changes the most */
00204   if (abs(dc) > abs(dr))  BresenhamAlongC(rA, cA, rB, cB,  direction, p, thickness);
00205   else                    BresenhamAlongR(rA, cA, rB, cB,  direction, p, thickness);
00206 }
00207 
00208 
00209 
00212 template<class PixelType, class PixelMatrix>  
00213 void AARImage<PixelType,PixelMatrix>::BresenhamAlongC(int rA, int cA, int rB, int cB, int direction, PixelType p, int thickness)
00214 {
00215   const int dr    = rB-rA;
00216   const int dc    = cB-cA;
00217   const int incE  = 2*dr;
00218   const int incSE = 2*(dr-dc);
00219 
00220   //cout << "AlongC" << endl;
00221   
00222   int d = 2*dr-dc;
00223   int r = rA;
00224   int i;
00225   
00226   for (i=-thickness/2; i<=thickness/2; i++)
00227     draw_pixel(rA+i,cA,p);  /* set starting point */
00228 
00229   for (int c=cA+1; c<=cB; c++) {
00230     if (d <= 0 ) /* choose E */
00231       d += incE;
00232     else {       /* choose SE */
00233       d += incSE;
00234       r += direction;
00235     }
00236     for (i=-thickness/2; i<=thickness/2; i++)
00237       draw_pixel(r+i,c,p);
00238   }
00239 }
00240 
00241 
00242 
00245 template<class PixelType, class PixelMatrix>
00246 void AARImage<PixelType,PixelMatrix>::BresenhamAlongR(int rA, int cA, int rB, int cB, int direction, PixelType p, int thickness)
00247 {
00248   const int dc    = cB-cA;
00249   const int dr    = rB-rA;
00250   const int incE  = 2*dc;
00251   const int incSE = 2*(dc-dr);
00252 
00253   //cout << "AlongR" << endl;
00254   
00255   int d  = 2*dc-dr;
00256   int c  = cA;
00257   int rp = rA; /* r corrected for direction */
00258 
00259   int i;
00260   
00261   for (i=-thickness/2; i<=thickness/2; i++)
00262     draw_pixel(rA,cA+i,p);  /* set starting point */
00263 
00264   for (int r=rA; r<rB; r++) {
00265     rp += direction;
00266     if (d <= 0 ) /* choose E */
00267       d += incE;
00268     else {       /* choose SE */
00269       d += incSE;
00270       c += 1;
00271     }
00272     for (i=-thickness/2; i<=thickness/2; i++)
00273       draw_pixel(rp,c+i,p);
00274   }
00275 }
00276 
00277 
00278 
00294 template<class PixelType, class PixelMatrix>
00295 void AARImage<PixelType,PixelMatrix>::draw_bar(CartesianCoordinate cx, CartesianCoordinate cy,
00296                                                double angle, double length, double width, 
00297                                                PixelType p, bool always_draw)
00298 {
00299   /* Lines shorter than one pixel can be skipped if requested */
00300   /* The "-1" corrects for the width of the halves of each endpoint that are counted implicitly */
00301   if (always_draw || length >= 1.0) {
00302     const double              xoffset = (double)(((length)/2)*cos(angle));
00303     const double              yoffset = (double)(((length)/2)*sin(angle));
00304     const CartesianCoordinate y1      = cy-yoffset;
00305     const CartesianCoordinate y2      = cy+yoffset;
00306     const CartesianCoordinate x1      = cx-xoffset;
00307     const CartesianCoordinate x2      = cx+xoffset;
00308     const PixelSubscript      r1      = row_from_y(y1);
00309     const PixelSubscript      r2      = row_from_y(y2);
00310     const PixelSubscript      c1      = col_from_x(x1);
00311     const PixelSubscript      c2      = col_from_x(x2);
00312     
00315     if (p.istransparent()) {
00316       PixelAverage<> pa;
00317       pa+=get_pixel(r1,c1);
00318       pa+=get_pixel(r2,c2);
00319       p=contrasting_color(pa());
00320     }
00321 
00322     /* Draw at least one full line */ 
00323     if (width<=1)
00324       draw_line(r1,c1,r2,c2,p,1);
00325     else {
00326       /* This is a hack to get a filled rectangle without having to handle polygons */
00327       double delt;
00328       for (delt=0; delt<width/2; delt+=0.5) {
00329         const double deltax=(double)(delt*cos(M_PI/2-angle));
00330         const double deltay=(double)(delt*sin(M_PI/2-angle));
00331         draw_line( row_from_y(y1+deltay), col_from_x(x1-deltax),
00332                    row_from_y(y2+deltay), col_from_x(x2-deltax), p, std::min(2,int(width)));
00333         draw_line( row_from_y(y1-deltay), col_from_x(x1+deltax),
00334                    row_from_y(y2-deltay), col_from_x(x2+deltax), p, std::min(2,int(width)));
00335       }
00336     }
00337   }
00338 }
00339 
00340 
00341 
00342 } /* namespace Plot */
00343 #endif /* __IMAGE_H__ */

Generated at Mon Aug 21 00:30:54 2000 for RF-LISSOM by doxygen1.2.1 written by Dimitri van Heesch, © 1997-2000