moved kdeaccessibility kdeaddons kdeadmin kdeartwork kdebindings kdeedu kdegames...
[kdeedu.git] / kstars / kstars / fitsviewer.cpp
blobc570a0c91b15ba7448b8e6402e6591085074c4c3
1 /***************************************************************************
2 FITSViewer.cpp - A FITSViewer for KStars
3 -------------------
4 begin : Thu Jan 22 2004
5 copyright : (C) 2004 by Jasem Mutlaq
6 email : mutlaqja@ikarustech.com
7 ***************************************************************************/
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * Some code fragments were adapted from Peter Kirchgessner's FITS plugin*
17 * See http://members.aol.com/pkirchg for more details. *
18 ***************************************************************************/
21 #include <klocale.h>
22 #include <kmessagebox.h>
23 #include <kfiledialog.h>
24 #include <kaction.h>
25 #include <kaccel.h>
26 #include <kdebug.h>
27 #include <ktoolbar.h>
28 #include <kapplication.h>
29 #include <kpixmap.h>
30 #include <ktempfile.h>
31 #include <kimageeffect.h>
32 #include <kmenubar.h>
33 #include <kprogress.h>
34 #include <kstatusbar.h>
35 #include <kcommand.h>
36 #include <klineedit.h>
37 #include <klistview.h>
39 #include <qfile.h>
40 #include <qvbox.h>
41 #include <qcursor.h>
42 #include <qstringlist.h>
43 #include <qlistview.h>
44 #include <qradiobutton.h>
45 #include <qclipboard.h>
46 #include <qimage.h>
48 #include <math.h>
49 #include <unistd.h>
50 #include <stdlib.h>
51 #include <netinet/in.h>
53 #include "fitsviewer.h"
54 #include "fitsimage.h"
55 #include "fitsprocess.h"
56 #include "fitshistogram.h"
57 #include "conbridlg.h"
58 #include "statform.h"
59 #include "imagereductiondlg.h"
60 #include "fitsheaderdialog.h"
61 #include "ksutils.h"
62 #include "Options.h"
64 extern int fits_ieee32_intel;
65 extern int fits_ieee32_motorola;
66 extern int fits_ieee64_intel;
67 extern int fits_ieee64_motorola;
69 #define FITS_GETBITPIX16(p,val) val = ((p[0] << 8) | (p[1]))
70 #define FITS_GETBITPIX32(p,val) val = \
71 ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3])
73 #define FITS_GETBITPIXM32(p,val) \
74 { if (fits_ieee32_intel) {unsigned char uc[4]; \
75 uc[0] = p[3]; uc[1] = p[2]; uc[2] = p[1]; uc[3] = p[0]; \
76 val = *(FITS_BITPIXM32 *)uc; } \
77 else if (fits_ieee32_motorola) { val = *(FITS_BITPIXM32 *)p; } \
78 else if (fits_ieee64_motorola) {FITS_BITPIXM64 m64; \
79 unsigned char *uc= (unsigned char *)&m64; \
80 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; \
81 val = (FITS_BITPIXM32)m64; } \
82 else if (fits_ieee64_intel) {FITS_BITPIXM64 i64; \
83 unsigned char *uc= (unsigned char *)&i64; \
84 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]; \
85 val = (FITS_BITPIXM32)i64;}\
88 #define FITS_GETBITPIXM64(p,val) \
89 { if (fits_ieee64_intel) {unsigned char uc[8]; \
90 uc[0] = p[7]; uc[1] = p[6]; uc[2] = p[5]; uc[3] = p[4]; \
91 uc[4] = p[3]; uc[5] = p[2]; uc[6] = p[1]; uc[7] = p[0]; \
92 val = *(FITS_BITPIXM64 *)uc; } else val = *(FITS_BITPIXM64 *)p; }
94 FITSViewer::FITSViewer (const KURL *url, QWidget *parent, const char *name)
95 : KMainWindow (parent, name)
97 image = NULL;
98 currentURL = *url;
99 imgBuffer = NULL;
100 histo = NULL;
101 Dirty = 0;
103 /* Initiliaze menu actions */
104 history = new KCommandHistory(actionCollection());
105 history->setUndoLimit(10);
106 history->setRedoLimit(10);
107 history->documentSaved();
108 connect(history, SIGNAL(documentRestored()), this, SLOT(fitsRestore()));
110 /* Setup image widget */
111 image = new FITSImage(this);
112 setCentralWidget(image);
114 statusBar()->insertItem("", 0);
115 statusBar()->setItemFixed(0, 100);
116 statusBar()->insertItem("", 1);
117 statusBar()->setItemFixed(1, 100);
118 statusBar()->insertItem("", 2);
119 statusBar()->setItemFixed(2, 100);
120 statusBar()->insertItem(i18n("Welcome to KStars FITS Viewer"), 3, 1, true);
121 statusBar()->setItemAlignment(3 , Qt::AlignLeft);
123 /* FITS initializations */
124 if (!initFITS())
126 close();
127 return;
130 QFile tempFile;
132 if (KSUtils::openDataFile( tempFile, "imgreduction.png" ) )
134 new KAction( i18n("Image Reduction"), tempFile.name(), KShortcut( "Ctrl+R" ), this, SLOT( imageReduction()), actionCollection(), "image_reduce");
135 tempFile.close();
137 else
138 new KAction( i18n("Image Reduction"), "blend", KShortcut( "Ctrl+R" ), this, SLOT( imageReduction()), actionCollection(), "image_reduce");
140 /*if (KSUtils::openDataFile( tempFile, "bricon.png" ) )
142 new KAction( i18n("Brightness/Contrast"), tempFile.name(), KShortcut( "Ctrl+T" ), this, SLOT( BrightContrastDlg()), actionCollection(), "image_brightness_contrast");
143 tempFile.close();
145 else*/
146 new KAction( i18n("Brightness/Contrast"), "contrast+", KShortcut( "Ctrl+T" ), this, SLOT( BrightContrastDlg()), actionCollection(), "image_brightness_contrast");
148 if (KSUtils::openDataFile( tempFile, "histogram.png" ) )
150 new KAction ( i18n("Histogram"), tempFile.name(), KShortcut("Ctrl+H"), this, SLOT (imageHistogram()), actionCollection(), "image_histogram");
151 tempFile.close();
153 else
154 new KAction ( i18n("Histogram"), "wizard", KShortcut("Ctrl+H"), this, SLOT (imageHistogram()), actionCollection(), "image_histogram");
156 KStdAction::open(this, SLOT(fileOpen()), actionCollection());
157 KStdAction::save(this, SLOT(fileSave()), actionCollection());
158 KStdAction::saveAs(this, SLOT(fileSaveAs()), actionCollection());
159 KStdAction::close(this, SLOT(slotClose()), actionCollection());
160 KStdAction::copy(this, SLOT(fitsCOPY()), actionCollection());
161 KStdAction::zoomIn(image, SLOT(fitsZoomIn()), actionCollection());
162 KStdAction::zoomOut(image, SLOT(fitsZoomOut()), actionCollection());
163 new KAction( i18n( "&Default Zoom" ), "viewmagfit.png", KShortcut( "Ctrl+D" ),
164 image, SLOT(fitsZoomDefault()), actionCollection(), "zoom_default" );
165 new KAction( i18n( "Statistics"), "sum", 0, this, SLOT(fitsStatistics()), actionCollection(), "image_stats");
166 new KAction( i18n( "FITS Header"), "frame_spreadsheet.png", 0, this, SLOT(fitsHeader()), actionCollection(), "fits_editor");
168 /* Create GUI */
169 createGUI("fitsviewer.rc");
171 /* initially resize in accord with KDE rules */
172 resize(640, 480);
175 FITSViewer::~FITSViewer()
177 free(imgBuffer);
180 bool FITSViewer::initFITS()
183 free(imgBuffer);
184 imgBuffer = NULL;
185 image->clearMem();
187 /* Load image into buffer */
188 if ( (imgBuffer = loadData (currentURL.path().ascii(), imgBuffer)) == NULL) { close(); return false; }
189 /* Display image in the central widget */
190 if (image->loadFits(currentURL.path().ascii()) == -1) { close(); return false; }
192 /* Clear history */
193 history->clear();
195 /* Set new file caption */
196 setCaption(currentURL.fileName());
198 /* Get initial statistics */
199 calculateStats();
201 image->viewport()->resize(image->viewport()->width() + 5, image->viewport()->height());
202 image->viewportResizeEvent(NULL);
204 return true;
208 void FITSViewer::slotClose()
211 if (Dirty)
214 QString caption = i18n( "Save Changes to FITS?" );
215 QString message = i18n( "The current FITS file has unsaved changes. Would you like to save before closing it?" );
216 QString ybut = KStdGuiItem::save().text();
217 QString nbut = i18n( "&Discard" );
218 int ans = KMessageBox::warningYesNoCancel( 0, message, caption, ybut, nbut );
219 if ( ans == KMessageBox::Yes )
220 fileSave();
221 else if ( ans == KMessageBox::No )
222 fitsRestore();
225 if (Dirty == 0)
226 close();
229 void FITSViewer::closeEvent(QCloseEvent *ev)
232 if (Dirty)
235 QString caption = i18n( "Save Changes to FITS?" );
236 QString message = i18n( "The current FITS file has unsaved changes. Would you like to save before closing it?" );
237 QString ybut = KStdGuiItem::save().text();
238 QString nbut = i18n( "&Discard" );
239 int ans = KMessageBox::warningYesNoCancel( 0, message, caption, ybut, nbut );
240 if ( ans == KMessageBox::Yes )
241 fileSave();
242 else if ( ans == KMessageBox::No )
243 fitsRestore();
246 if (Dirty == 0)
247 ev->accept();
248 else
249 ev->ignore();
253 void FITSViewer::show_fits_errors()
255 char *msg;
256 /* Write out error messages of FITS-Library */
257 while ((msg = fits_get_error ()) != NULL)
258 KMessageBox::error(0, msg);
261 float * FITSViewer::loadData(const char *filename, float *buffer)
263 FILE *fp;
264 FITS_FILE *ifp;
265 FITS_HDU_LIST *hdulist;
266 unsigned char *tempData, *tempDataPtr;
267 register FITS_BITPIX16 pixval_16 =0;
268 register FITS_BITPIX32 pixval_32 =0;
269 register FITS_BITPIXM32 pixval_m32 =0;
270 register FITS_BITPIXM64 pixval_m64 =0;
271 int totalCount;
272 int width, height, bpp, bitpix;
274 fp = fopen (filename, "rb");
275 if (!fp)
277 KMessageBox::error(0, i18n("Cannot open file for reading"));
278 return (NULL);
280 fclose (fp);
282 ifp = fits_open (filename, "r");
283 if (ifp == NULL)
285 KMessageBox::error(0, i18n("Error during open of FITS file"));
286 return (NULL);
288 if (ifp->n_pic <= 0)
290 KMessageBox::error(0, i18n("FITS file keeps no displayable images"));
291 fits_close (ifp);
292 return (NULL);
295 // We only deal with 1 image in a FITS for now.
296 hdulist = fits_seek_image (ifp, 1);
297 if (hdulist == NULL) return (NULL);
299 width = hdulist->naxisn[0];
300 height = hdulist->naxisn[1];
302 totalCount = width * height;
304 bpp = hdulist->bpp;
305 bitpix = hdulist->bitpix;
307 buffer = (float *) malloc (height * width * sizeof(float));
308 tempData = (unsigned char *) malloc (height * width * bpp * sizeof(unsigned char));
309 if (buffer == NULL || tempData == NULL)
311 KMessageBox::error(0, i18n("Not enough memory to load FITS."));
312 return (NULL);
314 tempDataPtr = tempData;
316 if (fread(tempData, 1, width * height * bpp, ifp->fp) != (unsigned int) (width * height * bpp))
318 KMessageBox::error(0, i18n("Unable to read FITS data from file. %1.\n").arg(strerror(errno)));
319 return (NULL);
322 switch (bitpix)
324 case 8:
325 for (int i=0; i < totalCount; i++)
326 buffer[i] = tempData[i];
327 break;
329 case 16:
330 for (int i=0; i < totalCount ; i++)
332 FITS_GETBITPIX16(tempData, pixval_16);
333 buffer[i] = pixval_16;//ntohs(pixval_16);
334 tempData+=2;
336 break;
338 case 32:
339 for (int i=0; i < totalCount ; i++)
341 FITS_GETBITPIX32(tempData, pixval_32);
342 //pixval_32 = ntohl(pixval_32);
343 if (isnan(pixval_32)) pixval_32 = 0;
344 buffer[i] = pixval_32;
345 tempData+=4;
347 break;
349 case -32:
350 for (int i=0; i < totalCount ; i++)
352 if (fits_nan_32 (tempData))
353 pixval_m32 = 0;
354 else
355 FITS_GETBITPIXM32(tempData, pixval_m32);
356 buffer[i] = pixval_m32;
357 tempData+=4;
359 break;
361 case -64:
362 for (int i=0; i < totalCount ; i++)
364 if (fits_nan_64 (tempData))
365 pixval_m64 = 0;
366 else
367 FITS_GETBITPIXM64(tempData, pixval_m64);
368 buffer[i] = pixval_m64;
369 tempData+=8;
371 break;
374 fits_close(ifp);
375 free(tempDataPtr);
376 return buffer;
380 void FITSViewer::calculateStats()
382 /*kdDebug() << "Calculating statistics..." << endl;*/
383 stats.min = min(stats.minAt);
384 stats.max = max(stats.maxAt);
385 stats.average = average();
386 stats.stddev = stddev();
387 stats.bitpix = image->bitpix;
388 stats.width = image->width;
389 stats.height = image->height;
391 /*kdDebug() << "Min: " << stats.min << " - Max: " << stats.max << endl;
392 kdDebug() << "Average: " << stats.average << " - stddev: " << stats.stddev << endl;
393 kdDebug() << "Width: " << stats.width << " - Height " << stats.height << " - bitpix " << stats.bitpix << endl;*/
395 statusBar()->changeItem( QString("%1 x %2").arg( (int) stats.width).arg( (int) stats.height), 2);
399 double FITSViewer::min(int & minIndex)
401 if (!imgBuffer) return -1;
402 int width = image->currentRect.width();
403 int height = image->currentRect.height();
404 double lmin = imgBuffer[image->currentRect.y() * width + image->currentRect.x()];
405 int index=0;
407 for (int i= image->currentRect.y() ; i < height; i++)
408 for (int j= image->currentRect.x(); j < width; j++)
410 index = (i * width) + j;
411 if (imgBuffer[index] < lmin)
413 minIndex = index;
414 lmin = imgBuffer[index];
419 return lmin;
422 double FITSViewer::max(int & maxIndex)
424 if (!imgBuffer) return -1;
425 int width = image->currentRect.width();
426 int height = image->currentRect.height();
427 double lmax = imgBuffer[image->currentRect.y() * width + image->currentRect.x()];
428 int index=0;
430 for (int i= image->currentRect.y() ; i < height; i++)
431 for (int j= image->currentRect.x(); j < width; j++)
433 index = (i * width) + j;
434 if ( imgBuffer[index] > lmax)
436 maxIndex = index;
437 lmax = imgBuffer[index];
441 return lmax;
444 double FITSViewer::average()
446 int index=0;
447 double sum=0;
448 int width = image->currentRect.width();
449 int height = image->currentRect.height();
450 if (!imgBuffer) return -1;
452 for (int i= image->currentRect.y() ; i < height; i++)
453 for (int j= image->currentRect.x(); j < width; j++)
455 index = (i * width) + j;
456 sum += imgBuffer[index];
459 return (sum / (width * height ));
462 double FITSViewer::stddev()
464 int index=0;
465 double lsum=0;
466 int width = image->currentRect.width();
467 int height = image->currentRect.height();
468 if (!imgBuffer) return -1;
470 for (int i= image->currentRect.y() ; i < height; i++)
471 for (int j= image->currentRect.x(); j < width; j++)
473 index = (i * width) + j;
474 lsum += (imgBuffer[index] - stats.average) * (imgBuffer[index] - stats.average);
477 return (sqrt(lsum/(width * height - 1)));
481 void FITSViewer::keyPressEvent (QKeyEvent *ev)
483 //QImage Tempimage = imageList.at(undo+1)->copy();
485 ev->accept(); //make sure key press events are captured.
486 switch (ev->key())
488 //case Key_H : KImageEffect::contrastHSV(image); break;
489 //case Key_S : KImageEffect::sharpen(image); break;
490 //case Key_B : KImageEffect::blur(image); break;
492 default : ev->ignore();
497 void FITSViewer::fileOpen()
500 if (Dirty)
503 QString caption = i18n( "Save Changes to FITS?" );
504 QString message = i18n( "The current FITS file has unsaved changes. Would you like to save before closing it?" );
505 QString ybut = KStdGuiItem::save().text();
506 QString nbut = i18n( "&Discard" );
507 int ans = KMessageBox::warningYesNoCancel( 0, message, caption, ybut, nbut );
508 if ( ans == KMessageBox::Yes )
509 fileSave();
510 else if ( ans == KMessageBox::No )
511 fitsRestore();
514 KURL fileURL = KFileDialog::getOpenURL( QDir::homeDirPath(), "*.fits *.fit *.fts|Flexible Image Transport System");
516 if (fileURL.isEmpty())
517 return;
520 currentURL = fileURL;
522 initFITS();
526 void FITSViewer::fileSave()
529 FITS_FILE *ifp;
530 QString recordList;
531 KURL backupCurrent = currentURL;
532 QString bitpixRec;
533 FITS_BITPIX16 pixval_16 =0;
534 FITS_BITPIX32 pixval_32 =0;
535 FITS_BITPIXM32 pixval_m32 =0;
536 FITS_BITPIXM64 pixval_m64 =0;
537 unsigned char *transData;
538 int index=0, i=0, transCount = 0, totalCount= image->width * image->height;
540 QString currentDir = Options::fitsSaveDirectory();
542 //kdDebug() << "We doing stats BEFORE we save!! " << endl;
543 //calculateStats();
545 // If no changes made, return.
546 if (Dirty == 0 && !currentURL.isEmpty())
547 return;
549 if (currentURL.isEmpty())
551 currentURL = KFileDialog::getSaveURL( currentDir, "*.fits |Flexible Image Transport System");
552 // if user presses cancel
553 if (currentURL.isEmpty())
555 currentURL = backupCurrent;
556 return;
558 if (currentURL.path().contains('.') == 0) currentURL.setPath(currentURL.path() + ".fits");
560 if (QFile::exists(currentURL.path()))
562 int r=KMessageBox::warningContinueCancel(static_cast<QWidget *>(parent()),
563 i18n( "A file named \"%1\" already exists. "
564 "Overwrite it?" ).arg(currentURL.fileName()),
565 i18n( "Overwrite File?" ),
566 i18n( "&Overwrite" ) );
568 if(r==KMessageBox::Cancel) return;
572 if ( currentURL.isValid() )
574 transData = (unsigned char *) malloc (sizeof(unsigned char) * totalCount * image->bpp);
575 if (transData == NULL)
577 KMessageBox::error(0, i18n("Error: Low memory. Saving is aborted."));
578 return;
581 ifp = fits_open (currentURL.path().ascii(), "w");
582 if (ifp == NULL)
584 KMessageBox::error(0, i18n("Error during open of FITS file."));
585 return;
588 setbuf(ifp->fp, NULL);
590 bitpixRec.sprintf("BITPIX = %d /Modified by KStars ", image->bitpix);
591 bitpixRec.truncate(80);
593 for (unsigned int j=0; j < record.count(); j++)
595 recordList = record[j];
597 if ( (index = recordList.find("BITPIX")) != -1)
598 recordList.replace(index, FITS_CARD_SIZE, bitpixRec);
600 fwrite(recordList.ascii(), 1, FITS_RECORD_SIZE, ifp->fp);
603 switch (image->bitpix)
605 case 8:
606 for (i= image->height - 1; i >= 0; i--)
607 fwrite(image->displayImage->scanLine(i), 1, image->width, ifp->fp);
608 break;
611 case 16:
612 for (i= 0, transCount = 0 ; i < totalCount ; i++, transCount += 2)
614 pixval_16 = (unsigned short) imgBuffer[i];
615 transData[transCount] = ((unsigned char*) &pixval_16)[1];
616 transData[transCount+1] = ((unsigned char*) &pixval_16)[0];
618 // Now we need to write all uchars to file. We have 2 bytes per pixel
619 transCount = 0;
620 totalCount *= 2;
622 for (i=0, transCount = 0; i < totalCount; i += transCount)
623 transCount = fwrite( transData + i , 1, totalCount - i, ifp->fp);
625 break;
627 case 32:
628 for (i=0, transCount = 0 ; i < totalCount ; i++, transCount += 4)
630 pixval_32 = (unsigned int) imgBuffer[i];
631 transData[transCount] = ((unsigned char*) &pixval_32)[3];
632 transData[transCount+1] = ((unsigned char*) &pixval_32)[2];
633 transData[transCount+2] = ((unsigned char*) &pixval_32)[1];
634 transData[transCount+3] = ((unsigned char*) &pixval_32)[0];
637 // Now we need to write all uchars to file. We have 4 bytes per pixel
638 transCount = 0;
639 totalCount *= 4;
641 for (i=0, transCount = 0; i < totalCount; i += transCount)
642 transCount = fwrite( transData + i , 1, totalCount - i, ifp->fp);
643 break;
645 case -32:
646 for (i=0, transCount = 0 ; i < totalCount ; i++, transCount += 4)
648 pixval_m32 = imgBuffer[i];
649 transData[transCount] = ((unsigned char*) &pixval_m32)[3];
650 transData[transCount+1] = ((unsigned char*) &pixval_m32)[2];
651 transData[transCount+2] = ((unsigned char*) &pixval_m32)[1];
652 transData[transCount+3] = ((unsigned char*) &pixval_m32)[0];
656 // Now we need to write all uchars to file. We have 4 bytes per pixel
657 transCount = 0;
658 totalCount *= 4;
660 for (i=0, transCount = 0; i < totalCount; i += transCount)
661 transCount = fwrite( transData + i , 1, totalCount - i, ifp->fp);
663 break;
665 case -64:
666 for (i=0, transCount = 0 ; i < totalCount ; i++, transCount += 8)
668 pixval_m64 = imgBuffer[i];
669 transData[transCount] = 0;
670 transData[transCount+1] = 0;
671 transData[transCount+2] = 0;
672 transData[transCount+3] = 0;
673 transData[transCount+4] = ((unsigned char*) &pixval_m32)[3];
674 transData[transCount+5] = ((unsigned char*) &pixval_m32)[2];
675 transData[transCount+6] = ((unsigned char*) &pixval_m32)[1];
676 transData[transCount+7] = ((unsigned char*) &pixval_m32)[0];
680 // Now we need to write all uchars to file. We have 4 bytes per pixel
681 transCount = 0;
682 totalCount *= 8;
684 for (i=0, transCount = 0; i < totalCount; i += transCount)
685 transCount = fwrite( transData + i , 1, totalCount - i, ifp->fp);
686 break;
689 fits_close(ifp);
691 statusBar()->changeItem(i18n("File saved."), 3);
693 free(transData);
694 Dirty = 0;
695 history->clear();
696 fitsRestore();
697 //updateImgBuffer();
699 else
701 QString message = i18n( "Invalid URL: %1" ).arg( currentURL.url() );
702 KMessageBox::sorry( 0, message, i18n( "Invalid URL" ) );
708 void FITSViewer::fileSaveAs()
711 currentURL = "";
712 fileSave();
715 void FITSViewer::fitsCOPY()
717 kapp->clipboard()->setImage(*image->displayImage);
720 void FITSViewer::updateImgBuffer()
722 int width = image->width;
723 int height = image->height;
725 for (int i=0; i < height; i++)
726 for (int j=0; j < width; j++)
727 imgBuffer[i * width + j] = (int) *(image->displayImage->scanLine(height - i - 1) + j);
728 //image->reducedImgBuffer[i * width + j];
730 calculateStats();
733 void FITSViewer::imageReduction()
735 FITSProcessCommand *cbc;
736 FITSHistogramCommand *hbc;
737 QStringList darkFiles, flatFiles, darkflatFiles;
738 int darkCombineMode = 0 , flatCombineMode = 0, darkflatCombineMode =0;
739 QListViewItem *file;
741 image->saveTemplateImage();
742 ImageReductionDlg irDialog(this);
744 if (irDialog.exec() == QDialog::Accepted)
746 if (irDialog.darkListView->childCount() == 0 &&
747 irDialog.flatListView->childCount() == 0)
749 image->destroyTemplateImage();
750 return;
753 darkCombineMode = irDialog.darkAverageB->isChecked() ? 0 : 1;
754 flatCombineMode = irDialog.flatAverageB->isChecked() ? 0 : 1;
755 darkflatCombineMode= irDialog.darkflatAverageB->isChecked() ? 0 : 1;
757 file = irDialog.darkListView->firstChild();
758 while (file)
760 darkFiles << file->text(0);
761 file = file->nextSibling();
764 file = irDialog.flatListView->firstChild();
765 while (file)
767 flatFiles << file->text(0);
768 file = file->nextSibling();
771 file = irDialog.darkflatListView->firstChild();
772 while (file)
774 darkflatFiles << file->text(0);
775 file = file->nextSibling();
778 cbc = new FITSProcessCommand(this);
779 FITSProcess reduc(this, darkFiles, flatFiles, darkflatFiles, darkCombineMode, flatCombineMode, darkflatCombineMode);
780 reduc.reduce();
781 history->addCommand(cbc, false);
782 calculateStats();
783 hbc = new FITSHistogramCommand(this, NULL, FITSImage::FITSLinear, (int) stats.min, (int) stats.max);
784 history->addCommand(hbc);
785 fitsChange();
788 image->destroyTemplateImage();
792 void FITSViewer::BrightContrastDlg()
794 FITSChangeCommand *cbc;
795 image->saveTemplateImage();
796 ContrastBrightnessDlg conbriDlg(this);
798 if (conbriDlg.exec() == QDialog::Rejected)
800 image->reLoadTemplateImage();
801 image->zoomToCurrent();
803 else
805 memcpy(imgBuffer , conbriDlg.localImgBuffer, stats.width * stats.height * 4);
806 free(conbriDlg.localImgBuffer);
807 fitsChange();
808 image->update();
809 cbc = new FITSChangeCommand(this, CONTRAST_BRIGHTNESS, image->displayImage, image->templateImage);
810 history->addCommand(cbc, false);
814 image->destroyTemplateImage();
818 void FITSViewer::imageHistogram()
821 /*FITSHistogramCommand *histC;
822 unsigned int * backupBuf = (unsigned int *) malloc (image->width * image->height * sizeof(unsigned int));
823 if (backBuf == NULL)
825 KMessageBox::error(0, i18n("Not enough memory to complete the operation."));
826 return;
828 memcpy(backupBuf, imgBuffer, width * height);*/
830 //image->saveTemplateImage();
832 if (histo == NULL)
834 histo = new FITSHistogram(this);
835 histo->show();
837 else
839 histo->constructHistogram(imgBuffer);
840 histo->updateBoxes();
841 histo->show();
844 /*if (hist.exec() == QDialog::Rejected)
846 if (hist.napply > 0)
847 for (int i=0; i < hist.napply; i++)
848 history->undo();
849 else
851 image->reLoadTemplateImage();
852 image->zoomToCurrent();
854 //free (backupBuf);
856 else
858 if (hist.napply > 0) fitsChange();
859 //histC = new FITSHistogramCommand(this, hist.type, backupBuf, image->displayImage, image->templateImage);
860 //history->addCommand(histC, false);
864 image->destroyTemplateImage();*/
868 void FITSViewer::fitsRestore()
871 Dirty = 0;
872 setCaption(currentURL.fileName());
875 void FITSViewer::fitsChange()
878 Dirty = 1;
880 setCaption(currentURL.fileName() + i18n(" [modified]"));
883 void FITSViewer::fitsStatistics()
885 statForm stat(this);
887 calculateStats();
889 stat.widthOUT->setText(QString("%1").arg(stats.width));
890 stat.heightOUT->setText(QString("%1").arg(stats.height));
891 stat.bitpixOUT->setText(QString("%1").arg(stats.bitpix));
892 stat.maxOUT->setText(QString("%1").arg(stats.max));
893 stat.minOUT->setText(QString("%1").arg(stats.min));
894 stat.atMaxOUT->setText(QString("%1").arg(stats.maxAt));
895 stat.atMinOUT->setText(QString("%1").arg(stats.minAt));
896 stat.meanOUT->setText(QString("%1").arg(stats.average));
897 stat.stddevOUT->setText(QString("%1").arg(stats.stddev));
899 stat.exec();
903 void FITSViewer::fitsHeader()
905 QStringList cards;
906 QString recordList;
907 QString property;
908 int equal, slash;
910 fitsHeaderDialog header(this);
911 header.headerView->setSorting(-1);
912 header.headerView->setColumnAlignment(1, Qt::AlignHCenter);
914 for (unsigned int i=0; i < record.count(); i++)
916 recordList = record[i];
917 //recordList = QString((char *) record);
919 for (int j=0; j < FITS_RECORD_SIZE / FITS_CARD_SIZE; j++)
921 property = recordList.left(FITS_CARD_SIZE);
923 equal = property.find('=');
925 if (equal == -1)
927 if (property.contains(" ") != FITS_CARD_SIZE)
928 cards << property << "" << "";
929 recordList.remove(0, FITS_CARD_SIZE);
930 if (property.find("END") != -1)
931 break;
932 else
933 continue;
937 cards << property.left(equal);
938 slash = property.find("'");
939 if (slash != -1)
940 slash = property.find("'", slash + 1) + 1;
941 else
942 slash = property.find('/') - 1;
944 cards << property.mid(equal + 2, slash - (equal + 2)).simplifyWhiteSpace().remove("'");
945 cards << property.mid(slash + 1, FITS_CARD_SIZE - (slash + 1)).simplifyWhiteSpace();
946 recordList.remove(0, FITS_CARD_SIZE);
952 for (int k= cards.count() - 3; k >=0 ; k-=3)
953 new QListViewItem( header.headerView, cards[k], cards[k+1], cards[k+2]);
956 header.exec();
961 FITSChangeCommand::FITSChangeCommand(QWidget * parent, int inType, QImage* newIMG, QImage *oldIMG)
963 viewer = (FITSViewer *) parent;
964 newImage = new QImage();
965 oldImage = new QImage();
966 *newImage = newIMG->copy();
967 *oldImage = oldIMG->copy();
968 type = inType;
971 FITSChangeCommand::~FITSChangeCommand() {}
973 void FITSChangeCommand::execute()
976 viewer->image->displayImage = newImage;
977 viewer->image->zoomToCurrent();
978 viewer->fitsChange();
982 void FITSChangeCommand::unexecute()
985 viewer->image->displayImage = oldImage;
986 viewer->image->zoomToCurrent();
990 QString FITSChangeCommand::name() const
992 switch (type)
994 case FITSViewer::CONTRAST_BRIGHTNESS:
995 return i18n("Brightness/Contrast");
996 break;
997 case FITSViewer::IMAGE_REDUCTION:
998 return i18n("Image Reduction");
999 break;
1000 case FITSViewer::IMAGE_FILTER:
1001 return i18n("Image Filter");
1002 break;
1003 default:
1004 return i18n("unknown");
1005 break;
1011 #include "fitsviewer.moc"