00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "fitshistogram.h"
00019 #include "fitsviewer.h"
00020 #include "fitsimage.h"
00021 #include "indi/fitsrw.h"
00022
00023 #include <math.h>
00024 #include <stdlib.h>
00025
00026 #include <qpainter.h>
00027 #include <qslider.h>
00028 #include <qcursor.h>
00029 #include <qpen.h>
00030 #include <qpixmap.h>
00031 #include <qradiobutton.h>
00032 #include <qpushbutton.h>
00033
00034 #include <kdebug.h>
00035 #include <klineedit.h>
00036 #include <klocale.h>
00037
00038
00039
00040 FITSHistogram::FITSHistogram(QWidget *parent, const char * name) : histDialog(parent, name)
00041 {
00042 viewer = (FITSViewer *) parent;
00043
00044 setModal(false);
00045
00046 minSlider->setMinValue(0);
00047 minSlider->setMaxValue(BARS-1);
00048 minSlider->setValue(0);
00049
00050 maxSlider->setMinValue(0);
00051 maxSlider->setMaxValue(BARS-1);
00052 maxSlider->setValue(BARS-1);
00053
00054 type = 0;
00055 napply=0;
00056
00057 histFrame->setCursor(Qt::CrossCursor);
00058 histFrame->setMouseTracking(true);
00059 setMouseTracking(true);
00060
00061 connect(minSlider, SIGNAL(valueChanged(int)), this, SLOT(updateBoxes()));
00062 connect(minSlider, SIGNAL(valueChanged(int)), this, SLOT(updateIntenFreq(int )));
00063 connect(maxSlider, SIGNAL(valueChanged(int)), this, SLOT(updateBoxes()));
00064 connect(maxSlider, SIGNAL(valueChanged(int)), this, SLOT(updateIntenFreq(int )));
00065 connect(applyB, SIGNAL(clicked()), this, SLOT(applyScale()));
00066
00067 constructHistogram(viewer->imgBuffer);
00068
00069 updateBoxes();
00070
00071 }
00072
00073 FITSHistogram::~FITSHistogram() {}
00074
00075 void FITSHistogram::updateBoxes()
00076 {
00077 if (minSlider->value() == BARS)
00078 minOUT->setText(QString("%1").arg((int) viewer->stats.max));
00079 else
00080 minOUT->setText(QString("%1").arg( (int) ( ceil (minSlider->value() * binSize) + viewer->stats.min)));
00081
00082 if (maxSlider->value() == BARS)
00083 maxOUT->setText(QString("%1").arg((int) viewer->stats.max));
00084 else
00085 maxOUT->setText(QString("%1").arg( (int) ( ceil (maxSlider->value() * binSize) + viewer->stats.min)));
00086
00087 update();
00088 }
00089
00090 void FITSHistogram::applyScale()
00091 {
00092 int swap;
00093 int min = minSlider->value();
00094 int max = maxSlider->value();
00095
00096 FITSHistogramCommand *histC;
00097
00098
00099 if (min > max)
00100 {
00101 swap = min;
00102 min = max;
00103 max = swap;
00104 }
00105
00106 min = (int) (min * binSize + viewer->stats.min);
00107 max = (int) (max * binSize + viewer->stats.min);
00108
00109
00110 napply++;
00111
00112
00113 if (autoR->isOn())
00114 type = 0;
00115
00116 else if (linearR->isOn())
00117 type = 1;
00118
00119 else if (logR->isOn())
00120 type = 2;
00121
00122 else if (sqrtR->isOn())
00123 type = 3;
00124
00125 histC = new FITSHistogramCommand(viewer, this, type, min, max);
00126 viewer->history->addCommand(histC);
00127
00128 }
00129
00130 void FITSHistogram::constructHistogram(float * buffer)
00131 {
00132 int maxHeight = 0;
00133 int height = histFrame->height();
00134 int id;
00135 int index;
00136 int range = (int) (viewer->stats.max - viewer->stats.min);
00137
00138 for (int i=0; i < BARS; i++)
00139 histArray[i] = 0;
00140 binSize = ( (double) range / (double) BARS);
00141
00142
00143 if (binSize == 0 || buffer == NULL)
00144 return;
00145
00146 for (int i=0; i < viewer->stats.width * viewer->stats.height; i++)
00147 {
00148 id = (int) ((buffer[i] - viewer->stats.min) / binSize);
00149 if (id >= BARS) id = BARS - 1;
00150 histArray[id]++;
00151
00152 }
00153
00154 if (binSize < 1)
00155 for (int i=0; i < BARS - 1; i++)
00156 if (histArray[i] == 0)
00157 {
00158 index = (int) ceil(i * binSize);
00159 if (index == (int) (ceil ((i+1) * binSize)))
00160 histArray[i] = histArray[i+1];
00161 }
00162
00163 maxHeight = findMax() / height;
00164
00165 kdDebug() << "Maximum height is " << maxHeight << " -- binsize " << binSize << endl;
00166
00167 histogram = new QPixmap(500, 150, 1);
00168 histogram->fill(Qt::black);
00169 QPainter p(histogram);
00170 QPen pen( white, 1);
00171 p.setPen(pen);
00172
00173 for (int i=0; i < BARS; i++)
00174 p.drawLine(i, height , i, height - (int) ((double) histArray[i] / (double) maxHeight));
00175
00176 }
00177
00178 void FITSHistogram::paintEvent( QPaintEvent *)
00179 {
00180 int height = histFrame->height();
00181 int xMin = minSlider->value(), xMax = maxSlider->value();
00182
00183 QPainter p(histFrame);
00184 QPen pen;
00185 pen.setWidth(1);
00186
00187 bitBlt(histFrame, 0, 0, histogram);
00188
00189 pen.setColor(blue);
00190 p.setPen(pen);
00191
00192 p.drawLine(xMin, height - 2, xMin, height/2 -2);
00193 pen.setColor(red);
00194 p.setPen(pen);
00195 p.drawLine(xMax, 2, xMax, height/2 -2);
00196
00197
00198 }
00199
00200 void FITSHistogram::mouseMoveEvent( QMouseEvent *e)
00201 {
00202 int x = e->x();
00203 int y = e->y();
00204
00205 x -= histFrame->x();
00206 y -= histFrame->y();
00207
00208 if (x < 0 || x >= BARS || y < 0 || y > histFrame->height() )
00209 return;
00210
00211 updateIntenFreq(x);
00212
00213 }
00214
00215 void FITSHistogram::updateIntenFreq(int x)
00216 {
00217
00218 int index = (int) ceil(x * binSize);
00219
00220 intensityOUT->setText(QString("%1").arg((int) ( index + viewer->stats.min)));
00221
00222 frequencyOUT->setText(QString("%1").arg(histArray[x]));
00223
00224 }
00225
00226
00227 int FITSHistogram::findMax()
00228 {
00229 int max =0;
00230
00231 for (int i=0; i < BARS; i++)
00232 if (histArray[i] > max) max = histArray[i];
00233
00234 return max;
00235 }
00236
00237 FITSHistogramCommand::FITSHistogramCommand(QWidget * parent, FITSHistogram *inHisto, int newType, int lmin, int lmax)
00238 {
00239 viewer = (FITSViewer *) parent;
00240 type = newType;
00241 histo = inHisto;
00242 oldImage = new QImage();
00243
00244 buffer = (float *) malloc (viewer->image->width * viewer->image->height * sizeof(float));
00245
00246
00247
00248 min = lmin;
00249 max = lmax;
00250 }
00251
00252 FITSHistogramCommand::~FITSHistogramCommand()
00253 {
00254 free(buffer);
00255 delete (oldImage);
00256 }
00257
00258 void FITSHistogramCommand::execute()
00259 {
00260 float val, bufferVal;
00261 double coeff;
00262 FITSImage *image = viewer->image;
00263 int width = image->width;
00264 int height = image->height;
00265
00266 memcpy(buffer, viewer->imgBuffer,image->width * image->height * sizeof(float));
00267 *oldImage = image->displayImage->copy();
00268
00269 switch (type)
00270 {
00271 case FITSImage::FITSAuto:
00272 case FITSImage::FITSLinear:
00273 for (int i=0; i < height; i++)
00274 for (int j=0; j < width; j++)
00275 {
00276 bufferVal = viewer->imgBuffer[i * width + j];
00277 if (bufferVal < min) bufferVal = min;
00278 else if (bufferVal > max) bufferVal = max;
00279
00280
00281
00282
00283
00284
00285 viewer->imgBuffer[i * width + j] = bufferVal;
00286
00287 }
00288 break;
00289
00290 case FITSImage::FITSLog:
00291
00292 coeff = max / log(1 + max);
00293
00294 for (int i=0; i < height; i++)
00295 for (int j=0; j < width; j++)
00296 {
00297 bufferVal = viewer->imgBuffer[i * width + j];
00298 if (bufferVal < min) bufferVal = min;
00299 else if (bufferVal > max) bufferVal = max;
00300 val = (coeff * log(1 + bufferVal));
00301 if (val < min) val = min;
00302 else if (val > max) val = max;
00303 viewer->imgBuffer[i * width + j] = val;
00304
00305
00306 }
00307 break;
00308
00309 case FITSImage::FITSSqrt:
00310
00311 coeff = max / sqrt(max);
00312
00313 for (int i=0; i < height; i++)
00314 for (int j=0; j < width; j++)
00315 {
00316 bufferVal = (int) viewer->imgBuffer[i * width + j];
00317 if (bufferVal < min) bufferVal = min;
00318 else if (bufferVal > max) bufferVal = max;
00319 val = (int) (coeff * sqrt(bufferVal));
00320
00321 viewer->imgBuffer[i * width + j] = val;
00322
00323 }
00324
00325 break;
00326
00327
00328 default:
00329 break;
00330 }
00331
00332
00333 float lmin= viewer->imgBuffer[0];
00334 float lmax= viewer->imgBuffer[0];
00335 int totalPix = width * height;
00336
00337 for (int i=1; i < totalPix; i++)
00338
00339 if ( viewer->imgBuffer[i] < lmin) lmin = viewer->imgBuffer[i];
00340 else if (viewer->imgBuffer[i] > lmax) lmax = viewer->imgBuffer[i];
00341
00342 double datadiff = 255.;
00343 double pixdiff = lmax - lmin;
00344 double offs = -lmin * datadiff / pixdiff;
00345 double scale = datadiff / pixdiff;
00346 int tdata = 0;
00347
00348
00349 for (int i=0; i < height; i++)
00350 for (int j=0; j < width; j++)
00351 {
00352
00353
00354 tdata = (long) (viewer->imgBuffer[i * width + j] * scale + offs);
00355 if (tdata < 0) tdata = 0;
00356 else if (tdata > 255) tdata = 255;
00357 image->displayImage->setPixel(j, height - i - 1, tdata);
00358 }
00359
00360 viewer->calculateStats();
00361
00362
00363 if (histo != NULL)
00364 {
00365 histo->constructHistogram(viewer->imgBuffer);
00366 histo->update();
00367 histo->updateBoxes();
00368 }
00369
00370 viewer->image->zoomToCurrent();
00371 viewer->fitsChange();
00372
00373 }
00374
00375 void FITSHistogramCommand::unexecute()
00376 {
00377 memcpy( viewer->imgBuffer, buffer, viewer->image->width * viewer->image->height * sizeof(float));
00378 viewer->calculateStats();
00379 *viewer->image->displayImage = oldImage->copy();
00380 viewer->image->zoomToCurrent();
00381
00382 if (histo != NULL)
00383 {
00384 histo->constructHistogram(viewer->imgBuffer);
00385 histo->update();
00386 histo->updateBoxes();
00387 }
00388 }
00389
00390 QString FITSHistogramCommand::name() const
00391 {
00392
00393 switch (type)
00394 {
00395 case 0:
00396 return i18n("Auto Scale");
00397 break;
00398 case 1:
00399 return i18n("Linear Scale");
00400 break;
00401 case 2:
00402 return i18n("Logarithmic Scale");
00403 break;
00404 case 3:
00405 return i18n("Square Root Scale");
00406 break;
00407 default:
00408 break;
00409 }
00410
00411 return i18n("Unknown");
00412
00413 }
00414
00415
00416
00417
00418
00419 #include "fitshistogram.moc"