1 /***************************************************************************
2 FITSViewer.cpp - A FITSViewer for KStars
4 begin : Thu Jan 22 2004
5 copyright : (C) 2004 by Jasem Mutlaq
6 email : mutlaqja@ikarustech.com
7 ***************************************************************************/
9 /***************************************************************************
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. *
16 * Some code fragments were adapted from Peter Kirchgessner's FITS plugin*
17 * See http://members.aol.com/pkirchg for more details. *
18 ***************************************************************************/
22 #include <kmessagebox.h>
23 #include <kfiledialog.h>
28 #include <kapplication.h>
30 #include <ktempfile.h>
31 #include <kimageeffect.h>
33 #include <kprogress.h>
34 #include <kstatusbar.h>
36 #include <klineedit.h>
37 #include <klistview.h>
42 #include <qstringlist.h>
43 #include <qlistview.h>
44 #include <qradiobutton.h>
45 #include <qclipboard.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"
59 #include "imagereductiondlg.h"
60 #include "fitsheaderdialog.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
)
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 */
132 if (KSUtils::openDataFile( tempFile
, "imgreduction.png" ) )
134 new KAction( i18n("Image Reduction"), tempFile
.name(), KShortcut( "Ctrl+R" ), this, SLOT( imageReduction()), actionCollection(), "image_reduce");
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");
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");
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");
169 createGUI("fitsviewer.rc");
171 /* initially resize in accord with KDE rules */
175 FITSViewer::~FITSViewer()
180 bool FITSViewer::initFITS()
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; }
195 /* Set new file caption */
196 setCaption(currentURL
.fileName());
198 /* Get initial statistics */
201 image
->viewport()->resize(image
->viewport()->width() + 5, image
->viewport()->height());
202 image
->viewportResizeEvent(NULL
);
208 void FITSViewer::slotClose()
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
)
221 else if ( ans
== KMessageBox::No
)
229 void FITSViewer::closeEvent(QCloseEvent
*ev
)
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
)
242 else if ( ans
== KMessageBox::No
)
253 void FITSViewer::show_fits_errors()
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
)
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;
272 int width
, height
, bpp
, bitpix
;
274 fp
= fopen (filename
, "rb");
277 KMessageBox::error(0, i18n("Cannot open file for reading"));
282 ifp
= fits_open (filename
, "r");
285 KMessageBox::error(0, i18n("Error during open of FITS file"));
290 KMessageBox::error(0, i18n("FITS file keeps no displayable images"));
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
;
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."));
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
)));
325 for (int i
=0; i
< totalCount
; i
++)
326 buffer
[i
] = tempData
[i
];
330 for (int i
=0; i
< totalCount
; i
++)
332 FITS_GETBITPIX16(tempData
, pixval_16
);
333 buffer
[i
] = pixval_16
;//ntohs(pixval_16);
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
;
350 for (int i
=0; i
< totalCount
; i
++)
352 if (fits_nan_32 (tempData
))
355 FITS_GETBITPIXM32(tempData
, pixval_m32
);
356 buffer
[i
] = pixval_m32
;
362 for (int i
=0; i
< totalCount
; i
++)
364 if (fits_nan_64 (tempData
))
367 FITS_GETBITPIXM64(tempData
, pixval_m64
);
368 buffer
[i
] = pixval_m64
;
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()];
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
)
414 lmin
= imgBuffer
[index
];
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()];
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
)
437 lmax
= imgBuffer
[index
];
444 double FITSViewer::average()
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()
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.
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()
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
)
510 else if ( ans
== KMessageBox::No
)
514 KURL fileURL
= KFileDialog::getOpenURL( QDir::homeDirPath(), "*.fits *.fit *.fts|Flexible Image Transport System");
516 if (fileURL
.isEmpty())
520 currentURL
= fileURL
;
526 void FITSViewer::fileSave()
531 KURL backupCurrent
= currentURL
;
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;
545 // If no changes made, return.
546 if (Dirty
== 0 && !currentURL
.isEmpty())
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
;
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."));
581 ifp
= fits_open (currentURL
.path().ascii(), "w");
584 KMessageBox::error(0, i18n("Error during open of FITS file."));
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
)
606 for (i
= image
->height
- 1; i
>= 0; i
--)
607 fwrite(image
->displayImage
->scanLine(i
), 1, image
->width
, ifp
->fp
);
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
622 for (i
=0, transCount
= 0; i
< totalCount
; i
+= transCount
)
623 transCount
= fwrite( transData
+ i
, 1, totalCount
- i
, ifp
->fp
);
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
641 for (i
=0, transCount
= 0; i
< totalCount
; i
+= transCount
)
642 transCount
= fwrite( transData
+ i
, 1, totalCount
- i
, ifp
->fp
);
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
660 for (i
=0, transCount
= 0; i
< totalCount
; i
+= transCount
)
661 transCount
= fwrite( transData
+ i
, 1, totalCount
- i
, ifp
->fp
);
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
684 for (i
=0, transCount
= 0; i
< totalCount
; i
+= transCount
)
685 transCount
= fwrite( transData
+ i
, 1, totalCount
- i
, ifp
->fp
);
691 statusBar()->changeItem(i18n("File saved."), 3);
701 QString message
= i18n( "Invalid URL: %1" ).arg( currentURL
.url() );
702 KMessageBox::sorry( 0, message
, i18n( "Invalid URL" ) );
708 void FITSViewer::fileSaveAs()
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];
733 void FITSViewer::imageReduction()
735 FITSProcessCommand
*cbc
;
736 FITSHistogramCommand
*hbc
;
737 QStringList darkFiles
, flatFiles
, darkflatFiles
;
738 int darkCombineMode
= 0 , flatCombineMode
= 0, darkflatCombineMode
=0;
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();
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();
760 darkFiles
<< file
->text(0);
761 file
= file
->nextSibling();
764 file
= irDialog
.flatListView
->firstChild();
767 flatFiles
<< file
->text(0);
768 file
= file
->nextSibling();
771 file
= irDialog
.darkflatListView
->firstChild();
774 darkflatFiles
<< file
->text(0);
775 file
= file
->nextSibling();
778 cbc
= new FITSProcessCommand(this);
779 FITSProcess
reduc(this, darkFiles
, flatFiles
, darkflatFiles
, darkCombineMode
, flatCombineMode
, darkflatCombineMode
);
781 history
->addCommand(cbc
, false);
783 hbc
= new FITSHistogramCommand(this, NULL
, FITSImage::FITSLinear
, (int) stats
.min
, (int) stats
.max
);
784 history
->addCommand(hbc
);
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();
805 memcpy(imgBuffer
, conbriDlg
.localImgBuffer
, stats
.width
* stats
.height
* 4);
806 free(conbriDlg
.localImgBuffer
);
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));
825 KMessageBox::error(0, i18n("Not enough memory to complete the operation."));
828 memcpy(backupBuf, imgBuffer, width * height);*/
830 //image->saveTemplateImage();
834 histo
= new FITSHistogram(this);
839 histo
->constructHistogram(imgBuffer
);
840 histo
->updateBoxes();
844 /*if (hist.exec() == QDialog::Rejected)
847 for (int i=0; i < hist.napply; i++)
851 image->reLoadTemplateImage();
852 image->zoomToCurrent();
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()
872 setCaption(currentURL
.fileName());
875 void FITSViewer::fitsChange()
880 setCaption(currentURL
.fileName() + i18n(" [modified]"));
883 void FITSViewer::fitsStatistics()
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
));
903 void FITSViewer::fitsHeader()
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('=');
927 if (property
.contains(" ") != FITS_CARD_SIZE
)
928 cards
<< property
<< "" << "";
929 recordList
.remove(0, FITS_CARD_SIZE
);
930 if (property
.find("END") != -1)
937 cards
<< property
.left(equal
);
938 slash
= property
.find("'");
940 slash
= property
.find("'", slash
+ 1) + 1;
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]);
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();
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
994 case FITSViewer::CONTRAST_BRIGHTNESS
:
995 return i18n("Brightness/Contrast");
997 case FITSViewer::IMAGE_REDUCTION
:
998 return i18n("Image Reduction");
1000 case FITSViewer::IMAGE_FILTER
:
1001 return i18n("Image Filter");
1004 return i18n("unknown");
1011 #include "fitsviewer.moc"