00001 #include "Graphics.h"
00002 #include "FilterBankGenerator.h"
00003
00004 using namespace std;
00005
00006
00007
00008
00009
00010 #define CHKBOUNDS(p,ERR_F) { \
00011 unsigned int rowoffset=(p-img)-(p-img)/yInc*yInc; \
00012 if(p<img || p>=img+h*yInc || rowoffset>=w*xInc || rowoffset/xInc*xInc!=rowoffset) { \
00013 cout << "Graphics Bad draw! line:" << __LINE__ << " frame=" << (gen!=NULL?gen->getFrameNumber():0) << ' ' << (int)(p-img) << " w=" << w << " xInc=" << xInc << " h=" << h << " yInc=" << yInc << endl; \
00014 ERR_F; \
00015 } \
00016 }
00017
00018
00019 Graphics::Graphics(FilterBankGenerator& fbg, unsigned int layer, unsigned int channel)
00020 : gen(&fbg), genLayer(layer), genChan(channel), img(NULL), w(0), h(0), xInc(0), yInc(0), c(0)
00021 {
00022 updateFBG();
00023 }
00024
00025 Graphics::Graphics(unsigned char * base, unsigned int width, unsigned int height, unsigned int interval, unsigned int stride)
00026 : gen(NULL), genLayer(), genChan(), img(base), w(width), h(height), xInc(interval), yInc(stride), c(0)
00027 {}
00028
00029 void Graphics::updateFBG() {
00030 if(gen==NULL)
00031 return;
00032 img=gen->getImage(genLayer,genChan);
00033 w=gen->getWidth(genLayer);
00034 h=gen->getHeight(genLayer);
00035 xInc=gen->getIncrement(genLayer);
00036 yInc=gen->getStride(genLayer);
00037 }
00038
00039 void Graphics::drawRect(int x, int y, int width, int height) {
00040 if(img==NULL)
00041 return;
00042 if(width<0) {
00043 x+=width;
00044 width=-width;
00045 }
00046 if(height<0) {
00047 y+=height;
00048 height=-height;
00049 }
00050 if(x>=(int)w || y>=(int)h || x+width<0 || y+height<0)
00051 return;
00052 if(x<0 && y<0 && x+width>=(int)w && y+height>=(int)h)
00053 return;
00054 unsigned int left=x>0?x:0;
00055 unsigned int top=y>0?y:0;
00056 unsigned int right=( (x+width>=(int)w) ? w : x+width);
00057 unsigned int bot=( (y+height>=(int)h) ? h : y+height);
00058
00059 if(x>=0) {
00060 unsigned char * p=img+top*yInc+left*xInc;
00061 unsigned char * end=img+bot*yInc+left*xInc;
00062 while(p!=end) {
00063 CHKBOUNDS(p,return);
00064 *p=c;
00065 p+=yInc;
00066 }
00067 }
00068
00069 if(y>=0) {
00070 unsigned char * p=img+top*yInc+left*xInc;
00071 unsigned char * end=img+top*yInc+right*xInc;
00072 while(p!=end) {
00073 CHKBOUNDS(p,return);
00074 *p=c;
00075 p+=xInc;
00076 }
00077 }
00078
00079 if(right<w && left!=right) {
00080 unsigned char * p=img+top*yInc+right*xInc;
00081 unsigned char * end=img+bot*yInc+right*xInc;
00082 while(p!=end) {
00083 CHKBOUNDS(p,return);
00084 *p=c;
00085 p+=yInc;
00086 }
00087 }
00088
00089 if(bot<h && top!=bot) {
00090 unsigned char * p=img+bot*yInc+left*xInc;
00091 unsigned char * end=img+bot*yInc+right*xInc;
00092 while(p!=end) {
00093 CHKBOUNDS(p,return);
00094 *p=c;
00095 p+=xInc;
00096 }
00097 }
00098
00099 if(right<w && bot<h) {
00100 unsigned char * p=img+bot*yInc+right*xInc;
00101 CHKBOUNDS(p,return);
00102 *p=c;
00103 return;
00104 }
00105 }
00106 void Graphics::drawRect(float x, float y, float width, float height) {
00107 unsigned int left,top,right,bot;
00108 getPixelCoordinates(left,top,x,y);
00109 getPixelCoordinates(right,bot,x+width,y+height);
00110 drawRect((int)left,(int)top,(int)(right-left),(int)(bot-top));
00111 }
00112
00113
00114
00115
00116
00117
00118 void Graphics::drawLine(int ix1, int iy1, int ix2, int iy2) {
00119
00120
00121
00122
00123
00124 if(ix1<0 && ix2<0 || iy1<0 && iy2<0 || ix1>=(int)w && ix2>=(int)w || iy1>=(int)h && iy2>=(int)h)
00125 return;
00126
00127 float x1=ix1, y1=iy1, x2=ix2, y2=iy2;
00128 float width=x2-x1;
00129 float height=y2-y1;
00130 bool clipped=false;
00131 if(width!=0) {
00132 float slope=height/width;
00133 if(x1<x2) {
00134 if(x1<0) {
00135 y1-=x1*slope;
00136 x1=0;
00137 clipped=true;
00138 }
00139 if(x2>=w) {
00140 y2-=(x2-(w-1))*slope;
00141 x2=w-1;
00142 clipped=true;
00143 }
00144 } else {
00145 if(x2<0) {
00146 y2-=x2*slope;
00147 x2=0;
00148 clipped=true;
00149 }
00150 if(x1>=w) {
00151 y1-=(x1-(w-1))*slope;
00152 x1=w-1;
00153 clipped=true;
00154 }
00155 }
00156 }
00157 if(clipped) {
00158 if(x1<0 && x2<0 || y1<0 && y2<0 || x1>=w && x2>=w || y1>=h && y2>=h)
00159 return;
00160 clipped=false;
00161 }
00162 if(height!=0) {
00163 float invslope=width/height;
00164 if(y1<y2) {
00165 if(y1<0) {
00166 x1-=y1*invslope;
00167 y1=0;
00168 clipped=true;
00169 }
00170 if(y2>=h) {
00171 x2-=(y2-(h-1))*invslope;
00172 y2=h-1;
00173 clipped=true;
00174 }
00175 } else {
00176 if(y2<0) {
00177 x2-=y2*invslope;
00178 y2=0;
00179 clipped=true;
00180 }
00181 if(y1>=h) {
00182 x1-=(y1-(h-1))*invslope;
00183 y1=h-1;
00184 clipped=true;
00185 }
00186 }
00187 }
00188 if(clipped) {
00189 if(x1<0 && x2<0 || y1<0 && y2<0 || x1>=w && x2>=w || y1>=h && y2>=h)
00190 return;
00191 clipped=false;
00192 }
00193 width=x2-x1;
00194 height=y2-y1;
00195 int aw=abs((int)width);
00196 int ah=abs((int)height);
00197 int d=aw>ah?aw:ah;
00198 float dx=width/d;
00199 float dy=height/d;
00200 for(float x=x1,y=y1;d>0;d--,x+=dx,y+=dy) {
00201 unsigned char * p=(img+((int)y)*yInc+((int)x)*xInc);
00202 CHKBOUNDS(p,continue);
00203 *p=c;
00204 }
00205 unsigned char * p=(img+((int)y2)*yInc+((int)x2)*xInc);
00206 CHKBOUNDS(p,return);
00207 *p=c;
00208 }
00209 void Graphics::drawLine(float x1, float y1, float x2, float y2) {
00210 unsigned int px1,py1,px2,py2;
00211 getPixelCoordinates(px1,py1,x1,y1);
00212 getPixelCoordinates(px2,py2,x2,y2);
00213 drawLine((int)px1,(int)py1,(int)px2,(int)py2);
00214 }
00215
00216 void Graphics::getPixelCoordinates(unsigned int& px, unsigned int& py, float x, float y) const {
00217 if(gen!=NULL) {
00218 gen->getPixelCoordinates(px,py,x,y,genLayer);
00219 } else {
00220
00221 px=(unsigned int)((w-1)*(x+1)/2+.5f);
00222 float aspect=h/(float)w;
00223 py=(unsigned int)((h-1)*(y+aspect)/(aspect*2)+.5f);
00224 }
00225 }
00226
00227 void Graphics::getRealCoordinates(float& x, float& y, unsigned int px, unsigned int py) const {
00228 if(gen!=NULL) {
00229 gen->getRealCoordinates(x,y,px,py,genLayer);
00230 } else {
00231
00232 x=px/(float)(w-1)*2-1;
00233 float aspect=h/(float)w;
00234 y=py/(float)(h-1)*aspect*2-aspect;
00235 }
00236 }
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247