/*************************************************************************** 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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"