You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeedu/kstars/kstars/fitsimage.cpp

481 lines
12 KiB

/***************************************************************************
FITSImage.cpp - FITS Image
-------------------
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 <klocale.h>
#include <kmessagebox.h>
#include <tdefiledialog.h>
#include <tdeaction.h>
#include <tdeaccel.h>
#include <kdebug.h>
#include <tdetoolbar.h>
#include <tdeapplication.h>
#include <kpixmap.h>
#include <ktempfile.h>
#include <kimageeffect.h>
#include <kmenubar.h>
#include <kprogress.h>
#include <kstatusbar.h>
#include <tqfile.h>
#include <tqvbox.h>
#include <tqcursor.h>
#include <tqpixmap.h>
#include <tqframe.h>
#include <math.h>
#include <unistd.h>
#include <stdlib.h>
#include <netinet/in.h>
#include "fitsimage.h"
#include "fitsviewer.h"
//#include "focusdialog.h"
#include "ksutils.h"
/* Load info */
typedef struct
{
uint replace; /* replacement for blank/NaN-values */
uint use_datamin;/* Use DATAMIN/MAX-scaling if possible */
uint compose; /* compose images with naxis==3 */
} FITSLoadVals;
static FITSLoadVals plvals =
{
0, /* Replace with black */
0, /* Do autoscale on pixel-values */
0 /* Dont compose images */
};
FITSImage::FITSImage(TQWidget * parent, const char * name) : TQScrollView(parent, name), zoomFactor(1.2)
{
viewer = (FITSViewer *) parent;
reducedImgBuffer = NULL;
displayImage = NULL;
imgFrame = new FITSFrame(this, viewport());
addChild(imgFrame);
currentZoom = 0.0;
grayTable=new TQRgb[256];
for (int i=0;i<256;i++)
grayTable[i]=tqRgb(i,i,i);
viewport()->setMouseTracking(true);
imgFrame->setMouseTracking(true);
}
FITSImage::~FITSImage()
{
free(reducedImgBuffer);
delete(displayImage);
}
/*void FITSImage::drawContents ( TQPainter * p, int clipx, int clipy, int clipw, int cliph )
{
//kdDebug() << "in draw contents " << endl;
//imgFrame->update();
}*/
/**Bitblt the image onto the viewer widget */
/*void FITSImage::paintEvent (TQPaintEvent *ev)
{
//kdDebug() << "in paint event " << endl;
//bitBlt(imgFrame, 0, 0, &qpix);
}*/
/* Resize event */
void FITSImage::resizeEvent (TQResizeEvent */*ev*/)
{
updateScrollBars();
}
void FITSImage::contentsMouseMoveEvent ( TQMouseEvent * e )
{
double x,y;
bool validPoint = true;
if (!displayImage) return;
x = e->x();
y = e->y();
if (imgFrame->x() > 0)
x -= imgFrame->x();
if (imgFrame->y() > 0)
y -= imgFrame->y();
y -= 20;
x -= 20;
//kdDebug() << "X= " << x << " -- Y= " << y << endl;
if (currentZoom > 0)
{
x /= pow(zoomFactor, currentZoom);
y /= pow(zoomFactor, currentZoom);
}
else if (currentZoom < 0)
{
x *= pow(zoomFactor, abs((int) currentZoom));
//kdDebug() << "The X power is " << pow(zoomFactor, abs(currentZoom)) << " -- X final = " << x << endl;
y *= pow(zoomFactor, abs((int) currentZoom));
}
if (x < 0 || x > width)
validPoint = false;
//kdDebug() << "regular x= " << e->x() << " -- X= " << x << " -- imgFrame->x()= " << imgFrame->x() << " - displayImageWidth= " << viewer->displayImage->width() << endl;
if (y < 0 || y > height)
validPoint = false;
else
// invert the Y since we read FITS buttom up
y = height - y;
//kdDebug() << " -- X= " << x << " -- Y= " << y << endl;
if (viewer->imgBuffer == NULL)
kdDebug() << "viewer buffer is NULL " << endl;
if (validPoint)
{
viewer->statusBar()->changeItem(TQString("%1 , %2").arg( (int) x).arg( (int) y), 0);
viewer->statusBar()->changeItem( TDEGlobal::locale()->formatNumber( viewer->imgBuffer[(int) (y * width + x)], 3 ), 1 );
setCursor(TQt::CrossCursor);
}
else
{
//viewer->statusBar()->changeItem(TQString("(X,Y)"), 0);
setCursor(TQt::ArrowCursor);
}
}
void FITSImage::viewportResizeEvent ( TQResizeEvent * /*e*/)
{
int w, h, conW, conH, x, y;
if (!displayImage) return;
w = viewport()->width();
h = viewport()->height();
conW = (int) (currentWidth + 40);
conH = (int) (currentHeight + 40);
if ( w > conW )
x = (int) ( (w - conW) / 2.);
else
x = 0;
if ( h > conH )
y = (int) ( (h - conH) / 2.);
else
y = 0;
// do new movement
moveChild( imgFrame, x, y );
}
void FITSImage::reLoadTemplateImage()
{
*displayImage = templateImage->copy();
}
void FITSImage::saveTemplateImage()
{
templateImage = new TQImage(displayImage->copy());
}
void FITSImage::destroyTemplateImage()
{
delete (templateImage);
}
void FITSImage::clearMem()
{
free(reducedImgBuffer);
delete (displayImage);
reducedImgBuffer = NULL;
displayImage = NULL;
}
int FITSImage::loadFits (const char *filename)
{
FILE *fp;
FITS_FILE *ifp;
FITS_HDU_LIST *hdl;
// TODO add KStars options for transformation
FITS_PIX_TRANSFORM trans;
register unsigned char *dest;
//register unsigned char *tempBuffer;
unsigned char *data;
int i, j;
double a, b;
int err = 0;
fp = fopen (filename, "rb");
if (!fp)
{
KMessageBox::error(0, i18n("Cannot open file for reading"));
return (-1);
}
fclose (fp);
ifp = fits_open (filename, "r");
if (ifp == NULL)
{
KMessageBox::error(0, i18n("Error during open of FITS file"));
return (-1);
}
if (ifp->n_pic <= 0)
{
KMessageBox::error(0, i18n("FITS file keeps no displayable images"));
fits_close (ifp);
return (-1);
}
//displayImage = new TQImage();
KProgressDialog fitsProgress(this, 0, i18n("FITS Viewer"), i18n("Loading FITS..."));
hdl = fits_seek_image (ifp, 1);
if (hdl == NULL) return (-1);
width = hdl->naxisn[0];
height = hdl->naxisn[1];
currentWidth = hdl->naxisn[0];
currentHeight = hdl->naxisn[1];
bitpix = hdl->bitpix;
bpp = hdl->bpp;
imgFrame->setGeometry(0, 0, width, height);
data = (unsigned char *) malloc (height * width * sizeof(unsigned char));
//tempBuffer = (unsigned char *) malloc (height * width * sizeof(unsigned char));
if (data == NULL)
{
KMessageBox::error(0, i18n("Not enough memory to load FITS."));
return (-1);
}
/* If the transformation from pixel value to */
/* data value has been specified, use it */
if ( plvals.use_datamin
&& hdl->used.datamin && hdl->used.datamax
&& hdl->used.bzero && hdl->used.bscale)
{
a = (hdl->datamin - hdl->bzero) / hdl->bscale;
b = (hdl->datamax - hdl->bzero) / hdl->bscale;
if (a < b) trans.pixmin = a, trans.pixmax = b;
else trans.pixmin = b, trans.pixmax = a;
}
else
{
trans.pixmin = hdl->pixmin;
trans.pixmax = hdl->pixmax;
}
trans.datamin = 0.0;
trans.datamax = 255.0;
trans.replacement = plvals.replace;
trans.dsttyp = 'c';
//displayImage->create(width, height, 32);
currentRect.setX(0);
currentRect.setY(0);
currentRect.setWidth(width);
currentRect.setHeight(height);
fitsProgress.progressBar()->setTotalSteps(height);
fitsProgress.setMinimumWidth(300);
fitsProgress.show();
delete (displayImage);
displayImage = new TQImage(width, height, 8, 256, TQImage::IgnoreEndian);
for (int i=0; i < 256; i++)
displayImage->setColor(i, grayTable[i]);
//displayImage = new TQImage();
//displayImage->create(width, height, 32);
/* FITS stores images with bottom row first. Therefore we have */
/* to fill the image from bottom to top. */
dest = data + height * width;
for (i = height - 1; i >= 0 ; i--)
{
/* Read FITS line */
dest -= width;
if (fits_read_pixel (ifp, hdl, width, &trans, dest) != width)
{
err = 1;
break;
}
//for (j=0; j < width; j++)
//{
//val = dest[j];
//displayImage->setPixel(j, i, tqRgb(val, val, val));
//}
for (j = 0 ; j < width; j++)
displayImage->setPixel(j, i, dest[j]);
fitsProgress.progressBar()->setProgress(height - i);
}
reducedImgBuffer = data;
convertImageToPixmap();
viewportResizeEvent(NULL);
if (err)
KMessageBox::error(0, i18n("EOF encountered on reading."));
fits_record_list * FRList = hdl->header_record_list;
while (FRList != NULL)
{
viewer->record << TQString((char *) FRList->data);
FRList = FRList->next_record;
}
//memcpy(viewer->record, hdl->header_record_list->data , FITS_RECORD_SIZE);
fits_close(ifp);
return (err ? -1 : 0);
}
void FITSImage::convertImageToPixmap()
{
qpix = kpix.convertToPixmap ( *(displayImage) );
}
void FITSImage::zoomToCurrent()
{
double cwidth, cheight;
if (currentZoom >= 0)
{
cwidth = ((double) displayImage->width()) * pow(zoomFactor, currentZoom) ;
cheight = ((double) displayImage->height()) * pow(zoomFactor, currentZoom);
}
else
{
cwidth = ((double) displayImage->width()) / pow(zoomFactor, abs((int) currentZoom)) ;
cheight = ((double) displayImage->height()) / pow(zoomFactor, abs((int) currentZoom));
}
if (cwidth != displayImage->width() || cheight != displayImage->height())
{
qpix = kpix.convertToPixmap (displayImage->smoothScale( (int) cwidth, (int) cheight));
//imgFrame->resize( (int) width, (int) height);
viewportResizeEvent (NULL);
imgFrame->update();
}
else
{
qpix = kpix.convertToPixmap ( *displayImage );
imgFrame->update();
}
}
void FITSImage::fitsZoomIn()
{
currentZoom++;
viewer->actionCollection()->action("view_zoom_out")->setEnabled (true);
if (currentZoom > 5)
viewer->actionCollection()->action("view_zoom_in")->setEnabled (false);
currentWidth *= zoomFactor; //pow(zoomFactor, abs(currentZoom)) ;
currentHeight *= zoomFactor; //pow(zoomFactor, abs(currentZoom));
//kdDebug() << "Current width= " << currentWidth << " -- Current height= " << currentHeight << endl;
qpix = kpix.convertToPixmap (displayImage->smoothScale( (int) currentWidth, (int) currentHeight));
imgFrame->resize( (int) currentWidth, (int) currentHeight);
update();
viewportResizeEvent (NULL);
//updateScrollBars();
}
void FITSImage::fitsZoomOut()
{
currentZoom--;
if (currentZoom < -5)
viewer->actionCollection()->action("view_zoom_out")->setEnabled (false);
viewer->actionCollection()->action("view_zoom_in")->setEnabled (true);
currentWidth /= zoomFactor; //pow(zoomFactor, abs(currentZoom));
currentHeight /= zoomFactor;//pow(zoomFactor, abs(currentZoom));
qpix = kpix.convertToPixmap (displayImage->smoothScale( (int) currentWidth, (int) currentHeight));
imgFrame->resize( (int) currentWidth, (int) currentHeight);
update();
viewportResizeEvent (NULL);
//updateScrollBars();
}
void FITSImage::fitsZoomDefault()
{
viewer->actionCollection()->action("view_zoom_out")->setEnabled (true);
viewer->actionCollection()->action("view_zoom_in")->setEnabled (true);
currentZoom = 0;
currentWidth = width;
currentHeight = height;
qpix = kpix.convertToPixmap (*displayImage);
imgFrame->resize( (int) currentWidth, (int) currentHeight);
update();
viewportResizeEvent (NULL);
//updateScrollBars();
}
FITSFrame::FITSFrame(FITSImage * img, TQWidget * parent, const char * name) : TQFrame(parent, name, TQt::WNoAutoErase)
{
image = img;
setPaletteBackgroundColor(image->viewport()->paletteBackgroundColor());
}
FITSFrame::~FITSFrame() {}
void FITSFrame::paintEvent(TQPaintEvent * /*e*/)
{
bitBlt(this, 20, 20, &(image->qpix));
resize( (int) (image->currentWidth + 40), (int) (image->currentHeight + 40));
}
#include "fitsimage.moc"