image.cpp

Go to the documentation of this file.
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   // draw the axes
00172   /*  if (draw_axes)
00173     {
00174       int xs = width_direct();
00175       int ys = height_direct();
00176       for(double x = -1.0 ; x <= 1.0 ; x+=0.1)
00177         for(double y = -1.0 ; y <= 1.0 ; y+=0.1)
00178           {
00179             DirectPoint dp=ocsToDcs(PointValue(x,y));
00180             if (dp.y>=0 && dp.y<ys)
00181               {
00182                 QRgb * scanline = (QRgb*)result.scanLine(dp.y);
00183                 int delta = axe_fatiness(y);
00184                 for(int x = 0 ; x < xs ; x+=delta) scanline[x]=qRgb(0,0,0);
00185               }
00186             if (dp.x>=0 && dp.x<xs)
00187               {
00188                 int delta = axe_fatiness(x);
00189                 for(int y = 0 ; y < ys ; y+=delta) 
00190                   {
00191                     QRgb * scanline = (QRgb*)result.scanLine(y);
00192                     scanline[dp.x]=qRgb(0,0,0);
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   // calculate the size of a pixel in the paintdevice
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         // dp refers to the position in the image
00243         int a = pixel_width  + dp.x*as/xs;
00244         int b = pixel_height + dp.y*bs/ys;
00245         // a and b now refers to the coordinate in the paintdevice
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   // now we need to print the extrema
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       //      printf("Ranging from %g to %g step %g\n",i->left(),i->right(),horiz());
00394       // we calculate the top left direct coordinate and bottom right direct coordinate
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 

Generated on Mon Jun 5 22:08:42 2006 for iis by  doxygen 1.4.6