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.
tdeedu/kstars/kstars/fitsviewer.cpp

1010 lines
28 KiB

/***************************************************************************
FITSViewer.cpp - A FITSViewer for KStars
-------------------
begin : Thu Jan 22 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. *
* *
* Some code fragments were adapted from Peter Kirchgessner's FITS plugin*
* See http://members.aol.com/pkirchg for more details. *
***************************************************************************/
#include <tdelocale.h>
#include <tdemessagebox.h>
#include <tdefiledialog.h>
#include <tdeaction.h>
#include <tdeaccel.h>
#include <kdebug.h>
#include <tdetoolbar.h>
#include <tdeapplication.h>
#include <kpixmap.h>
#include <tdetempfile.h>
#include <kimageeffect.h>
#include <tdemenubar.h>
#include <kprogress.h>
#include <kstatusbar.h>
#include <kcommand.h>
#include <klineedit.h>
#include <tdelistview.h>
#include <tqfile.h>
#include <tqvbox.h>
#include <tqcursor.h>
#include <tqstringlist.h>
#include <tqlistview.h>
#include <tqradiobutton.h>
#include <tqclipboard.h>
#include <tqimage.h>
#include <math.h>
#include <unistd.h>
#include <stdlib.h>
#include <netinet/in.h>
#include "fitsviewer.h"
#include "fitsimage.h"
#include "fitsprocess.h"
#include "fitshistogram.h"
#include "conbridlg.h"
#include "statform.h"
#include "imagereductiondlg.h"
#include "fitsheaderdialog.h"
#include "ksutils.h"
#include "Options.h"
extern int fits_ieee32_intel;
extern int fits_ieee32_motorola;
extern int fits_ieee64_intel;
extern int fits_ieee64_motorola;
#define FITS_GETBITPIX16(p,val) val = ((p[0] << 8) | (p[1]))
#define FITS_GETBITPIX32(p,val) val = \
((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3])
#define FITS_GETBITPIXM32(p,val) \
{ if (fits_ieee32_intel) {unsigned char uc[4]; \
uc[0] = p[3]; uc[1] = p[2]; uc[2] = p[1]; uc[3] = p[0]; \
val = *(FITS_BITPIXM32 *)uc; } \
else if (fits_ieee32_motorola) { val = *(FITS_BITPIXM32 *)p; } \
else if (fits_ieee64_motorola) {FITS_BITPIXM64 m64; \
unsigned char *uc= (unsigned char *)&m64; \
uc[0]=p[0]; uc[1]=p[1]; uc[2]=p[2]; uc[3]=p[3]; uc[4]=uc[5]=uc[6]=uc[7]=0; \
val = (FITS_BITPIXM32)m64; } \
else if (fits_ieee64_intel) {FITS_BITPIXM64 i64; \
unsigned char *uc= (unsigned char *)&i64; \
uc[0]=uc[1]=uc[2]=uc[3]=0; uc[7]=p[3]; uc[6]=p[2]; uc[5]=p[1]; uc[4]=p[0]; \
val = (FITS_BITPIXM32)i64;}\
}
#define FITS_GETBITPIXM64(p,val) \
{ if (fits_ieee64_intel) {unsigned char uc[8]; \
uc[0] = p[7]; uc[1] = p[6]; uc[2] = p[5]; uc[3] = p[4]; \
uc[4] = p[3]; uc[5] = p[2]; uc[6] = p[1]; uc[7] = p[0]; \
val = *(FITS_BITPIXM64 *)uc; } else val = *(FITS_BITPIXM64 *)p; }
FITSViewer::FITSViewer (const KURL *url, TQWidget *parent, const char *name)
: TDEMainWindow (parent, name)
{
image = NULL;
currentURL = *url;
imgBuffer = NULL;
histo = NULL;
Dirty = 0;
/* Initiliaze menu actions */
history = new KCommandHistory(actionCollection());
history->setUndoLimit(10);
history->setRedoLimit(10);
history->documentSaved();
connect(history, TQT_SIGNAL(documentRestored()), this, TQT_SLOT(fitsRestore()));
/* Setup image widget */
image = new FITSImage(this);
setCentralWidget(image);
statusBar()->insertItem("", 0);
statusBar()->setItemFixed(0, 100);
statusBar()->insertItem("", 1);
statusBar()->setItemFixed(1, 100);
statusBar()->insertItem("", 2);
statusBar()->setItemFixed(2, 100);
statusBar()->insertItem(i18n("Welcome to KStars FITS Viewer"), 3, 1, true);
statusBar()->setItemAlignment(3 , TQt::AlignLeft);
/* FITS initializations */
if (!initFITS())
{
close();
return;
}
TQFile tempFile;
if (KSUtils::openDataFile( tempFile, "imgreduction.png" ) )
{
new TDEAction( i18n("Image Reduction"), tempFile.name(), TDEShortcut( "Ctrl+R" ), TQT_TQOBJECT(this), TQT_SLOT( imageReduction()), actionCollection(), "image_reduce");
tempFile.close();
}
else
new TDEAction( i18n("Image Reduction"), "blend", TDEShortcut( "Ctrl+R" ), TQT_TQOBJECT(this), TQT_SLOT( imageReduction()), actionCollection(), "image_reduce");
/*if (KSUtils::openDataFile( tempFile, "bricon.png" ) )
{
new TDEAction( i18n("Brightness/Contrast"), tempFile.name(), TDEShortcut( "Ctrl+T" ), TQT_TQOBJECT(this), TQT_SLOT( BrightContrastDlg()), actionCollection(), "image_brightness_contrast");
tempFile.close();
}
else*/
new TDEAction( i18n("Brightness/Contrast"), "contrast+", TDEShortcut( "Ctrl+T" ), TQT_TQOBJECT(this), TQT_SLOT( BrightContrastDlg()), actionCollection(), "image_brightness_contrast");
if (KSUtils::openDataFile( tempFile, "histogram.png" ) )
{
new TDEAction ( i18n("Histogram"), tempFile.name(), TDEShortcut("Ctrl+H"), TQT_TQOBJECT(this), TQT_SLOT (imageHistogram()), actionCollection(), "image_histogram");
tempFile.close();
}
else
new TDEAction ( i18n("Histogram"), "wizard", TDEShortcut("Ctrl+H"), TQT_TQOBJECT(this), TQT_SLOT (imageHistogram()), actionCollection(), "image_histogram");
KStdAction::open(TQT_TQOBJECT(this), TQT_SLOT(fileOpen()), actionCollection());
KStdAction::save(TQT_TQOBJECT(this), TQT_SLOT(fileSave()), actionCollection());
KStdAction::saveAs(TQT_TQOBJECT(this), TQT_SLOT(fileSaveAs()), actionCollection());
KStdAction::close(TQT_TQOBJECT(this), TQT_SLOT(slotClose()), actionCollection());
KStdAction::copy(TQT_TQOBJECT(this), TQT_SLOT(fitsCOPY()), actionCollection());
KStdAction::zoomIn(TQT_TQOBJECT(image), TQT_SLOT(fitsZoomIn()), actionCollection());
KStdAction::zoomOut(TQT_TQOBJECT(image), TQT_SLOT(fitsZoomOut()), actionCollection());
new TDEAction( i18n( "&Default Zoom" ), "viewmagfit.png", TDEShortcut( "Ctrl+D" ),
TQT_TQOBJECT(image), TQT_SLOT(fitsZoomDefault()), actionCollection(), "zoom_default" );
new TDEAction( i18n( "Statistics"), "sum", 0, TQT_TQOBJECT(this), TQT_SLOT(fitsStatistics()), actionCollection(), "image_stats");
new TDEAction( i18n( "FITS Header"), "frame_spreadsheet.png", 0, TQT_TQOBJECT(this), TQT_SLOT(fitsHeader()), actionCollection(), "fits_editor");
/* Create GUI */
createGUI("fitsviewer.rc");
/* initially resize in accord with KDE rules */
resize(640, 480);
}
FITSViewer::~FITSViewer()
{
free(imgBuffer);
}
bool FITSViewer::initFITS()
{
free(imgBuffer);
imgBuffer = NULL;
image->clearMem();
/* Load image into buffer */
if ( (imgBuffer = loadData (currentURL.path().ascii(), imgBuffer)) == NULL) { close(); return false; }
/* Display image in the central widget */
if (image->loadFits(currentURL.path().ascii()) == -1) { close(); return false; }
/* Clear history */
history->clear();
/* Set new file caption */
setCaption(currentURL.fileName());
/* Get initial statistics */
calculateStats();
image->viewport()->resize(image->viewport()->width() + 5, image->viewport()->height());
image->viewportResizeEvent(NULL);
return true;
}
void FITSViewer::slotClose()
{
if (Dirty)
{
TQString caption = i18n( "Save Changes to FITS?" );
TQString message = i18n( "The current FITS file has unsaved changes. Would you like to save before closing it?" );
int ans = KMessageBox::warningYesNoCancel( 0, message, caption, KStdGuiItem::save(), KStdGuiItem::discard() );
if ( ans == KMessageBox::Yes )
fileSave();
else if ( ans == KMessageBox::No )
fitsRestore();
}
if (Dirty == 0)
close();
}
void FITSViewer::closeEvent(TQCloseEvent *ev)
{
if (Dirty)
{
TQString caption = i18n( "Save Changes to FITS?" );
TQString message = i18n( "The current FITS file has unsaved changes. Would you like to save before closing it?" );
int ans = KMessageBox::warningYesNoCancel( 0, message, caption, KStdGuiItem::save(), KStdGuiItem::discard() );
if ( ans == KMessageBox::Yes )
fileSave();
else if ( ans == KMessageBox::No )
fitsRestore();
}
if (Dirty == 0)
ev->accept();
else
ev->ignore();
}
void FITSViewer::show_fits_errors()
{
char *msg;
/* Write out error messages of FITS-Library */
while ((msg = fits_get_error ()) != NULL)
KMessageBox::error(0, msg);
}
float * FITSViewer::loadData(const char *filename, float *buffer)
{
FILE *fp;
FITS_FILE *ifp;
FITS_HDU_LIST *hdulist;
unsigned char *tempData, *tempDataPtr;
FITS_BITPIX16 pixval_16 =0;
FITS_BITPIX32 pixval_32 =0;
FITS_BITPIXM32 pixval_m32 =0;
FITS_BITPIXM64 pixval_m64 =0;
int totalCount;
int width, height, bpp, bitpix;
fp = fopen (filename, "rb");
if (!fp)
{
KMessageBox::error(0, i18n("Cannot open file for reading"));
return (NULL);
}
fclose (fp);
ifp = fits_open (filename, "r");
if (ifp == NULL)
{
KMessageBox::error(0, i18n("Error during open of FITS file"));
return (NULL);
}
if (ifp->n_pic <= 0)
{
KMessageBox::error(0, i18n("FITS file keeps no displayable images"));
fits_close (ifp);
return (NULL);
}
// We only deal with 1 image in a FITS for now.
hdulist = fits_seek_image (ifp, 1);
if (hdulist == NULL) return (NULL);
width = hdulist->naxisn[0];
height = hdulist->naxisn[1];
totalCount = width * height;
bpp = hdulist->bpp;
bitpix = hdulist->bitpix;
buffer = (float *) malloc (height * width * sizeof(float));
tempData = (unsigned char *) malloc (height * width * bpp * sizeof(unsigned char));
if (buffer == NULL || tempData == NULL)
{
KMessageBox::error(0, i18n("Not enough memory to load FITS."));
return (NULL);
}
tempDataPtr = tempData;
if (fread(tempData, 1, width * height * bpp, ifp->fp) != (unsigned int) (width * height * bpp))
{
KMessageBox::error(0, i18n("Unable to read FITS data from file. %1.\n").arg(strerror(errno)));
return (NULL);
}
switch (bitpix)
{
case 8:
for (int i=0; i < totalCount; i++)
buffer[i] = tempData[i];
break;
case 16:
for (int i=0; i < totalCount ; i++)
{
FITS_GETBITPIX16(tempData, pixval_16);
buffer[i] = pixval_16;//ntohs(pixval_16);
tempData+=2;
}
break;
case 32:
for (int i=0; i < totalCount ; i++)
{
//pixval_32 = ntohl(pixval_32);
if (fits_nan_32(tempData)) {
pixval_32 = 0;
}
else {
FITS_GETBITPIX32(tempData, pixval_32);
}
buffer[i] = pixval_32;
tempData+=4;
}
break;
case -32:
for (int i=0; i < totalCount ; i++)
{
if (fits_nan_32 (tempData))
pixval_m32 = 0;
else
FITS_GETBITPIXM32(tempData, pixval_m32);
buffer[i] = pixval_m32;
tempData+=4;
}
break;
case -64:
for (int i=0; i < totalCount ; i++)
{
if (fits_nan_64 (tempData))
pixval_m64 = 0;
else
FITS_GETBITPIXM64(tempData, pixval_m64);
buffer[i] = pixval_m64;
tempData+=8;
}
break;
}
fits_close(ifp);
free(tempDataPtr);
return buffer;
}
void FITSViewer::calculateStats()
{
/*kdDebug() << "Calculating statistics..." << endl;*/
stats.min = min(stats.minAt);
stats.max = max(stats.maxAt);
stats.average = average();
stats.stddev = stddev();
stats.bitpix = image->bitpix;
stats.width = image->width;
stats.height = image->height;
/*kdDebug() << "Min: " << stats.min << " - Max: " << stats.max << endl;
kdDebug() << "Average: " << stats.average << " - stddev: " << stats.stddev << endl;
kdDebug() << "Width: " << stats.width << " - Height " << stats.height << " - bitpix " << stats.bitpix << endl;*/
statusBar()->changeItem( TQString("%1 x %2").arg( (int) stats.width).arg( (int) stats.height), 2);
}
double FITSViewer::min(int & minIndex)
{
if (!imgBuffer) return -1;
int width = image->currentRect.width();
int height = image->currentRect.height();
double lmin = imgBuffer[image->currentRect.y() * width + image->currentRect.x()];
int index=0;
for (int i= image->currentRect.y() ; i < height; i++)
for (int j= image->currentRect.x(); j < width; j++)
{
index = (i * width) + j;
if (imgBuffer[index] < lmin)
{
minIndex = index;
lmin = imgBuffer[index];
}
}
return lmin;
}
double FITSViewer::max(int & maxIndex)
{
if (!imgBuffer) return -1;
int width = image->currentRect.width();
int height = image->currentRect.height();
double lmax = imgBuffer[image->currentRect.y() * width + image->currentRect.x()];
int index=0;
for (int i= image->currentRect.y() ; i < height; i++)
for (int j= image->currentRect.x(); j < width; j++)
{
index = (i * width) + j;
if ( imgBuffer[index] > lmax)
{
maxIndex = index;
lmax = imgBuffer[index];
}
}
return lmax;
}
double FITSViewer::average()
{
int index=0;
double sum=0;
int width = image->currentRect.width();
int height = image->currentRect.height();
if (!imgBuffer) return -1;
for (int i= image->currentRect.y() ; i < height; i++)
for (int j= image->currentRect.x(); j < width; j++)
{
index = (i * width) + j;
sum += imgBuffer[index];
}
return (sum / (width * height ));
}
double FITSViewer::stddev()
{
int index=0;
double lsum=0;
int width = image->currentRect.width();
int height = image->currentRect.height();
if (!imgBuffer) return -1;
for (int i= image->currentRect.y() ; i < height; i++)
for (int j= image->currentRect.x(); j < width; j++)
{
index = (i * width) + j;
lsum += (imgBuffer[index] - stats.average) * (imgBuffer[index] - stats.average);
}
return (sqrt(lsum/(width * height - 1)));
}
void FITSViewer::keyPressEvent (TQKeyEvent *ev)
{
//TQImage Tempimage = imageList.at(undo+1)->copy();
ev->accept(); //make sure key press events are captured.
switch (ev->key())
{
//case Key_H : KImageEffect::contrastHSV(image); break;
//case Key_S : KImageEffect::sharpen(image); break;
//case Key_B : KImageEffect::blur(image); break;
default : ev->ignore();
}
}
void FITSViewer::fileOpen()
{
if (Dirty)
{
TQString caption = i18n( "Save Changes to FITS?" );
TQString message = i18n( "The current FITS file has unsaved changes. Would you like to save before closing it?" );
int ans = KMessageBox::warningYesNoCancel( 0, message, caption, KStdGuiItem::save(), KStdGuiItem::discard() );
if ( ans == KMessageBox::Yes )
fileSave();
else if ( ans == KMessageBox::No )
fitsRestore();
}
KURL fileURL = KFileDialog::getOpenURL( TQDir::homeDirPath(), "*.fits *.fit *.fts|Flexible Image Transport System");
if (fileURL.isEmpty())
return;
currentURL = fileURL;
initFITS();
}
void FITSViewer::fileSave()
{
FITS_FILE *ifp;
TQString recordList;
KURL backupCurrent = currentURL;
TQString bitpixRec;
FITS_BITPIX16 pixval_16 =0;
FITS_BITPIX32 pixval_32 =0;
FITS_BITPIXM32 pixval_m32 =0;
FITS_BITPIXM64 pixval_m64 =0;
unsigned char *transData;
int index=0, i=0, transCount = 0, totalCount= image->width * image->height;
TQString currentDir = Options::fitsSaveDirectory();
//kdDebug() << "We doing stats BEFORE we save!! " << endl;
//calculateStats();
// If no changes made, return.
if (Dirty == 0 && !currentURL.isEmpty())
return;
if (currentURL.isEmpty())
{
currentURL = KFileDialog::getSaveURL( currentDir, "*.fits |Flexible Image Transport System");
// if user presses cancel
if (currentURL.isEmpty())
{
currentURL = backupCurrent;
return;
}
if (currentURL.path().contains('.') == 0) currentURL.setPath(currentURL.path() + ".fits");
if (TQFile::exists(currentURL.path()))
{
int r=KMessageBox::warningContinueCancel(TQT_TQWIDGET(parent()),
i18n( "A file named \"%1\" already exists. "
"Overwrite it?" ).arg(currentURL.fileName()),
i18n( "Overwrite File?" ),
i18n( "&Overwrite" ) );
if(r==KMessageBox::Cancel) return;
}
}
if ( currentURL.isValid() )
{
transData = (unsigned char *) malloc (sizeof(unsigned char) * totalCount * image->bpp);
if (transData == NULL)
{
KMessageBox::error(0, i18n("Error: Low memory. Saving is aborted."));
return;
}
ifp = fits_open (currentURL.path().ascii(), "w");
if (ifp == NULL)
{
KMessageBox::error(0, i18n("Error during open of FITS file."));
return;
}
setbuf(ifp->fp, NULL);
bitpixRec.sprintf("BITPIX = %d /Modified by KStars ", image->bitpix);
bitpixRec.truncate(80);
for (unsigned int j=0; j < record.count(); j++)
{
recordList = record[j];
if ( (index = recordList.find("BITPIX")) != -1)
recordList.replace(index, FITS_CARD_SIZE, bitpixRec);
fwrite(recordList.ascii(), 1, FITS_RECORD_SIZE, ifp->fp);
}
switch (image->bitpix)
{
case 8:
for (i= image->height - 1; i >= 0; i--)
fwrite(image->displayImage->scanLine(i), 1, image->width, ifp->fp);
break;
case 16:
for (i= 0, transCount = 0 ; i < totalCount ; i++, transCount += 2)
{
pixval_16 = (unsigned short) imgBuffer[i];
transData[transCount] = ((unsigned char*) &pixval_16)[1];
transData[transCount+1] = ((unsigned char*) &pixval_16)[0];
}
// Now we need to write all uchars to file. We have 2 bytes per pixel
transCount = 0;
totalCount *= 2;
for (i=0, transCount = 0; i < totalCount; i += transCount)
transCount = fwrite( transData + i , 1, totalCount - i, ifp->fp);
break;
case 32:
for (i=0, transCount = 0 ; i < totalCount ; i++, transCount += 4)
{
pixval_32 = (unsigned int) imgBuffer[i];
transData[transCount] = ((unsigned char*) &pixval_32)[3];
transData[transCount+1] = ((unsigned char*) &pixval_32)[2];
transData[transCount+2] = ((unsigned char*) &pixval_32)[1];
transData[transCount+3] = ((unsigned char*) &pixval_32)[0];
}
// Now we need to write all uchars to file. We have 4 bytes per pixel
transCount = 0;
totalCount *= 4;
for (i=0, transCount = 0; i < totalCount; i += transCount)
transCount = fwrite( transData + i , 1, totalCount - i, ifp->fp);
break;
case -32:
for (i=0, transCount = 0 ; i < totalCount ; i++, transCount += 4)
{
pixval_m32 = imgBuffer[i];
transData[transCount] = ((unsigned char*) &pixval_m32)[3];
transData[transCount+1] = ((unsigned char*) &pixval_m32)[2];
transData[transCount+2] = ((unsigned char*) &pixval_m32)[1];
transData[transCount+3] = ((unsigned char*) &pixval_m32)[0];
}
// Now we need to write all uchars to file. We have 4 bytes per pixel
transCount = 0;
totalCount *= 4;
for (i=0, transCount = 0; i < totalCount; i += transCount)
transCount = fwrite( transData + i , 1, totalCount - i, ifp->fp);
break;
case -64:
for (i=0, transCount = 0 ; i < totalCount ; i++, transCount += 8)
{
pixval_m64 = imgBuffer[i];
transData[transCount] = 0;
transData[transCount+1] = 0;
transData[transCount+2] = 0;
transData[transCount+3] = 0;
transData[transCount+4] = ((unsigned char*) &pixval_m32)[3];
transData[transCount+5] = ((unsigned char*) &pixval_m32)[2];
transData[transCount+6] = ((unsigned char*) &pixval_m32)[1];
transData[transCount+7] = ((unsigned char*) &pixval_m32)[0];
}
// Now we need to write all uchars to file. We have 4 bytes per pixel
transCount = 0;
totalCount *= 8;
for (i=0, transCount = 0; i < totalCount; i += transCount)
transCount = fwrite( transData + i , 1, totalCount - i, ifp->fp);
break;
}
fits_close(ifp);
statusBar()->changeItem(i18n("File saved."), 3);
free(transData);
Dirty = 0;
history->clear();
fitsRestore();
//updateImgBuffer();
}
else
{
TQString message = i18n( "Invalid URL: %1" ).arg( currentURL.url() );
KMessageBox::sorry( 0, message, i18n( "Invalid URL" ) );
}
}
void FITSViewer::fileSaveAs()
{
currentURL = "";
fileSave();
}
void FITSViewer::fitsCOPY()
{
kapp->clipboard()->setImage(*image->displayImage);
}
void FITSViewer::updateImgBuffer()
{
int width = image->width;
int height = image->height;
for (int i=0; i < height; i++)
for (int j=0; j < width; j++)
imgBuffer[i * width + j] = (int) *(image->displayImage->scanLine(height - i - 1) + j);
//image->reducedImgBuffer[i * width + j];
calculateStats();
}
void FITSViewer::imageReduction()
{
FITSProcessCommand *cbc;
FITSHistogramCommand *hbc;
TQStringList darkFiles, flatFiles, darkflatFiles;
int darkCombineMode = 0 , flatCombineMode = 0, darkflatCombineMode =0;
TQListViewItem *file;
image->saveTemplateImage();
ImageReductionDlg irDialog(this);
if (irDialog.exec() == TQDialog::Accepted)
{
if (irDialog.darkListView->childCount() == 0 &&
irDialog.flatListView->childCount() == 0)
{
image->destroyTemplateImage();
return;
}
darkCombineMode = irDialog.darkAverageB->isChecked() ? 0 : 1;
flatCombineMode = irDialog.flatAverageB->isChecked() ? 0 : 1;
darkflatCombineMode= irDialog.darkflatAverageB->isChecked() ? 0 : 1;
file = irDialog.darkListView->firstChild();
while (file)
{
darkFiles << file->text(0);
file = file->nextSibling();
}
file = irDialog.flatListView->firstChild();
while (file)
{
flatFiles << file->text(0);
file = file->nextSibling();
}
file = irDialog.darkflatListView->firstChild();
while (file)
{
darkflatFiles << file->text(0);
file = file->nextSibling();
}
cbc = new FITSProcessCommand(this);
FITSProcess reduc(this, darkFiles, flatFiles, darkflatFiles, darkCombineMode, flatCombineMode, darkflatCombineMode);
reduc.reduce();
history->addCommand(cbc, false);
calculateStats();
hbc = new FITSHistogramCommand(this, NULL, FITSImage::FITSLinear, (int) stats.min, (int) stats.max);
history->addCommand(hbc);
fitsChange();
}
image->destroyTemplateImage();
}
void FITSViewer::BrightContrastDlg()
{
FITSChangeCommand *cbc;
image->saveTemplateImage();
ContrastBrightnessDlg conbriDlg(this);
if (conbriDlg.exec() == TQDialog::Rejected)
{
image->reLoadTemplateImage();
image->zoomToCurrent();
}
else
{
memcpy(imgBuffer , conbriDlg.localImgBuffer, stats.width * stats.height * 4);
free(conbriDlg.localImgBuffer);
fitsChange();
image->update();
cbc = new FITSChangeCommand(this, CONTRAST_BRIGHTNESS, image->displayImage, image->templateImage);
history->addCommand(cbc, false);
}
image->destroyTemplateImage();
}
void FITSViewer::imageHistogram()
{
/*FITSHistogramCommand *histC;
unsigned int * backupBuf = (unsigned int *) malloc (image->width * image->height * sizeof(unsigned int));
if (backBuf == NULL)
{
KMessageBox::error(0, i18n("Not enough memory to complete the operation."));
return;
}
memcpy(backupBuf, imgBuffer, width * height);*/
//image->saveTemplateImage();
if (histo == NULL)
{
histo = new FITSHistogram(this);
histo->show();
}
else
{
histo->constructHistogram(imgBuffer);
histo->updateBoxes();
histo->show();
}
/*if (hist.exec() == TQDialog::Rejected)
{
if (hist.napply > 0)
for (int i=0; i < hist.napply; i++)
history->undo();
else
{
image->reLoadTemplateImage();
image->zoomToCurrent();
}
//free (backupBuf);
}
else
{
if (hist.napply > 0) fitsChange();
//histC = new FITSHistogramCommand(this, hist.type, backupBuf, image->displayImage, image->templateImage);
//history->addCommand(histC, false);
}
image->destroyTemplateImage();*/
}
void FITSViewer::fitsRestore()
{
Dirty = 0;
setCaption(currentURL.fileName());
}
void FITSViewer::fitsChange()
{
Dirty = 1;
setCaption(currentURL.fileName() + i18n(" [modified]"));
}
void FITSViewer::fitsStatistics()
{
statForm stat(this);
calculateStats();
stat.widthOUT->setText(TQString("%1").arg(stats.width));
stat.heightOUT->setText(TQString("%1").arg(stats.height));
stat.bitpixOUT->setText(TQString("%1").arg(stats.bitpix));
stat.maxOUT->setText(TQString("%1").arg(stats.max));
stat.minOUT->setText(TQString("%1").arg(stats.min));
stat.atMaxOUT->setText(TQString("%1").arg(stats.maxAt));
stat.atMinOUT->setText(TQString("%1").arg(stats.minAt));
stat.meanOUT->setText(TQString("%1").arg(stats.average));
stat.stddevOUT->setText(TQString("%1").arg(stats.stddev));
stat.exec();
}
void FITSViewer::fitsHeader()
{
TQStringList cards;
TQString recordList;
TQString property;
int equal, slash;
fitsHeaderDialog header(this);
header.headerView->setSorting(-1);
header.headerView->setColumnAlignment(1, TQt::AlignHCenter);
for (unsigned int i=0; i < record.count(); i++)
{
recordList = record[i];
//recordList = TQString((char *) record);
for (int j=0; j < FITS_RECORD_SIZE / FITS_CARD_SIZE; j++)
{
property = recordList.left(FITS_CARD_SIZE);
equal = property.find('=');
if (equal == -1)
{
if (property.contains(" ") != FITS_CARD_SIZE)
cards << property << "" << "";
recordList.remove(0, FITS_CARD_SIZE);
if (property.find("END") != -1)
break;
else
continue;
}
cards << property.left(equal);
slash = property.find("'");
if (slash != -1)
slash = property.find("'", slash + 1) + 1;
else
slash = property.find('/') - 1;
cards << property.mid(equal + 2, slash - (equal + 2)).simplifyWhiteSpace().remove("'");
cards << property.mid(slash + 1, FITS_CARD_SIZE - (slash + 1)).simplifyWhiteSpace();
recordList.remove(0, FITS_CARD_SIZE);
}
}
for (int k= cards.count() - 3; k >=0 ; k-=3)
new TQListViewItem( header.headerView, cards[k], cards[k+1], cards[k+2]);
header.exec();
}
FITSChangeCommand::FITSChangeCommand(TQWidget * parent, int inType, TQImage* newIMG, TQImage *oldIMG)
{
viewer = (FITSViewer *) parent;
newImage = new TQImage();
oldImage = new TQImage();
*newImage = newIMG->copy();
*oldImage = oldIMG->copy();
type = inType;
}
FITSChangeCommand::~FITSChangeCommand() {}
void FITSChangeCommand::execute()
{
viewer->image->displayImage = newImage;
viewer->image->zoomToCurrent();
viewer->fitsChange();
}
void FITSChangeCommand::unexecute()
{
viewer->image->displayImage = oldImage;
viewer->image->zoomToCurrent();
}
TQString FITSChangeCommand::name() const
{
switch (type)
{
case FITSViewer::CONTRAST_BRIGHTNESS:
return i18n("Brightness/Contrast");
break;
case FITSViewer::IMAGE_REDUCTION:
return i18n("Image Reduction");
break;
case FITSViewer::IMAGE_FILTER:
return i18n("Image Filter");
break;
default:
return i18n("unknown");
break;
}
}
#include "fitsviewer.moc"