You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
420 lines
11 KiB
420 lines
11 KiB
/***************************************************************************
|
|
fitshistogram.cpp - FITS Historgram
|
|
-----------------
|
|
begin : Thu Mar 4th 2004
|
|
copyright : (C) 2004 by Jasem Mutlaq
|
|
email : mutlaqja@ikarustech.com
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "fitshistogram.h"
|
|
#include "fitsviewer.h"
|
|
#include "fitsimage.h"
|
|
#include "indi/fitsrw.h"
|
|
|
|
#include <math.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <tqpainter.h>
|
|
#include <tqslider.h>
|
|
#include <tqcursor.h>
|
|
#include <tqpen.h>
|
|
#include <tqpixmap.h>
|
|
#include <tqradiobutton.h>
|
|
#include <tqpushbutton.h>
|
|
|
|
#include <kdebug.h>
|
|
#include <klineedit.h>
|
|
#include <tdelocale.h>
|
|
|
|
|
|
|
|
FITSHistogram::FITSHistogram(TQWidget *parent, const char * name) : histDialog(parent, name)
|
|
{
|
|
viewer = (FITSViewer *) parent;
|
|
|
|
setModal(false);
|
|
|
|
minSlider->setMinValue(0);
|
|
minSlider->setMaxValue(BARS-1);
|
|
minSlider->setValue(0);
|
|
|
|
maxSlider->setMinValue(0);
|
|
maxSlider->setMaxValue(BARS-1);
|
|
maxSlider->setValue(BARS-1);
|
|
|
|
type = 0;
|
|
napply=0;
|
|
|
|
histFrame->setCursor(TQt::CrossCursor);
|
|
histFrame->setMouseTracking(true);
|
|
setMouseTracking(true);
|
|
|
|
connect(minSlider, TQ_SIGNAL(valueChanged(int)), this, TQ_SLOT(updateBoxes()));
|
|
connect(minSlider, TQ_SIGNAL(valueChanged(int)), this, TQ_SLOT(updateIntenFreq(int )));
|
|
connect(maxSlider, TQ_SIGNAL(valueChanged(int)), this, TQ_SLOT(updateBoxes()));
|
|
connect(maxSlider, TQ_SIGNAL(valueChanged(int)), this, TQ_SLOT(updateIntenFreq(int )));
|
|
connect(applyB, TQ_SIGNAL(clicked()), this, TQ_SLOT(applyScale()));
|
|
|
|
constructHistogram(viewer->imgBuffer);
|
|
|
|
updateBoxes();
|
|
|
|
}
|
|
|
|
FITSHistogram::~FITSHistogram() {}
|
|
|
|
void FITSHistogram::updateBoxes()
|
|
{
|
|
if (minSlider->value() == BARS)
|
|
minOUT->setText(TQString("%1").arg((int) viewer->stats.max));
|
|
else
|
|
minOUT->setText(TQString("%1").arg( (int) ( ceil (minSlider->value() * binSize) + viewer->stats.min)));
|
|
|
|
if (maxSlider->value() == BARS)
|
|
maxOUT->setText(TQString("%1").arg((int) viewer->stats.max));
|
|
else
|
|
maxOUT->setText(TQString("%1").arg( (int) ( ceil (maxSlider->value() * binSize) + viewer->stats.min)));
|
|
|
|
update();
|
|
}
|
|
|
|
void FITSHistogram::applyScale()
|
|
{
|
|
int swap;
|
|
int min = minSlider->value();
|
|
int max = maxSlider->value();
|
|
|
|
FITSHistogramCommand *histC;
|
|
//kdDebug() << "Width " << viewer->image->width << endl;
|
|
|
|
if (min > max)
|
|
{
|
|
swap = min;
|
|
min = max;
|
|
max = swap;
|
|
}
|
|
|
|
min = (int) (min * binSize + viewer->stats.min);
|
|
max = (int) (max * binSize + viewer->stats.min);
|
|
|
|
|
|
napply++;
|
|
|
|
// Auto
|
|
if (autoR->isOn())
|
|
type = 0;
|
|
// Linear
|
|
else if (linearR->isOn())
|
|
type = 1;
|
|
// Log
|
|
else if (logR->isOn())
|
|
type = 2;
|
|
// Exp
|
|
else if (sqrtR->isOn())
|
|
type = 3;
|
|
|
|
histC = new FITSHistogramCommand(viewer, this, type, min, max);
|
|
viewer->history->addCommand(histC);
|
|
|
|
}
|
|
|
|
void FITSHistogram::constructHistogram(float * buffer)
|
|
{
|
|
int maxHeight = 0;
|
|
int height = histFrame->height();
|
|
int id;
|
|
int index;
|
|
int range = (int) (viewer->stats.max - viewer->stats.min);
|
|
|
|
for (int i=0; i < BARS; i++)
|
|
histArray[i] = 0;
|
|
binSize = ( (double) range / (double) BARS);
|
|
|
|
//kdDebug() << "#2" << endl;
|
|
if (binSize == 0 || buffer == NULL)
|
|
return;
|
|
|
|
for (int i=0; i < viewer->stats.width * viewer->stats.height; i++)
|
|
{
|
|
id = (int) ((buffer[i] - viewer->stats.min) / binSize);
|
|
if (id >= BARS) id = BARS - 1;
|
|
histArray[id]++;
|
|
|
|
}
|
|
|
|
if (binSize < 1)
|
|
for (int i=0; i < BARS - 1; i++)
|
|
if (histArray[i] == 0)
|
|
{
|
|
index = (int) ceil(i * binSize);
|
|
if (index == (int) (ceil ((i+1) * binSize)))
|
|
histArray[i] = histArray[i+1];
|
|
}
|
|
|
|
maxHeight = findMax() / height;
|
|
|
|
kdDebug() << "Maximum height is " << maxHeight << " -- binsize " << binSize << endl;
|
|
|
|
histogram = new TQPixmap(500, 150, 1);
|
|
histogram->fill(TQt::black);
|
|
TQPainter p(histogram);
|
|
TQPen pen( white, 1);
|
|
p.setPen(pen);
|
|
|
|
for (int i=0; i < BARS; i++)
|
|
p.drawLine(i, height , i, height - (int) ((double) histArray[i] / (double) maxHeight));
|
|
|
|
}
|
|
|
|
void FITSHistogram::paintEvent( TQPaintEvent */*e*/)
|
|
{
|
|
int height = histFrame->height();
|
|
int xMin = minSlider->value(), xMax = maxSlider->value();
|
|
|
|
TQPainter p(histFrame);
|
|
TQPen pen;
|
|
pen.setWidth(1);
|
|
|
|
bitBlt(histFrame, 0, 0, histogram);
|
|
|
|
pen.setColor(blue);
|
|
p.setPen(pen);
|
|
|
|
p.drawLine(xMin, height - 2, xMin, height/2 -2);
|
|
pen.setColor(red);
|
|
p.setPen(pen);
|
|
p.drawLine(xMax, 2, xMax, height/2 -2);
|
|
|
|
|
|
}
|
|
|
|
void FITSHistogram::mouseMoveEvent( TQMouseEvent *e)
|
|
{
|
|
int x = e->x();
|
|
int y = e->y();
|
|
|
|
x -= histFrame->x();
|
|
y -= histFrame->y();
|
|
|
|
if (x < 0 || x >= BARS || y < 0 || y > histFrame->height() )
|
|
return;
|
|
|
|
updateIntenFreq(x);
|
|
|
|
}
|
|
|
|
void FITSHistogram::updateIntenFreq(int x)
|
|
{
|
|
|
|
int index = (int) ceil(x * binSize);
|
|
|
|
intensityOUT->setText(TQString("%1").arg((int) ( index + viewer->stats.min)));
|
|
|
|
frequencyOUT->setText(TQString("%1").arg(histArray[x]));
|
|
|
|
}
|
|
|
|
|
|
int FITSHistogram::findMax()
|
|
{
|
|
int max =0;
|
|
|
|
for (int i=0; i < BARS; i++)
|
|
if (histArray[i] > max) max = histArray[i];
|
|
|
|
return max;
|
|
}
|
|
|
|
FITSHistogramCommand::FITSHistogramCommand(TQWidget * parent, FITSHistogram *inHisto, int newType, int lmin, int lmax)
|
|
{
|
|
viewer = (FITSViewer *) parent;
|
|
type = newType;
|
|
histo = inHisto;
|
|
oldImage = new TQImage();
|
|
// TODO apply maximum compression against this buffer
|
|
buffer = (float *) malloc (viewer->image->width * viewer->image->height * sizeof(float));
|
|
|
|
//if (buffer == NULL)
|
|
//return;
|
|
min = lmin;
|
|
max = lmax;
|
|
}
|
|
|
|
FITSHistogramCommand::~FITSHistogramCommand()
|
|
{
|
|
free(buffer);
|
|
delete (oldImage);
|
|
}
|
|
|
|
void FITSHistogramCommand::execute()
|
|
{
|
|
float val, bufferVal;
|
|
double coeff;
|
|
FITSImage *image = viewer->image;
|
|
int width = image->width;
|
|
int height = image->height;
|
|
|
|
memcpy(buffer, viewer->imgBuffer,image->width * image->height * sizeof(float));
|
|
*oldImage = image->displayImage->copy();
|
|
|
|
switch (type)
|
|
{
|
|
case FITSImage::FITSAuto:
|
|
case FITSImage::FITSLinear:
|
|
for (int i=0; i < height; i++)
|
|
for (int j=0; j < width; j++)
|
|
{
|
|
bufferVal = viewer->imgBuffer[i * width + j];
|
|
if (bufferVal < min) bufferVal = min;
|
|
else if (bufferVal > max) bufferVal = max;
|
|
//val = (int) (255. * ((double) (bufferVal - min) / (double) (max - min)));
|
|
//val = (int) (max * ((double) (bufferVal - min) / (double) (max - min)));
|
|
//val = (int) (bufferVal - min) * (max - min) + min;
|
|
//if (val < min) val = min;
|
|
//else if (val > max) val = max;
|
|
//image->reducedImgBuffer[i * width + j] = val;
|
|
viewer->imgBuffer[i * width + j] = bufferVal;
|
|
|
|
}
|
|
break;
|
|
|
|
case FITSImage::FITSLog:
|
|
//coeff = 255. / log(1 + max);
|
|
coeff = max / log(1 + max);
|
|
|
|
for (int i=0; i < height; i++)
|
|
for (int j=0; j < width; j++)
|
|
{
|
|
bufferVal = viewer->imgBuffer[i * width + j];
|
|
if (bufferVal < min) bufferVal = min;
|
|
else if (bufferVal > max) bufferVal = max;
|
|
val = (coeff * log(1 + bufferVal));
|
|
if (val < min) val = min;
|
|
else if (val > max) val = max;
|
|
viewer->imgBuffer[i * width + j] = val;
|
|
//image->reducedImgBuffer[i * width + j] = val;
|
|
//displayImage->setPixel(j, height - i - 1, val);
|
|
}
|
|
break;
|
|
|
|
case FITSImage::FITSSqrt:
|
|
//coeff = 255. / sqrt(max);
|
|
coeff = max / sqrt(max);
|
|
|
|
for (int i=0; i < height; i++)
|
|
for (int j=0; j < width; j++)
|
|
{
|
|
bufferVal = (int) viewer->imgBuffer[i * width + j];
|
|
if (bufferVal < min) bufferVal = min;
|
|
else if (bufferVal > max) bufferVal = max;
|
|
val = (int) (coeff * sqrt(bufferVal));
|
|
//image->reducedImgBuffer[i * width + j] = val;
|
|
viewer->imgBuffer[i * width + j] = val;
|
|
//displayImage->setPixel(j, height - i - 1, val);
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
//int lmin= image->reducedImgBuffer[0];
|
|
float lmin= viewer->imgBuffer[0];
|
|
float lmax= viewer->imgBuffer[0];
|
|
int totalPix = width * height;
|
|
|
|
for (int i=1; i < totalPix; i++)
|
|
//if ( image->reducedImgBuffer[i] < lmin) lmin = image->reducedImgBuffer[i];
|
|
if ( viewer->imgBuffer[i] < lmin) lmin = viewer->imgBuffer[i];
|
|
else if (viewer->imgBuffer[i] > lmax) lmax = viewer->imgBuffer[i];
|
|
|
|
double datadiff = 255.;
|
|
double pixdiff = lmax - lmin;
|
|
double offs = -lmin * datadiff / pixdiff;
|
|
double scale = datadiff / pixdiff;
|
|
int tdata = 0;
|
|
|
|
|
|
for (int i=0; i < height; i++)
|
|
for (int j=0; j < width; j++)
|
|
{
|
|
//bp8 = (FITS_BITPIX8) image->reducedImgBuffer[i * width + j];
|
|
//bp8 = (FITS_BITPIX8)
|
|
tdata = (long) (viewer->imgBuffer[i * width + j] * scale + offs);
|
|
if (tdata < 0) tdata = 0;
|
|
else if (tdata > 255) tdata = 255;
|
|
image->displayImage->setPixel(j, height - i - 1, tdata);
|
|
}
|
|
|
|
viewer->calculateStats();
|
|
|
|
//viewer->updateImgBuffer();
|
|
if (histo != NULL)
|
|
{
|
|
histo->constructHistogram(viewer->imgBuffer);
|
|
histo->update();
|
|
histo->updateBoxes();
|
|
}
|
|
|
|
viewer->image->zoomToCurrent();
|
|
viewer->fitsChange();
|
|
|
|
}
|
|
|
|
void FITSHistogramCommand::unexecute()
|
|
{
|
|
memcpy( viewer->imgBuffer, buffer, viewer->image->width * viewer->image->height * sizeof(float));
|
|
viewer->calculateStats();
|
|
*viewer->image->displayImage = oldImage->copy();
|
|
viewer->image->zoomToCurrent();
|
|
|
|
if (histo != NULL)
|
|
{
|
|
histo->constructHistogram(viewer->imgBuffer);
|
|
histo->update();
|
|
histo->updateBoxes();
|
|
}
|
|
}
|
|
|
|
TQString FITSHistogramCommand::name() const
|
|
{
|
|
|
|
switch (type)
|
|
{
|
|
case 0:
|
|
return i18n("Auto Scale");
|
|
break;
|
|
case 1:
|
|
return i18n("Linear Scale");
|
|
break;
|
|
case 2:
|
|
return i18n("Logarithmic Scale");
|
|
break;
|
|
case 3:
|
|
return i18n("Square Root Scale");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return i18n("Unknown");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#include "fitshistogram.moc"
|