00001 #include <qpainter.h>
00002 #include <qfiledialog.h>
00003 #include "runtime.h"
00004 #include "text.h"
00005 #include "image.h"
00006
00007 Data ImageValue::getSaveDescription(QString prefix)
00008 {
00009 QString fn = prefix+"."+QString::number((ulong)(void*)this)+".dat";
00010 DataBinner::write(data,fn);
00011 Token T;
00012 T["type"]= Symbol("image");
00013 T["filename"]=String(fn);
00014 T["center"]=center.getSaveDescription();
00015 T["scale"]=scale.getSaveDescription(prefix);
00016 return T;
00017 };
00018
00019 ImageValue::ImageValue(Token desc) : Value()
00020 {
00021 String filename = desc["filename"];
00022 QString fn = filename;
00023 data = DataBinner::read_file(fn);
00024 center = DirectPoint(desc["center"]);
00025 scale = PointValue(desc["scale"]);
00026 }
00027
00028 ImageValue::ImageValue(int xs, int ys, int c) : data(c,xs,ys)
00029 {
00030 center.x = xs / 2;
00031 center.y = ys / 2;
00032 scale.y = scale.x = max(xs,ys)/2.0;
00033 }
00034
00035 ImageValue * ImageValue::deepCopy()
00036 {
00037 int xs = width_direct();
00038 int ys = height_direct();
00039 int cs = channelcount();
00040 ImageValue * result= new ImageValue(width_direct(),height_direct(),channelcount());
00041 for(int c = 0 ; c < cs ; c ++)
00042 for(int x = 0 ; x < xs ; x++)
00043 for(int y = 0 ; y < ys ; y++)
00044 result->set_direct(x,y,c,
00045 get_direct(x,y,c));
00046 result->center = center;
00047 result->scale = scale;
00048 return result;
00049 }
00050
00051 ImageValue::ImageValue(PointValue tl, PointValue br, PointValue res, int c)
00052 : data(c,(int)((br.x-tl.x)*res.x),(int)((br.y-tl.y)*res.y)),
00053 scale(res)
00054 {
00055 center.x = (-tl.x)*scale.x;
00056 center.y = (-tl.y)*scale.y;
00057 }
00058
00059 ImageValue::ImageValue(QImage &i) : Value()
00060 {
00061 loadImage(i);
00062 };
00063
00064 ImageValue::ImageValue(QString str) : Value()
00065 {
00066 loadImage(str);
00067 };
00068
00069 void ImageValue::loadImage(QString str)
00070 {
00071 QImage i(str);
00072 loadImage(i);
00073 }
00074
00075 bool ImageValue::equals_same_type(Value * other)
00076 {
00077 ImageValue * o = (ImageValue*)other;
00078 return (data == o->data)
00079 && (center == o->center)
00080 && (scale.equals(o->scale));
00081 };
00082
00088 void ImageValue::loadImage(QImage&I1)
00089 {
00090 QImage I=I1.convertDepth(32);
00091 bool gray = I.isGrayscale();
00092 int w = I.width();
00093 int h = I.height();
00094 center.x = w / 2;
00095 center.y = h / 2;
00096 scale.y = scale.x = max(w,h)/2.0;
00097 data = Image(gray ? 1 : 3,I.width(),I.height());
00098 if (gray)
00099 for(Image::positions pos(data); pos.more() ; ++pos)
00100 {
00101 QRgb G = I.pixel(pos[imagex],pos[imagey]);
00102 pos=qGray(G);
00103 }
00104 else
00105 for(Image::vector_positions pos(data,imagex,imagey); pos.more() ; ++pos)
00106 {
00107 QRgb G = I.pixel(pos[imagex],pos[imagey]);
00108 Image::vector & v=pos;
00109 v[0]=qRed(G);
00110 v[1]=qGreen(G);
00111 v[2]=qBlue(G);
00112 }
00113 }
00114
00115 int axe_fatiness(double x)
00116 {
00117 if (x<1.01 && x>0.99) return 3;
00118 if (x>-1.01 && x<-0.99) return 3;
00119 if (x>-0.01 && x<0.01) return 1;
00120 return 2;
00121 }
00122
00123 QImage ImageValue::getQImage(bool draw_axes)
00124 {
00125 double loz = minz();
00126 double hiz = maxz();
00127 double diz = hiz-loz;
00128 if (diz==0) diz=1;
00129 QImage result(data.size(imagex),data.size(imagey),32);
00130 if (data.size(channels)==1)
00131 for(Image::matrix_positions pos(data,imagey); pos.more() ; ++pos)
00132 {
00133 QRgb * scanline = (QRgb*)result.scanLine(pos[imagey]);
00134 for(ColorLine::ordered_vectors xy(pos,colorlinex); xy.more() ; ++xy, ++scanline)
00135 {
00136 Image::value g = xy;
00137 g-=loz;
00138 g/=diz;
00139 g*=255.0;
00140 *scanline=qRgb((int)g,(int)g,(int)g);
00141 }
00142 }
00143 else
00144 for(Image::matrix_positions y(data,imagey); y.more() ; ++y)
00145 {
00146 QRgb * scanline = (QRgb*)result.scanLine(y[imagey]);
00147 for(ColorLine::ordered_vectors xy(y,colorlinex); xy.more() ; ++xy, ++scanline)
00148 {
00149 Image::vector &c = xy;
00150 float r = c[0];
00151 float g = c[1];
00152 float b = c[2];
00153
00154 r-=loz;
00155 r/=diz;
00156 r*=255.0;
00157
00158 g-=loz;
00159 g/=diz;
00160 g*=255.0;
00161
00162 b-=loz;
00163 b/=diz;
00164 b*=255.0;
00165
00166 int R = (int)r, G = (int)g, B = (int)b;
00167 *scanline=qRgb(R,G,B);
00168 }
00169 }
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199 return result;
00200 }
00201
00202 void ImageValue::drawAxes(QImage *onto)
00203 {
00204 int as = onto->width();
00205 int bs = onto->height();
00206 int xs = width_direct();
00207 int ys = height_direct();
00208
00209 QPen central(Qt::red);
00210 central.setStyle(Qt::SolidLine);
00211
00212 QPen sides(Qt::blue);
00213 sides.setStyle(Qt::SolidLine);
00214
00215 QPen units(Qt::red);
00216 units.setStyle(Qt::DashLine);
00217
00218 double dx,dy;
00219 if (as<100 || bs<100)
00220 {
00221 dx = 1.0;
00222 dy = 1.0;
00223 }
00224 else
00225 {
00226 dx = 0.1;
00227 dy = 0.1;
00228 }
00229
00230
00231 double pixel_width = (double)as/(double)xs;
00232 double pixel_height = (double)bs/(double)ys;
00233 pixel_width/=2;
00234 pixel_height/=2;
00235 pixel_width+=0.5;
00236 pixel_height+=0.5;
00237 QRgb c;
00238 for(double x = -10.0 ; x <= 10.0 ; x+=dx)
00239 for(double y = -10.0 ; y <= 10.0 ; y+=dy)
00240 {
00241 DirectPoint dp=ocsToDcs(PointValue(x,y));
00242
00243 int a = pixel_width + dp.x*as/xs;
00244 int b = pixel_height + dp.y*bs/ys;
00245
00246 if (a>=0 && a<as)
00247 {
00248 int s = axe_fatiness(x);
00249 if (s==1) c = qRgb(255,0,0);
00250 else if (s==2) c = qRgb(0,0,255);
00251 else c = qRgb(255,128,128);
00252
00253 for(int y = 0 ; y < bs ; y++)
00254 {
00255 QRgb * scanline = (QRgb*)onto->scanLine(y);
00256 scanline[a]=c;
00257 }
00258 }
00259
00260 if (b>=0 && b<bs)
00261 {
00262 int s = axe_fatiness(y);
00263 if (s==1) c = qRgb(255,0,0);
00264 else if (s==2) c = qRgb(0,0,255);
00265 else c = qRgb(255,128,128);
00266
00267 QRgb * scanline = (QRgb*)onto->scanLine(b);
00268 for(int x = 0 ; x < as ; x++)
00269 scanline[x]=c;
00270 }
00271 }
00272 }
00273
00274 void ImageValue::drawLegend(QPainter * painter, int as, int bs)
00275 {
00276
00277 QString hi = QString("max: ")+QString::number(maxz());
00278 QString lo = QString("min: ")+QString::number(minz());
00279 QString me = QString("median: ")+QString::number(medianz());
00280 QString t = hi+"\n"+me+"\n"+lo;
00281 QRect bounds =
00282 painter->boundingRect(0,0,640,480,Qt::AlignBottom|Qt::AlignLeft,t);
00283 if (bounds.width()>as ||
00284 bounds.height()>bs/4) return;
00285 painter->setPen(Qt::white);
00286 painter->drawText(2,-2,as,bs,Qt::AlignBottom|Qt::AlignLeft,t);
00287 painter->setPen(Qt::black);
00288 painter->drawText(0,0,as,bs,Qt::AlignBottom|Qt::AlignLeft,t);
00289 }
00290
00291 double ImageValue::maxz()
00292 {
00293 if (data.empty()) return 0;
00294 double mz = get_direct(0,0,0);
00295 for(Image::values v(data); v.more(); ++v)
00296 if (v>mz) mz=v;
00297 return mz;
00298 }
00299
00300 double ImageValue::minz()
00301 {
00302 if (data.empty()) return 0;
00303 double mz = get_direct(0,0,0);
00304 for(Image::values v(data); v.more(); ++v)
00305 if (v<mz) mz=v;
00306 return mz;
00307 }
00308
00309 int float_cmp(const void * a , const void * b)
00310 {
00311 float * A = (float*)a;
00312 float * B = (float*)b;
00313 float c = *A;
00314 float d = *B;
00315 if (c<d) return -1;
00316 if (c>d) return 1;
00317 return 0;
00318 }
00319
00320 double ImageValue::medianz()
00321 {
00322 if (data.empty()) return 0;
00323 int size = width_direct()*height_direct()*channelcount();
00324 float * sort = (float*)malloc(sizeof(float)*size);
00325 assert(sort);
00326 int p = 0;
00327 for(Image::values it(data) ; it.more(); it++)
00328 sort[p++]=*it;
00329 qsort(sort,size,sizeof(float),float_cmp);
00330 float result = sort[size/2];
00331 free(sort);
00332 return result;
00333 }
00334
00335 Value * Runtime::image(QString filename)
00336 {
00337 return new ImageValue(filename);
00338 }
00339
00340 Value * Runtime::image(Value * what)
00341 {
00342 if (what==NULL) return NULL;
00343 if (typeid(*what)!=typeid(TextValue)) return NULL;
00344 TextValue * t = (TextValue*)what;
00345 return image(t->getText());
00346 }
00347
00348 Value * Runtime::image()
00349 {
00350 QString s = QFileDialog::getOpenFileName(".",
00351 "Images (*.png *.xpm *.jpg)",
00352 NULL,
00353 "Select file to open",
00354 "Choose a file");
00355 if(s.isEmpty()) return NULL;
00356 return image(s);
00357 }
00358
00359 Value * Runtime::image(vector<Value*> v)
00360 {
00361 if (v.size()==0) return image();
00362 if (v.size()==1) return image(v[0]);
00363 return NULL;
00364 }
00365
00366 DirectPoint ImageValue::ocsToDcs(const PointValue& in)
00367 {
00368 DirectPoint out;
00369 out.copyFrom(in * scale);
00370 out+=center;
00371 return out;
00372 }
00373
00374 PointValue ImageValue::dcsToOcs(const DirectPoint& in)
00375 {
00376 PointValue out=(PointValue)(in-center);
00377 out/=scale;
00378 return out;
00379 }
00380
00381 void ImageValue::negate()
00382 {
00383 for(Image::values it(data); it.more() ; it++)
00384 *it = -it;
00385 }
00386
00387 void ImageValue::addFrom(ImageValue * i)
00388 {
00389 int c1 = channelcount();
00390 int c2 = i->channelcount();
00391 if (c1==c2)
00392 {
00393
00394
00395 DirectPoint tl = ocsToDcs(i->topleft());
00396 DirectPoint br = ocsToDcs(i->bottomright());
00397 DirectPoint cr = tl;
00398 for(cr.x=tl.x; cr.x <= br.x ; cr.x++)
00399 for(cr.y=tl.y ; cr.y <= br.y ; cr.y++)
00400 {
00401 DirectPoint from = i->ocsToDcs(dcsToOcs(cr));
00402 if (!outside(cr) && !i->outside(from))
00403 for(int c = 0 ; c < c1 ; c++)
00404 {
00405 double v1 = get_direct(cr.x,cr.y,c);
00406 double v2 = i->get_direct(from.x,from.y,c);
00407 set_direct(cr.x,cr.y,c,v1+v2);
00408 }
00409 }
00410 }
00411 else
00412 assert(0);
00413 }
00414