• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kstars

fitsviewer.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           FITSViewer.cpp  -  A FITSViewer for KStars
00003                              -------------------
00004     begin                : Thu Jan 22 2004
00005     copyright            : (C) 2004 by Jasem Mutlaq
00006     email                : mutlaqja@ikarustech.com
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  *   Some code fragments were adapted from Peter Kirchgessner's FITS plugin*
00017  *   See http://members.aol.com/pkirchg for more details.                  *
00018  ***************************************************************************/
00019 
00020 
00021 #include <klocale.h>
00022 #include <kmessagebox.h>
00023 #include <kfiledialog.h>
00024 #include <kaction.h>
00025 #include <kaccel.h>
00026 #include <kdebug.h>
00027 #include <ktoolbar.h>
00028 #include <kapplication.h>
00029 #include <kpixmap.h> 
00030 #include <ktempfile.h>
00031 #include <kimageeffect.h> 
00032 #include <kmenubar.h>
00033 #include <kprogress.h>
00034 #include <kstatusbar.h>
00035 #include <kcommand.h>
00036 #include <klineedit.h>
00037 #include <klistview.h>
00038 
00039 #include <qfile.h>
00040 #include <qvbox.h>
00041 #include <qcursor.h>
00042 #include <qstringlist.h>
00043 #include <qlistview.h>
00044 #include <qradiobutton.h>
00045 #include <qclipboard.h>
00046 #include <qimage.h>
00047 
00048 #include <math.h>
00049 #include <unistd.h>
00050 #include <stdlib.h>
00051 #include <netinet/in.h>
00052 
00053 #include "fitsviewer.h"
00054 #include "fitsimage.h"
00055 #include "fitsprocess.h"
00056 #include "fitshistogram.h"
00057 #include "conbridlg.h"
00058 #include "statform.h"
00059 #include "imagereductiondlg.h"
00060 #include "fitsheaderdialog.h"
00061 #include "ksutils.h"
00062 #include "Options.h"
00063 
00064 extern int fits_ieee32_intel;
00065 extern int fits_ieee32_motorola;
00066 extern int fits_ieee64_intel;
00067 extern int fits_ieee64_motorola;
00068 
00069 #define FITS_GETBITPIX16(p,val) val = ((p[0] << 8) | (p[1]))
00070 #define FITS_GETBITPIX32(p,val) val = \
00071           ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3])
00072       
00073 #define FITS_GETBITPIXM32(p,val) \
00074  { if (fits_ieee32_intel) {unsigned char uc[4]; \
00075    uc[0] = p[3]; uc[1] = p[2]; uc[2] = p[1]; uc[3] = p[0]; \
00076    val = *(FITS_BITPIXM32 *)uc; } \
00077    else if (fits_ieee32_motorola) { val = *(FITS_BITPIXM32 *)p; } \
00078    else if (fits_ieee64_motorola) {FITS_BITPIXM64 m64; \
00079    unsigned char *uc= (unsigned char *)&m64; \
00080    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; \
00081    val = (FITS_BITPIXM32)m64; } \
00082    else if (fits_ieee64_intel) {FITS_BITPIXM64 i64; \
00083    unsigned char *uc= (unsigned char *)&i64; \
00084    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]; \
00085    val = (FITS_BITPIXM32)i64;}\
00086 }
00087       
00088 #define FITS_GETBITPIXM64(p,val) \
00089  { if (fits_ieee64_intel) {unsigned char uc[8]; \
00090    uc[0] = p[7]; uc[1] = p[6]; uc[2] = p[5]; uc[3] = p[4]; \
00091    uc[4] = p[3]; uc[5] = p[2]; uc[6] = p[1]; uc[7] = p[0]; \
00092    val = *(FITS_BITPIXM64 *)uc; } else val = *(FITS_BITPIXM64 *)p; }      
00093 
00094 FITSViewer::FITSViewer (const KURL *url, QWidget *parent, const char *name)
00095     : KMainWindow (parent, name)
00096 {
00097     image      = NULL;
00098     currentURL = *url;
00099     imgBuffer  = NULL;
00100     histo      = NULL;
00101     Dirty      = 0;
00102     
00103     /* Initiliaze menu actions */
00104     history = new KCommandHistory(actionCollection());
00105     history->setUndoLimit(10);
00106     history->setRedoLimit(10);
00107     history->documentSaved();
00108     connect(history, SIGNAL(documentRestored()), this, SLOT(fitsRestore()));
00109     
00110     /* Setup image widget */    
00111     image = new FITSImage(this);
00112     setCentralWidget(image);
00113    
00114     statusBar()->insertItem("", 0);
00115     statusBar()->setItemFixed(0, 100);
00116     statusBar()->insertItem("", 1);
00117     statusBar()->setItemFixed(1, 100);
00118     statusBar()->insertItem("", 2);
00119     statusBar()->setItemFixed(2, 100);
00120     statusBar()->insertItem(i18n("Welcome to KStars FITS Viewer"), 3, 1, true);
00121     statusBar()->setItemAlignment(3 , Qt::AlignLeft);
00122     
00123     /* FITS initializations */
00124     if (!initFITS())
00125     {
00126      close();
00127      return;
00128     }
00129      
00130     QFile tempFile;
00131     
00132     if (KSUtils::openDataFile( tempFile, "imgreduction.png" ) )
00133     {
00134         new KAction( i18n("Image Reduction"), tempFile.name(), KShortcut( "Ctrl+R" ), this, SLOT( imageReduction()), actionCollection(), "image_reduce");
00135     tempFile.close();
00136     }
00137     else
00138         new KAction( i18n("Image Reduction"), "blend", KShortcut( "Ctrl+R" ), this, SLOT( imageReduction()), actionCollection(), "image_reduce");
00139     
00140     /*if (KSUtils::openDataFile( tempFile, "bricon.png" ) )
00141     {
00142         new KAction( i18n("Brightness/Contrast"), tempFile.name(), KShortcut( "Ctrl+T" ), this, SLOT( BrightContrastDlg()), actionCollection(), "image_brightness_contrast");
00143     tempFile.close();
00144     }
00145     else*/
00146         new KAction( i18n("Brightness/Contrast"), "contrast+", KShortcut( "Ctrl+T" ), this, SLOT( BrightContrastDlg()), actionCollection(), "image_brightness_contrast");
00147     
00148     if (KSUtils::openDataFile( tempFile, "histogram.png" ) )
00149     {
00150         new KAction ( i18n("Histogram"), tempFile.name(), KShortcut("Ctrl+H"), this, SLOT (imageHistogram()), actionCollection(), "image_histogram");
00151     tempFile.close();
00152     }
00153     else
00154         new KAction ( i18n("Histogram"), "wizard", KShortcut("Ctrl+H"), this, SLOT (imageHistogram()), actionCollection(), "image_histogram");
00155     
00156     KStdAction::open(this, SLOT(fileOpen()), actionCollection());   
00157     KStdAction::save(this, SLOT(fileSave()), actionCollection());
00158     KStdAction::saveAs(this, SLOT(fileSaveAs()), actionCollection());
00159     KStdAction::close(this, SLOT(slotClose()), actionCollection());
00160     KStdAction::copy(this, SLOT(fitsCOPY()), actionCollection());
00161     KStdAction::zoomIn(image, SLOT(fitsZoomIn()), actionCollection());
00162     KStdAction::zoomOut(image, SLOT(fitsZoomOut()), actionCollection());
00163     new KAction( i18n( "&Default Zoom" ), "viewmagfit.png", KShortcut( "Ctrl+D" ),
00164         image, SLOT(fitsZoomDefault()), actionCollection(), "zoom_default" );
00165     new KAction( i18n( "Statistics"), "sum", 0, this, SLOT(fitsStatistics()), actionCollection(), "image_stats");
00166     new KAction( i18n( "FITS Header"), "frame_spreadsheet.png", 0, this, SLOT(fitsHeader()), actionCollection(), "fits_editor");
00167     
00168    /* Create GUI */  
00169    createGUI("fitsviewer.rc");
00170      
00171    /* initially resize in accord with KDE rules */
00172    resize(640, 480); 
00173 }
00174 
00175 FITSViewer::~FITSViewer()
00176 {
00177    free(imgBuffer);
00178 }
00179 
00180 bool  FITSViewer::initFITS()
00181 {
00182 
00183     free(imgBuffer);
00184     imgBuffer = NULL;
00185     image->clearMem();
00186     
00187   /* Load image into buffer */
00188     if ( (imgBuffer = loadData (currentURL.path().ascii(), imgBuffer)) == NULL)  { close(); return false; }
00189     /* Display image in the central widget */
00190     if (image->loadFits(currentURL.path().ascii()) == -1) { close(); return false; }
00191 
00192     /* Clear history */
00193     history->clear();
00194     
00195     /* Set new file caption */
00196     setCaption(currentURL.fileName());
00197     
00198     /* Get initial statistics */
00199     calculateStats();
00200     
00201     image->viewport()->resize(image->viewport()->width() + 5, image->viewport()->height());
00202     image->viewportResizeEvent(NULL);
00203     
00204     return true;
00205 
00206 }
00207 
00208 void FITSViewer::slotClose()
00209 {
00210 
00211   if (Dirty)
00212   {
00213     
00214   QString caption = i18n( "Save Changes to FITS?" );
00215         QString message = i18n( "The current FITS file has unsaved changes.  Would you like to save before closing it?" );
00216         int ans = KMessageBox::warningYesNoCancel( 0, message, caption, KStdGuiItem::save(), KStdGuiItem::discard() );
00217         if ( ans == KMessageBox::Yes )
00218             fileSave(); 
00219         else if ( ans == KMessageBox::No ) 
00220             fitsRestore();
00221    }
00222    
00223    if (Dirty == 0)
00224     close();
00225 }
00226 
00227 void FITSViewer::closeEvent(QCloseEvent *ev)
00228 {
00229 
00230   if (Dirty)
00231   {
00232     
00233   QString caption = i18n( "Save Changes to FITS?" );
00234         QString message = i18n( "The current FITS file has unsaved changes.  Would you like to save before closing it?" );
00235         int ans = KMessageBox::warningYesNoCancel( 0, message, caption, KStdGuiItem::save(), KStdGuiItem::discard() );
00236         if ( ans == KMessageBox::Yes )
00237             fileSave(); 
00238         else if ( ans == KMessageBox::No ) 
00239             fitsRestore();
00240    }
00241    
00242    if (Dirty == 0)
00243     ev->accept();
00244    else 
00245     ev->ignore();
00246 
00247 }
00248 
00249 void FITSViewer::show_fits_errors()
00250 {
00251   char *msg;
00252   /* Write out error messages of FITS-Library */
00253   while ((msg = fits_get_error ()) != NULL)
00254      KMessageBox::error(0, msg);
00255 }
00256 
00257 float * FITSViewer::loadData(const char *filename, float *buffer)
00258 {
00259   FILE *fp;
00260   FITS_FILE *ifp;
00261   FITS_HDU_LIST *hdulist;
00262   unsigned char *tempData, *tempDataPtr;
00263   register FITS_BITPIX16  pixval_16  =0;
00264   register FITS_BITPIX32  pixval_32  =0;
00265   register FITS_BITPIXM32 pixval_m32 =0;
00266   register FITS_BITPIXM64 pixval_m64 =0;
00267   int totalCount;
00268   int width, height, bpp, bitpix;
00269  
00270  fp = fopen (filename, "rb");
00271  if (!fp)
00272  {
00273    KMessageBox::error(0, i18n("Cannot open file for reading"));
00274    return (NULL);
00275  }
00276  fclose (fp);
00277 
00278  ifp = fits_open (filename, "r");
00279  if (ifp == NULL)
00280  {
00281    KMessageBox::error(0, i18n("Error during open of FITS file"));
00282    return (NULL);
00283  }
00284  if (ifp->n_pic <= 0)
00285  {
00286    KMessageBox::error(0, i18n("FITS file keeps no displayable images"));
00287    fits_close (ifp);
00288    return (NULL);
00289  }
00290   
00291   // We only deal with 1 image in a FITS for now.
00292   hdulist = fits_seek_image (ifp, 1);
00293   if (hdulist == NULL) return (NULL);
00294   
00295   width  = hdulist->naxisn[0]; 
00296   height = hdulist->naxisn[1];
00297   
00298   totalCount = width * height;
00299   
00300   bpp    = hdulist->bpp;
00301   bitpix = hdulist->bitpix;
00302   
00303   buffer           = (float          *) malloc (height * width * sizeof(float)); 
00304   tempData         = (unsigned char  *) malloc (height * width * bpp * sizeof(unsigned char));
00305   if (buffer == NULL || tempData == NULL)
00306   {
00307     KMessageBox::error(0, i18n("Not enough memory to load FITS."));
00308     return (NULL);
00309   }
00310   tempDataPtr      = tempData;
00311   
00312   if (fread(tempData, 1, width * height * bpp, ifp->fp) != (unsigned int) (width * height * bpp))
00313   {
00314     KMessageBox::error(0, i18n("Unable to read FITS data from file. %1.\n").arg(strerror(errno)));
00315     return (NULL);
00316   }
00317   
00318   switch (bitpix)
00319   {
00320    case 8:
00321     for (int i=0; i < totalCount; i++)
00322       buffer[i] = tempData[i];
00323     break;
00324     
00325    case 16:
00326     for (int i=0; i < totalCount ; i++)
00327     {
00328        FITS_GETBITPIX16(tempData, pixval_16);
00329        buffer[i] = pixval_16;//ntohs(pixval_16);
00330        tempData+=2;
00331      }
00332      break;
00333       
00334    case 32:
00335    for (int i=0; i < totalCount ; i++)
00336     {
00337     FITS_GETBITPIX32(tempData, pixval_32);
00338     //pixval_32 = ntohl(pixval_32);
00339     if (isnan(pixval_32)) pixval_32 = 0;
00340     buffer[i] = pixval_32;
00341     tempData+=4;
00342    }
00343     break;
00344     
00345    case -32:
00346    for (int i=0; i < totalCount ; i++)
00347     {
00348     if (fits_nan_32 (tempData))
00349      pixval_m32 = 0;
00350     else
00351      FITS_GETBITPIXM32(tempData, pixval_m32);
00352     buffer[i] = pixval_m32;    
00353     tempData+=4;
00354     }
00355     break;
00356     
00357     case -64:
00358     for (int i=0; i < totalCount ; i++)
00359     {
00360     if (fits_nan_64 (tempData))
00361      pixval_m64 = 0;
00362     else
00363      FITS_GETBITPIXM64(tempData, pixval_m64);
00364     buffer[i] = pixval_m64;
00365     tempData+=8;
00366    }
00367     break;
00368   }
00369  
00370   fits_close(ifp);
00371   free(tempDataPtr); 
00372   return buffer;                                              
00373 
00374 }
00375 
00376 void FITSViewer::calculateStats()
00377 {
00378   /*kdDebug() << "Calculating statistics..." << endl;*/
00379   stats.min     = min(stats.minAt);
00380   stats.max     = max(stats.maxAt);
00381   stats.average = average();
00382   stats.stddev  = stddev();
00383   stats.bitpix  = image->bitpix;
00384   stats.width   = image->width;
00385   stats.height  = image->height;
00386   
00387   /*kdDebug() << "Min: " << stats.min << " - Max: " << stats.max << endl;
00388   kdDebug() << "Average: " << stats.average << " - stddev: " << stats.stddev << endl;
00389   kdDebug() << "Width: " << stats.width << " - Height " << stats.height << " - bitpix " << stats.bitpix << endl;*/
00390   
00391   statusBar()->changeItem( QString("%1 x %2").arg( (int) stats.width).arg( (int) stats.height), 2);
00392 
00393 }
00394 
00395 double FITSViewer::min(int & minIndex)
00396 {
00397   if (!imgBuffer) return -1;
00398   int width   = image->currentRect.width();
00399   int height  = image->currentRect.height();
00400   double lmin = imgBuffer[image->currentRect.y() * width + image->currentRect.x()];
00401   int index=0; 
00402   
00403   for (int i= image->currentRect.y() ; i < height; i++)
00404     for (int j= image->currentRect.x(); j < width; j++)
00405     {
00406        index = (i * width) + j;
00407        if (imgBuffer[index] < lmin)
00408        {
00409          minIndex = index;
00410          lmin = imgBuffer[index];
00411        }
00412        
00413     }
00414     
00415     return lmin;
00416 }
00417 
00418 double FITSViewer::max(int & maxIndex)
00419 {
00420   if (!imgBuffer) return -1;
00421   int width   = image->currentRect.width();
00422   int height  = image->currentRect.height();
00423   double lmax = imgBuffer[image->currentRect.y() * width + image->currentRect.x()];
00424   int index=0;
00425   
00426   for (int i= image->currentRect.y() ; i < height; i++)
00427     for (int j= image->currentRect.x(); j < width; j++)
00428     {
00429        index = (i * width) + j;
00430        if ( imgBuffer[index] > lmax)
00431        {
00432         maxIndex = index;
00433         lmax = imgBuffer[index];
00434        }
00435     }
00436     
00437     return lmax;
00438 }
00439 
00440 double FITSViewer::average()
00441 {
00442   int index=0;
00443   double sum=0;  
00444   int width  = image->currentRect.width();
00445   int height = image->currentRect.height();
00446   if (!imgBuffer) return -1;
00447   
00448   for (int i= image->currentRect.y() ; i < height; i++)
00449     for (int j= image->currentRect.x(); j < width; j++)
00450     {
00451        index = (i * width) + j;
00452        sum += imgBuffer[index];
00453     }
00454     
00455     return (sum / (width * height ));
00456 }
00457 
00458 double FITSViewer::stddev()
00459 {
00460   int index=0;
00461   double lsum=0;
00462   int width  = image->currentRect.width();
00463   int height = image->currentRect.height();
00464   if (!imgBuffer) return -1;
00465   
00466   for (int i= image->currentRect.y() ; i < height; i++)
00467     for (int j= image->currentRect.x(); j < width; j++)
00468     {
00469        index = (i * width) + j;
00470        lsum += (imgBuffer[index] - stats.average) * (imgBuffer[index] - stats.average);
00471     }
00472     
00473   return (sqrt(lsum/(width * height - 1)));
00474 
00475 }
00476 
00477 void FITSViewer::keyPressEvent (QKeyEvent *ev)
00478 {
00479         //QImage Tempimage = imageList.at(undo+1)->copy();
00480     
00481     ev->accept();  //make sure key press events are captured.
00482     switch (ev->key())
00483     {
00484         //case Key_H    : KImageEffect::contrastHSV(image); break;
00485         //case Key_S    : KImageEffect::sharpen(image); break;
00486         //case Key_B    : KImageEffect::blur(image); break;
00487     
00488         default : ev->ignore();
00489     }
00490     
00491 }
00492 
00493 void FITSViewer::fileOpen()
00494 {
00495 
00496   if (Dirty)
00497   {
00498     
00499   QString caption = i18n( "Save Changes to FITS?" );
00500         QString message = i18n( "The current FITS file has unsaved changes.  Would you like to save before closing it?" );
00501         int ans = KMessageBox::warningYesNoCancel( 0, message, caption, KStdGuiItem::save(), KStdGuiItem::discard() );
00502         if ( ans == KMessageBox::Yes )
00503             fileSave(); 
00504         else if ( ans == KMessageBox::No ) 
00505             fitsRestore();
00506    }
00507    
00508    KURL fileURL = KFileDialog::getOpenURL( QDir::homeDirPath(), "*.fits *.fit *.fts|Flexible Image Transport System");
00509   
00510   if (fileURL.isEmpty())
00511     return;
00512 
00513   
00514   currentURL = fileURL;
00515   
00516   initFITS();
00517 
00518 }
00519 
00520 void FITSViewer::fileSave()
00521 {
00522   
00523   FITS_FILE *ifp;
00524   QString recordList;
00525   KURL backupCurrent = currentURL;
00526   QString bitpixRec;
00527   FITS_BITPIX16  pixval_16  =0;
00528   FITS_BITPIX32  pixval_32  =0;
00529   FITS_BITPIXM32 pixval_m32 =0;
00530   FITS_BITPIXM64 pixval_m64 =0;
00531   unsigned char *transData;
00532   int index=0, i=0, transCount = 0, totalCount= image->width * image->height;
00533   
00534   QString currentDir = Options::fitsSaveDirectory();
00535   
00536   //kdDebug() << "We doing stats BEFORE we save!! " << endl;
00537   //calculateStats();
00538   
00539   // If no changes made, return.
00540   if (Dirty == 0 && !currentURL.isEmpty())
00541     return;
00542   
00543   if (currentURL.isEmpty())
00544   {
00545     currentURL = KFileDialog::getSaveURL( currentDir, "*.fits |Flexible Image Transport System");
00546     // if user presses cancel
00547     if (currentURL.isEmpty())
00548     {
00549       currentURL = backupCurrent;
00550       return;
00551     }
00552     if (currentURL.path().contains('.') == 0) currentURL.setPath(currentURL.path() + ".fits");
00553     
00554     if (QFile::exists(currentURL.path()))
00555         {
00556             int r=KMessageBox::warningContinueCancel(static_cast<QWidget *>(parent()),
00557             i18n( "A file named \"%1\" already exists. "
00558                   "Overwrite it?" ).arg(currentURL.fileName()),
00559             i18n( "Overwrite File?" ),
00560             i18n( "&Overwrite" ) );
00561   
00562              if(r==KMessageBox::Cancel) return;
00563          }
00564    }
00565 
00566   if ( currentURL.isValid() )
00567   {
00568         transData = (unsigned char *) malloc (sizeof(unsigned char) * totalCount * image->bpp);
00569     if (transData == NULL)
00570     {
00571         KMessageBox::error(0, i18n("Error: Low memory. Saving is aborted."));
00572         return;
00573     }
00574   
00575     ifp = fits_open (currentURL.path().ascii(), "w");
00576         if (ifp == NULL)
00577         {
00578           KMessageBox::error(0, i18n("Error during open of FITS file."));
00579           return;
00580         }
00581         
00582     setbuf(ifp->fp, NULL);
00583     
00584     bitpixRec.sprintf("BITPIX  =                    %d /Modified by KStars                               ", image->bitpix);
00585     bitpixRec.truncate(80);
00586     
00587     for (unsigned int j=0; j < record.count(); j++)
00588     {
00589       recordList = record[j];
00590       
00591       if ( (index = recordList.find("BITPIX")) != -1)
00592         recordList.replace(index, FITS_CARD_SIZE, bitpixRec);
00593     
00594       fwrite(recordList.ascii(), 1, FITS_RECORD_SIZE, ifp->fp);
00595         }
00596     
00597     switch (image->bitpix)
00598     {
00599        case 8:
00600         for (i= image->height - 1; i >= 0; i--)
00601         fwrite(image->displayImage->scanLine(i), 1, image->width, ifp->fp);
00602         break;
00603         
00604         
00605        case 16:
00606             for (i= 0, transCount = 0 ; i < totalCount ; i++, transCount += 2)
00607             {
00608                 pixval_16 = (unsigned short) imgBuffer[i];
00609             transData[transCount]   = ((unsigned char*) &pixval_16)[1];
00610             transData[transCount+1] = ((unsigned char*) &pixval_16)[0];
00611         }
00612         // Now we need to write all uchars to file. We have 2 bytes per pixel
00613         transCount = 0;
00614         totalCount *= 2;
00615         
00616         for (i=0, transCount = 0; i < totalCount; i += transCount)
00617            transCount = fwrite( transData + i , 1, totalCount - i, ifp->fp);
00618                 
00619             break;
00620       
00621       case 32:
00622             for (i=0, transCount = 0 ; i < totalCount ; i++, transCount += 4)
00623             {
00624                 pixval_32 = (unsigned int) imgBuffer[i];
00625             transData[transCount]       = ((unsigned char*) &pixval_32)[3];
00626             transData[transCount+1]     = ((unsigned char*) &pixval_32)[2];
00627             transData[transCount+2]     = ((unsigned char*) &pixval_32)[1];
00628             transData[transCount+3]     = ((unsigned char*) &pixval_32)[0];
00629         }
00630         
00631         // Now we need to write all uchars to file. We have 4 bytes per pixel
00632         transCount = 0;
00633         totalCount *= 4;
00634         
00635         for (i=0, transCount = 0; i < totalCount; i += transCount)
00636            transCount = fwrite( transData + i , 1, totalCount - i, ifp->fp);
00637             break;
00638     
00639     case -32:
00640         for (i=0, transCount = 0 ; i < totalCount ; i++, transCount += 4)
00641             {
00642                 pixval_m32 = imgBuffer[i];
00643             transData[transCount]       = ((unsigned char*) &pixval_m32)[3];
00644             transData[transCount+1]     = ((unsigned char*) &pixval_m32)[2];
00645             transData[transCount+2]     = ((unsigned char*) &pixval_m32)[1];
00646             transData[transCount+3]     = ((unsigned char*) &pixval_m32)[0];
00647             
00648         }
00649         
00650         // Now we need to write all uchars to file. We have 4 bytes per pixel
00651         transCount = 0;
00652         totalCount *= 4;
00653         
00654         for (i=0, transCount = 0; i < totalCount; i += transCount)
00655            transCount = fwrite( transData + i , 1, totalCount - i, ifp->fp);
00656         
00657             break;
00658     
00659         case -64:
00660             for (i=0, transCount = 0 ; i < totalCount ; i++, transCount += 8)
00661             {
00662                 pixval_m64 = imgBuffer[i];
00663             transData[transCount]   = 0;
00664             transData[transCount+1] = 0;
00665             transData[transCount+2] = 0;
00666             transData[transCount+3] = 0;
00667             transData[transCount+4] = ((unsigned char*) &pixval_m32)[3];
00668             transData[transCount+5] = ((unsigned char*) &pixval_m32)[2];
00669             transData[transCount+6] = ((unsigned char*) &pixval_m32)[1];
00670             transData[transCount+7] = ((unsigned char*) &pixval_m32)[0];
00671             
00672         }
00673         
00674         // Now we need to write all uchars to file. We have 4 bytes per pixel
00675         transCount = 0;
00676         totalCount *= 8;
00677         
00678         for (i=0, transCount = 0; i < totalCount; i += transCount)
00679            transCount = fwrite( transData + i , 1, totalCount - i, ifp->fp);
00680             break;  
00681     }
00682         
00683     fits_close(ifp);
00684     
00685     statusBar()->changeItem(i18n("File saved."), 3);
00686     
00687     free(transData);
00688     Dirty = 0;
00689     history->clear();
00690     fitsRestore();
00691     //updateImgBuffer();
00692   }
00693   else
00694   {
00695         QString message = i18n( "Invalid URL: %1" ).arg( currentURL.url() );
00696         KMessageBox::sorry( 0, message, i18n( "Invalid URL" ) );
00697   }
00698     
00699 
00700 }
00701 
00702 void FITSViewer::fileSaveAs()
00703 {
00704   
00705   currentURL = "";
00706   fileSave();
00707 }
00708 
00709 void FITSViewer::fitsCOPY()
00710 {
00711    kapp->clipboard()->setImage(*image->displayImage);
00712 }
00713 
00714 void FITSViewer::updateImgBuffer()
00715 {
00716   int width = image->width;
00717   int height = image->height;
00718   
00719   for (int i=0; i < height; i++)
00720     for (int j=0; j < width; j++)
00721        imgBuffer[i * width + j] = (int) *(image->displayImage->scanLine(height - i - 1) + j);
00722        //image->reducedImgBuffer[i * width + j];
00723 
00724    calculateStats();
00725 }
00726 
00727 void FITSViewer::imageReduction()
00728 {
00729   FITSProcessCommand *cbc;
00730   FITSHistogramCommand *hbc;
00731   QStringList darkFiles, flatFiles, darkflatFiles;
00732   int darkCombineMode = 0 , flatCombineMode = 0, darkflatCombineMode =0;
00733   QListViewItem *file;
00734   
00735   image->saveTemplateImage();
00736   ImageReductionDlg irDialog(this);
00737      
00738   if (irDialog.exec() == QDialog::Accepted)
00739   {
00740     if (irDialog.darkListView->childCount() == 0 && 
00741         irDialog.flatListView->childCount() == 0)
00742     {
00743      image->destroyTemplateImage();
00744      return;
00745     }
00746      
00747     darkCombineMode    = irDialog.darkAverageB->isChecked() ? 0 : 1;
00748     flatCombineMode    = irDialog.flatAverageB->isChecked() ? 0 : 1;
00749     darkflatCombineMode= irDialog.darkflatAverageB->isChecked() ? 0 : 1;
00750      
00751     file = irDialog.darkListView->firstChild();
00752     while (file)
00753     {
00754       darkFiles << file->text(0);
00755       file = file->nextSibling();
00756     }
00757     
00758     file = irDialog.flatListView->firstChild();
00759     while (file)
00760     {
00761       flatFiles << file->text(0);
00762       file = file->nextSibling();
00763     }
00764     
00765     file = irDialog.darkflatListView->firstChild();
00766     while (file)
00767     {
00768       darkflatFiles << file->text(0);
00769       file = file->nextSibling();
00770     }
00771       
00772       cbc = new FITSProcessCommand(this);
00773       FITSProcess reduc(this, darkFiles, flatFiles, darkflatFiles, darkCombineMode, flatCombineMode, darkflatCombineMode);
00774       reduc.reduce();
00775       history->addCommand(cbc, false);
00776       calculateStats();
00777       hbc = new FITSHistogramCommand(this, NULL, FITSImage::FITSLinear, (int) stats.min, (int) stats.max);
00778       history->addCommand(hbc);
00779       fitsChange();
00780   }
00781   
00782   image->destroyTemplateImage();
00783 
00784 }
00785 
00786 void FITSViewer::BrightContrastDlg()
00787 {
00788   FITSChangeCommand *cbc;
00789   image->saveTemplateImage();
00790   ContrastBrightnessDlg conbriDlg(this);
00791     
00792   if (conbriDlg.exec() == QDialog::Rejected)
00793   {
00794     image->reLoadTemplateImage();
00795     image->zoomToCurrent();
00796   }
00797   else
00798   {
00799     memcpy(imgBuffer , conbriDlg.localImgBuffer, stats.width * stats.height * 4);
00800     free(conbriDlg.localImgBuffer);
00801     fitsChange();
00802     image->update();
00803     cbc = new FITSChangeCommand(this, CONTRAST_BRIGHTNESS, image->displayImage, image->templateImage);
00804     history->addCommand(cbc, false);
00805 
00806   }
00807   
00808   image->destroyTemplateImage();
00809     
00810 }
00811 
00812 void FITSViewer::imageHistogram()
00813 {
00814 
00815   /*FITSHistogramCommand *histC;
00816   unsigned int * backupBuf = (unsigned int *) malloc (image->width * image->height * sizeof(unsigned int));
00817   if (backBuf == NULL)
00818   {
00819        KMessageBox::error(0, i18n("Not enough memory to complete the operation."));
00820        return;
00821   }
00822   memcpy(backupBuf, imgBuffer, width * height);*/
00823    
00824   //image->saveTemplateImage();
00825   
00826   if (histo == NULL)
00827   {
00828     histo = new FITSHistogram(this);
00829     histo->show();
00830   }
00831   else
00832   {
00833     histo->constructHistogram(imgBuffer);
00834     histo->updateBoxes();
00835     histo->show();
00836   }
00837     
00838   /*if (hist.exec() == QDialog::Rejected)
00839   {
00840     if (hist.napply > 0)
00841       for (int i=0; i < hist.napply; i++)
00842         history->undo();
00843     else
00844     {
00845         image->reLoadTemplateImage();
00846         image->zoomToCurrent();
00847     }
00848     //free (backupBuf);
00849   }
00850   else
00851   {
00852     if (hist.napply > 0) fitsChange();
00853     //histC = new FITSHistogramCommand(this, hist.type, backupBuf, image->displayImage, image->templateImage);
00854     //history->addCommand(histC, false);
00855 
00856   }
00857   
00858   image->destroyTemplateImage();*/
00859   
00860 }
00861 
00862 void FITSViewer::fitsRestore() 
00863 {
00864  
00865  Dirty = 0;
00866  setCaption(currentURL.fileName());
00867  }
00868 
00869 void FITSViewer::fitsChange() 
00870 {
00871  
00872  Dirty = 1;
00873  
00874  setCaption(currentURL.fileName() + i18n(" [modified]"));
00875 }
00876 
00877 void FITSViewer::fitsStatistics()
00878 {
00879   statForm stat(this);
00880   
00881   calculateStats();
00882   
00883   stat.widthOUT->setText(QString("%1").arg(stats.width));
00884   stat.heightOUT->setText(QString("%1").arg(stats.height));
00885   stat.bitpixOUT->setText(QString("%1").arg(stats.bitpix));
00886   stat.maxOUT->setText(QString("%1").arg(stats.max));
00887   stat.minOUT->setText(QString("%1").arg(stats.min));
00888   stat.atMaxOUT->setText(QString("%1").arg(stats.maxAt));
00889   stat.atMinOUT->setText(QString("%1").arg(stats.minAt));
00890   stat.meanOUT->setText(QString("%1").arg(stats.average));
00891   stat.stddevOUT->setText(QString("%1").arg(stats.stddev));
00892   
00893   stat.exec();
00894 
00895 }
00896 
00897 void FITSViewer::fitsHeader()
00898 {
00899    QStringList cards;
00900    QString recordList;
00901    QString property;
00902    int equal, slash;
00903 
00904    fitsHeaderDialog header(this);
00905    header.headerView->setSorting(-1);
00906    header.headerView->setColumnAlignment(1, Qt::AlignHCenter);
00907    
00908    for (unsigned int i=0; i < record.count(); i++)
00909    {
00910      recordList = record[i];
00911      //recordList = QString((char *) record);
00912    
00913     for (int j=0; j < FITS_RECORD_SIZE / FITS_CARD_SIZE; j++)
00914     {
00915                property = recordList.left(FITS_CARD_SIZE);
00916            
00917            equal = property.find('=');
00918            
00919            if (equal == -1)
00920            {
00921             if (property.contains(" ") != FITS_CARD_SIZE)
00922                 cards << property << "" << "";
00923          recordList.remove(0, FITS_CARD_SIZE);
00924          if (property.find("END") != -1)
00925           break;
00926          else
00927           continue;
00928            }
00929            
00930            
00931                cards << property.left(equal);
00932                slash = property.find("'");
00933                if (slash != -1)
00934             slash = property.find("'", slash + 1) + 1;
00935                else
00936             slash = property.find('/') - 1;
00937        
00938             cards << property.mid(equal + 2, slash - (equal + 2)).simplifyWhiteSpace().remove("'");
00939             cards << property.mid(slash + 1, FITS_CARD_SIZE - (slash + 1)).simplifyWhiteSpace();
00940         recordList.remove(0, FITS_CARD_SIZE);
00941         
00942     }
00943     
00944    }
00945    
00946    for (int k= cards.count() - 3; k >=0 ; k-=3)
00947                new QListViewItem( header.headerView, cards[k], cards[k+1], cards[k+2]);
00948   
00949    
00950    header.exec();
00951 
00952 }
00953 
00954 
00955 FITSChangeCommand::FITSChangeCommand(QWidget * parent, int inType, QImage* newIMG, QImage *oldIMG)
00956 {
00957   viewer    = (FITSViewer *) parent;
00958   newImage  = new QImage();
00959   oldImage  = new QImage();
00960   *newImage = newIMG->copy();
00961   *oldImage = oldIMG->copy();
00962   type = inType;
00963 }
00964 
00965 FITSChangeCommand::~FITSChangeCommand() {}
00966             
00967 void FITSChangeCommand::execute()
00968 {
00969 
00970   viewer->image->displayImage = newImage;
00971   viewer->image->zoomToCurrent();
00972   viewer->fitsChange();
00973 
00974 }
00975 
00976 void FITSChangeCommand::unexecute()
00977 {
00978 
00979   viewer->image->displayImage = oldImage;
00980   viewer->image->zoomToCurrent();
00981 
00982 }
00983 
00984 QString FITSChangeCommand::name() const
00985 {
00986    switch (type)
00987    {
00988      case FITSViewer::CONTRAST_BRIGHTNESS:
00989             return i18n("Brightness/Contrast");
00990         break;
00991      case FITSViewer::IMAGE_REDUCTION:
00992             return i18n("Image Reduction");
00993         break;
00994      case FITSViewer::IMAGE_FILTER:
00995             return i18n("Image Filter");
00996         break;
00997      default:
00998             return i18n("unknown");
00999         break;
01000    }
01001 }
01002 
01003 
01004 
01005 #include "fitsviewer.moc"

kstars

Skip menu "kstars"
  • Main Page
  • Modules
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • keduca
  • kstars
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal