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= typename MatrixType<PixelType>::rectangular >
00037 class MatrixImage : public AARImage<PixelType,PixelMatrix> {
00038 private:
00039
00041 typedef typename AARImage<PixelType,PixelMatrix>::PixelSubscript PixelSubscript;
00042
00044 typedef typename 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 BoundingBoxType> bool onboundary
00097 (const BoundingBoxType& bb, unsigned thickness, PixelSubscript r, PixelSubscript c) const;
00098
00099
00100 public:
00103
00105 MatrixImage() : border(0), height(0), width(0), size_scale(1.0) { }
00106
00107 template <class Matrix>
00108 MatrixImage(const Matrix &A, double scale=1.0, int borderwidth=0,
00109 const ColorLookup<PixelType>& L=RYWColorLookup<PixelType>(),
00110 PixelType bordercolor=default_border );
00111
00112 template <class Matrix>
00113 MatrixImage(const Matrix &H, const Matrix &S, const Matrix &V, double scale=1.0,
00114 int borderwidth=0, PixelType bordercolor=default_border );
00116
00117
00119
00120 void draw_bar_on_matrix_element(const MatrixSubscript row, const MatrixSubscript col,
00121 double angle, double length, double width=1, PixelType p=default_fg)
00122 { draw_bar(x_from_matrixcol(col), y_from_matrixrow(row), angle, length, width, p); }
00123
00124
00130 template<class BoundingBoxType> inline void outline_boundary
00131 (const BoundingBoxType& bb, unsigned thickness, PixelType p=default_fg, bool infinite_outline=false);
00132
00133 };
00134
00135
00136
00139 template<class PixelType, class PixelMatrix>
00140 template <class Matrix>
00141 MatrixImage<PixelType,PixelMatrix>::MatrixImage
00142 (const Matrix &A, double scale, int borderwidth, const ColorLookup<PixelType>& L,
00143 PixelType bordercolor)
00144 : AARImage<PixelType>(typename Matrix::size_type(scale*A.nrows()+2*borderwidth),
00145 typename Matrix::size_type(scale*A.ncols()+2*borderwidth)),
00146 border(borderwidth), height(A.nrows()), width(A.ncols()), size_scale(scale) {
00147 draw_border(borderwidth,bordercolor);
00148 typedef typename Matrix::size_type Subscript;
00149 for (Subscript r=0; r<A.nrows(); r++)
00150 for (Subscript c=0; c<A.ncols(); c++) {
00151 const Bounded::LargeFloat val = mat::elem(A,r,c);
00152 draw_element(r,c,L(val));
00153 }
00154 }
00155
00156
00157
00159 template<class PixelType, class PixelMatrix>
00160 template <class Matrix>
00161 MatrixImage<PixelType,PixelMatrix>::MatrixImage
00162 (const Matrix &H, const Matrix &S, const Matrix &V, double scale, int borderwidth,
00163 PixelType bordercolor)
00164 : AARImage<PixelType>(typename Matrix::size_type(scale*H.nrows()+2*borderwidth),
00165 typename Matrix::size_type(scale*H.ncols()+2*borderwidth)),
00166 border(borderwidth), height(H.nrows()), width(H.ncols()), size_scale(scale) {
00167 assert(H.nrows()==S.nrows()); assert(H.nrows()==V.nrows());
00168 assert(H.ncols()==S.ncols()); assert(H.ncols()==V.ncols());
00169 draw_border(borderwidth,bordercolor);
00170 typedef typename Matrix::size_type Subscript;
00171 for (Subscript r=0; r<H.nrows(); r++)
00172 for (Subscript c=0; c<H.ncols(); c++)
00173 draw_element(r,c,HSVPixel<>(mat::elem(H,r,c),mat::elem(S,r,c),mat::elem(V,r,c)));
00174 }
00175
00176
00177
00178 template<class PixelType, class PixelMatrix>
00179 template<class BoundingBoxType>
00180 void MatrixImage<PixelType,PixelMatrix>::outline_boundary
00181 (const BoundingBoxType& bb, unsigned thickness, PixelType pixel, bool infinite_outline)
00182 {
00183 PixelType p=pixel;
00184
00186 const PixelSubscript nr = AARImage<PixelType,PixelMatrix>::nrows();
00187 const PixelSubscript nc = AARImage<PixelType,PixelMatrix>::ncols();
00188
00191 if (p.istransparent()) {
00192 PixelAverage<> pa;
00193 for (PixelSubscript row=0; row<nr; row++)
00194 for (PixelSubscript col=0; col<nc; col++)
00195 if (onboundary(bb,thickness,row,col))
00196 pa+=get_pixel(row,col);
00197 p=contrasting_color(pa());
00198 }
00199
00200 for (PixelSubscript row=0; row<nr; row++)
00201 for (PixelSubscript col=0; col<nc; col++)
00202 if ((infinite_outline && !bb.inside(matrix_row(row),matrix_col(col))) ||
00203 (onboundary(bb,thickness,row,col)))
00204 draw_pixel(row,col,p);
00205 }
00206
00207
00208
00225 template<class PixelType, class PixelMatrix>
00226 template<class BoundingBoxType>
00227 inline bool MatrixImage<PixelType,PixelMatrix>::onboundary
00228 (const BoundingBoxType& bb, unsigned thickness, PixelSubscript r, PixelSubscript c) const
00229 {
00230 if (inside(matrix_row(r),matrix_col(c)) && bb.inside(matrix_row(r),matrix_col(c)))
00231 return false;
00232
00234 const PixelSubscript nr = AARImage<PixelType,PixelMatrix>::nrows();
00235 const PixelSubscript nc = AARImage<PixelType,PixelMatrix>::ncols();
00236
00237 for (PixelSubscript sr=max<MatrixSubscript>(0,r-thickness);
00238 MatrixSubscript(sr)<=min<MatrixSubscript>(nr,r+thickness); sr++)
00239 for (PixelSubscript sc=max<MatrixSubscript>(0,c-thickness);
00240 MatrixSubscript(sc)<=min<MatrixSubscript>(nc,c+thickness); sc++) {
00241 const MatrixSubscript row=matrix_row(sr);
00242 const MatrixSubscript col=matrix_col(sc);
00243 if (inside(row,col) && bb.inside(row,col))
00244 return true;
00245 }
00246
00247 return false;
00248 }
00249
00250
00251
00252 }
00253 #endif