00001
00007 #ifndef __MATRIX_IMAGE_H__
00008 #define __MATRIX_IMAGE_H__
00009
00010 #include <cassert>
00011 #include <algorithm>
00012 #include <cmath>
00013
00014
00015 #include "../src/matrix.h"
00016 #include "../src/pixel.h"
00017 #include "../src/colorlookup.h"
00018 #include "../src/boundingbox.h"
00019 #include "../src/image.h"
00020
00021 namespace Plot {
00022
00023
00036 template<class PixelType=RGBPixel<>, class PixelMatrix=MatrixType<PixelType>::rectangular >
00037 class MatrixImage : public AARImage<PixelType,PixelMatrix> {
00038 private:
00039
00041 typedef AARImage<PixelType,PixelMatrix>::PixelSubscript PixelSubscript;
00042
00044 typedef AARImage<PixelType,PixelMatrix>::CartesianCoordinate CartesianCoordinate;
00045
00047 typedef int MatrixSubscript;
00048
00050 PixelSubscript border;
00051
00053 MatrixSubscript height;
00054
00056 MatrixSubscript width;
00057
00059 double size_scale;
00060
00063 inline bool inside(const MatrixSubscript r, const MatrixSubscript c) const {
00064 return (r>=0 && r<height &&
00065 c>=0 && c<width);
00066 }
00067
00069 inline MatrixSubscript matrix_row(const MatrixSubscript r) const
00070 { return MatrixSubscript(floor((r-border)/size_scale)); }
00071
00073 inline MatrixSubscript matrix_col(const PixelSubscript c) const
00074 { return MatrixSubscript(floor((c-border)/size_scale)); }
00075
00077 inline PixelSubscript pixel_row(const MatrixSubscript r) const
00078 { return PixelSubscript(r*size_scale)+border; }
00079
00081 inline PixelSubscript pixel_col(const MatrixSubscript c) const
00082 { return PixelSubscript(c*size_scale)+border; }
00083
00085 inline CartesianCoordinate x_from_matrixcol(const MatrixSubscript col)
00086 { return CartesianCoordinate(pixel_col(col))+size_scale/2; }
00087
00089 inline CartesianCoordinate y_from_matrixrow(const MatrixSubscript row)
00090 { return CartesianCoordinate(nrows()-1-(pixel_row(row)+size_scale/2))+0.5; }
00091
00093 inline void draw_element(const MatrixSubscript row, const MatrixSubscript col, PixelType p)
00094 { draw_rectangle(pixel_row(row), pixel_col(col), pixel_row(row+1), pixel_col(col+1),p); }
00095
00096 template<class T> bool onboundary
00097 (const BoundingBox<T>& bb, unsigned thickness, PixelSubscript r, PixelSubscript c) const;
00098
00099
00100 public:
00103
00105 MatrixImage() { }
00106
00107 template <class Matrix>
00108 MatrixImage(const Matrix &A, double scale=1.0, int borderwidth=0, const ColorLookup<PixelType>& L=RYWColorLookup<PixelType>() );
00109
00110 template <class Matrix>
00111 MatrixImage(const Matrix &H, const Matrix &S, const Matrix &V, double scale=1.0, int borderwidth=0 );
00113
00114
00116
00117 void draw_bar_on_matrix_element(const MatrixSubscript row, const MatrixSubscript col,
00118 double angle, double length, double width=1, PixelType p=default_fg)
00119 { draw_bar(x_from_matrixcol(col), y_from_matrixrow(row), angle, length, width, p); }
00120
00121
00124 template<class T> inline void outline_boundary
00125 (const BoundingBox<T>& bb, unsigned thickness, PixelType p=default_fg);
00126
00127 };
00128
00129
00130
00133 template<class PixelType, class PixelMatrix>
00134 template <class Matrix>
00135 MatrixImage<PixelType,PixelMatrix>::MatrixImage
00136 (const Matrix &A, double scale, int borderwidth, const ColorLookup<PixelType>& L )
00137 : AARImage<PixelType>(typename Matrix::size_type(scale*A.nrows()+2*borderwidth),
00138 typename Matrix::size_type(scale*A.ncols()+2*borderwidth)),
00139 border(borderwidth), height(A.nrows()), width(A.ncols()), size_scale(scale) {
00140 draw_border(borderwidth);
00141 typedef typename Matrix::size_type Subscript;
00142 for (Subscript r=0; r<A.nrows(); r++)
00143 for (Subscript c=0; c<A.ncols(); c++) {
00144 const Bounded::LargeFloat val = mat::elem(A,r,c);
00145 draw_element(r,c,L(val));
00146 }
00147 }
00148
00149
00150
00152 template<class PixelType, class PixelMatrix>
00153 template <class Matrix>
00154 MatrixImage<PixelType,PixelMatrix>::MatrixImage
00155 (const Matrix &H, const Matrix &S, const Matrix &V, double scale, int borderwidth )
00156 : AARImage<PixelType>(typename Matrix::size_type(scale*H.nrows()+2*borderwidth),
00157 typename Matrix::size_type(scale*H.ncols()+2*borderwidth)),
00158 border(borderwidth), height(H.nrows()), width(H.ncols()), size_scale(scale) {
00159 assert(H.nrows()==S.nrows()); assert(H.nrows()==V.nrows());
00160 assert(H.ncols()==S.ncols()); assert(H.ncols()==V.ncols());
00161 draw_border(borderwidth);
00162 typedef typename Matrix::size_type Subscript;
00163 for (Subscript r=0; r<H.nrows(); r++)
00164 for (Subscript c=0; c<H.ncols(); c++)
00165 draw_element(r,c,HSVPixel<>(mat::elem(H,r,c),mat::elem(S,r,c),mat::elem(V,r,c)));
00166 }
00167
00168
00169
00170 template<class PixelType, class PixelMatrix>
00171 template<class T>
00172 void MatrixImage<PixelType,PixelMatrix>::outline_boundary
00173 (const BoundingBox<T>& bb, unsigned thickness, PixelType pixel)
00174 {
00175 PixelType p=pixel;
00176
00179 if (p.istransparent()) {
00180 PixelAverage<> pa;
00181 for (PixelSubscript row=0; row<nrows(); row++)
00182 for (PixelSubscript col=0; col<ncols(); col++)
00183 if (onboundary(bb,thickness,row,col))
00184 pa+=get_pixel(row,col);
00185 p=contrasting_color(pa());
00186 }
00187
00188 for (PixelSubscript row=0; row<nrows(); row++)
00189 for (PixelSubscript col=0; col<ncols(); col++)
00190 if (onboundary(bb,thickness,row,col))
00191 draw_pixel(row,col,p);
00192 }
00193
00194
00195
00212 template<class PixelType, class PixelMatrix>
00213 template<class T>
00214 inline bool MatrixImage<PixelType,PixelMatrix>::onboundary
00215 (const BoundingBox<T>& bb, unsigned thickness, PixelSubscript r, PixelSubscript c) const
00216 {
00217 if (inside(matrix_row(r),matrix_col(c)) && bb.inside(matrix_row(r),matrix_col(c)))
00218 return false;
00219
00220 for (PixelSubscript sr=max<MatrixSubscript>(0,r-thickness); sr<=min<MatrixSubscript>(nrows(),r+thickness); sr++)
00221 for (PixelSubscript sc=max<MatrixSubscript>(0,c-thickness); sc<=min<MatrixSubscript>(ncols(),c+thickness); sc++) {
00222 const MatrixSubscript row=matrix_row(sr);
00223 const MatrixSubscript col=matrix_col(sc);
00224 if (inside(row,col) && bb.inside(row,col))
00225 return true;
00226 }
00227 }
00228
00229
00230
00231 }
00232 #endif