moved kdeaccessibility kdeaddons kdeadmin kdeartwork kdebindings kdeedu kdegames...
[kdeedu.git] / kstars / kstars / fitsimage.cpp
blob301ea64be5df16b4b0ca0f14a77c339839152a33
1 /***************************************************************************
2 FITSImage.cpp - FITS Image
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>
36 #include <qfile.h>
37 #include <qvbox.h>
38 #include <qcursor.h>
39 #include <qpixmap.h>
40 #include <qframe.h>
42 #include <math.h>
43 #include <unistd.h>
44 #include <stdlib.h>
45 #include <netinet/in.h>
47 #include "fitsimage.h"
48 #include "fitsviewer.h"
49 //#include "focusdialog.h"
50 #include "ksutils.h"
52 /* Load info */
53 typedef struct
55 uint replace; /* replacement for blank/NaN-values */
56 uint use_datamin;/* Use DATAMIN/MAX-scaling if possible */
57 uint compose; /* compose images with naxis==3 */
58 } FITSLoadVals;
60 static FITSLoadVals plvals =
62 0, /* Replace with black */
63 0, /* Do autoscale on pixel-values */
64 0 /* Dont compose images */
67 FITSImage::FITSImage(QWidget * parent, const char * name) : QScrollView(parent, name), zoomFactor(1.2)
69 viewer = (FITSViewer *) parent;
70 reducedImgBuffer = NULL;
71 displayImage = NULL;
73 imgFrame = new FITSFrame(this, viewport());
74 addChild(imgFrame);
76 currentZoom = 0.0;
77 grayTable=new QRgb[256];
78 for (int i=0;i<256;i++)
79 grayTable[i]=qRgb(i,i,i);
81 viewport()->setMouseTracking(true);
82 imgFrame->setMouseTracking(true);
86 FITSImage::~FITSImage()
88 free(reducedImgBuffer);
89 delete(displayImage);
92 /*void FITSImage::drawContents ( QPainter * p, int clipx, int clipy, int clipw, int cliph )
94 //kdDebug() << "in draw contents " << endl;
95 //imgFrame->update();
97 }*/
99 /**Bitblt the image onto the viewer widget */
100 /*void FITSImage::paintEvent (QPaintEvent *ev)
102 //kdDebug() << "in paint event " << endl;
103 //bitBlt(imgFrame, 0, 0, &qpix);
106 /* Resize event */
107 void FITSImage::resizeEvent (QResizeEvent */*ev*/)
109 updateScrollBars();
112 void FITSImage::contentsMouseMoveEvent ( QMouseEvent * e )
115 double x,y;
116 bool validPoint = true;
117 if (!displayImage) return;
120 x = e->x();
121 y = e->y();
123 if (imgFrame->x() > 0)
124 x -= imgFrame->x();
126 if (imgFrame->y() > 0)
127 y -= imgFrame->y();
129 y -= 20;
130 x -= 20;
131 //kdDebug() << "X= " << x << " -- Y= " << y << endl;
133 if (currentZoom > 0)
135 x /= pow(zoomFactor, currentZoom);
136 y /= pow(zoomFactor, currentZoom);
138 else if (currentZoom < 0)
140 x *= pow(zoomFactor, abs((int) currentZoom));
141 //kdDebug() << "The X power is " << pow(zoomFactor, abs(currentZoom)) << " -- X final = " << x << endl;
142 y *= pow(zoomFactor, abs((int) currentZoom));
145 if (x < 0 || x > width)
146 validPoint = false;
148 //kdDebug() << "regular x= " << e->x() << " -- X= " << x << " -- imgFrame->x()= " << imgFrame->x() << " - displayImageWidth= " << viewer->displayImage->width() << endl;
151 if (y < 0 || y > height)
152 validPoint = false;
153 else
154 // invert the Y since we read FITS buttom up
155 y = height - y;
157 //kdDebug() << " -- X= " << x << " -- Y= " << y << endl;
159 if (viewer->imgBuffer == NULL)
160 kdDebug() << "viewer buffer is NULL " << endl;
162 if (validPoint)
164 viewer->statusBar()->changeItem(QString("%1 , %2").arg( (int) x).arg( (int) y), 0);
165 viewer->statusBar()->changeItem( KGlobal::locale()->formatNumber( viewer->imgBuffer[(int) (y * width + x)], 3 ), 1 );
166 setCursor(Qt::CrossCursor);
168 else
170 //viewer->statusBar()->changeItem(QString("(X,Y)"), 0);
171 setCursor(Qt::ArrowCursor);
175 void FITSImage::viewportResizeEvent ( QResizeEvent * /*e*/)
177 int w, h, conW, conH, x, y;
178 if (!displayImage) return;
180 w = viewport()->width();
181 h = viewport()->height();
183 conW = (int) (currentWidth + 40);
184 conH = (int) (currentHeight + 40);
186 if ( w > conW )
187 x = (int) ( (w - conW) / 2.);
188 else
189 x = 0;
190 if ( h > conH )
191 y = (int) ( (h - conH) / 2.);
192 else
193 y = 0;
195 // do new movement
196 moveChild( imgFrame, x, y );
200 void FITSImage::reLoadTemplateImage()
202 *displayImage = templateImage->copy();
205 void FITSImage::saveTemplateImage()
207 templateImage = new QImage(displayImage->copy());
210 void FITSImage::destroyTemplateImage()
212 delete (templateImage);
215 void FITSImage::clearMem()
218 free(reducedImgBuffer);
219 delete (displayImage);
220 reducedImgBuffer = NULL;
221 displayImage = NULL;
226 int FITSImage::loadFits (const char *filename)
228 FILE *fp;
229 FITS_FILE *ifp;
230 FITS_HDU_LIST *hdl;
231 // TODO add KStars options for transformation
232 FITS_PIX_TRANSFORM trans;
233 register unsigned char *dest;
234 //register unsigned char *tempBuffer;
235 unsigned char *data;
236 int i, j;
237 double a, b;
238 int err = 0;
240 fp = fopen (filename, "rb");
241 if (!fp)
243 KMessageBox::error(0, i18n("Cannot open file for reading"));
244 return (-1);
246 fclose (fp);
248 ifp = fits_open (filename, "r");
249 if (ifp == NULL)
251 KMessageBox::error(0, i18n("Error during open of FITS file"));
252 return (-1);
254 if (ifp->n_pic <= 0)
256 KMessageBox::error(0, i18n("FITS file keeps no displayable images"));
257 fits_close (ifp);
258 return (-1);
261 //displayImage = new QImage();
262 KProgressDialog fitsProgress(this, 0, i18n("FITS Viewer"), i18n("Loading FITS..."));
264 hdl = fits_seek_image (ifp, 1);
265 if (hdl == NULL) return (-1);
267 width = hdl->naxisn[0];
268 height = hdl->naxisn[1];
269 currentWidth = hdl->naxisn[0];
270 currentHeight = hdl->naxisn[1];
271 bitpix = hdl->bitpix;
272 bpp = hdl->bpp;
274 imgFrame->setGeometry(0, 0, width, height);
276 data = (unsigned char *) malloc (height * width * sizeof(unsigned char));
277 //tempBuffer = (unsigned char *) malloc (height * width * sizeof(unsigned char));
278 if (data == NULL)
280 KMessageBox::error(0, i18n("Not enough memory to load FITS."));
281 return (-1);
284 /* If the transformation from pixel value to */
285 /* data value has been specified, use it */
286 if ( plvals.use_datamin
287 && hdl->used.datamin && hdl->used.datamax
288 && hdl->used.bzero && hdl->used.bscale)
290 a = (hdl->datamin - hdl->bzero) / hdl->bscale;
291 b = (hdl->datamax - hdl->bzero) / hdl->bscale;
292 if (a < b) trans.pixmin = a, trans.pixmax = b;
293 else trans.pixmin = b, trans.pixmax = a;
295 else
297 trans.pixmin = hdl->pixmin;
298 trans.pixmax = hdl->pixmax;
300 trans.datamin = 0.0;
301 trans.datamax = 255.0;
302 trans.replacement = plvals.replace;
303 trans.dsttyp = 'c';
305 //displayImage->create(width, height, 32);
306 currentRect.setX(0);
307 currentRect.setY(0);
308 currentRect.setWidth(width);
309 currentRect.setHeight(height);
311 fitsProgress.progressBar()->setTotalSteps(height);
312 fitsProgress.setMinimumWidth(300);
313 fitsProgress.show();
315 delete (displayImage);
317 displayImage = new QImage(width, height, 8, 256, QImage::IgnoreEndian);
318 for (int i=0; i < 256; i++)
319 displayImage->setColor(i, grayTable[i]);
320 //displayImage = new QImage();
321 //displayImage->create(width, height, 32);
324 /* FITS stores images with bottom row first. Therefore we have */
325 /* to fill the image from bottom to top. */
326 dest = data + height * width;
328 for (i = height - 1; i >= 0 ; i--)
330 /* Read FITS line */
331 dest -= width;
332 if (fits_read_pixel (ifp, hdl, width, &trans, dest) != width)
334 err = 1;
335 break;
338 //for (j=0; j < width; j++)
340 //val = dest[j];
341 //displayImage->setPixel(j, i, qRgb(val, val, val));
343 for (j = 0 ; j < width; j++)
344 displayImage->setPixel(j, i, dest[j]);
346 fitsProgress.progressBar()->setProgress(height - i);
349 reducedImgBuffer = data;
350 convertImageToPixmap();
351 viewportResizeEvent(NULL);
353 if (err)
354 KMessageBox::error(0, i18n("EOF encountered on reading."));
356 fits_record_list * FRList = hdl->header_record_list;
357 while (FRList != NULL)
359 viewer->record << QString((char *) FRList->data);
360 FRList = FRList->next_record;
362 //memcpy(viewer->record, hdl->header_record_list->data , FITS_RECORD_SIZE);
364 fits_close(ifp);
365 return (err ? -1 : 0);
368 void FITSImage::convertImageToPixmap()
370 qpix = kpix.convertToPixmap ( *(displayImage) );
373 void FITSImage::zoomToCurrent()
376 double cwidth, cheight;
378 if (currentZoom >= 0)
380 cwidth = ((double) displayImage->width()) * pow(zoomFactor, currentZoom) ;
381 cheight = ((double) displayImage->height()) * pow(zoomFactor, currentZoom);
383 else
385 cwidth = ((double) displayImage->width()) / pow(zoomFactor, abs((int) currentZoom)) ;
386 cheight = ((double) displayImage->height()) / pow(zoomFactor, abs((int) currentZoom));
389 if (cwidth != displayImage->width() || cheight != displayImage->height())
391 qpix = kpix.convertToPixmap (displayImage->smoothScale( (int) cwidth, (int) cheight));
392 //imgFrame->resize( (int) width, (int) height);
393 viewportResizeEvent (NULL);
394 imgFrame->update();
396 else
398 qpix = kpix.convertToPixmap ( *displayImage );
399 imgFrame->update();
405 void FITSImage::fitsZoomIn()
407 currentZoom++;
408 viewer->actionCollection()->action("view_zoom_out")->setEnabled (true);
409 if (currentZoom > 5)
410 viewer->actionCollection()->action("view_zoom_in")->setEnabled (false);
412 currentWidth *= zoomFactor; //pow(zoomFactor, abs(currentZoom)) ;
413 currentHeight *= zoomFactor; //pow(zoomFactor, abs(currentZoom));
415 //kdDebug() << "Current width= " << currentWidth << " -- Current height= " << currentHeight << endl;
417 qpix = kpix.convertToPixmap (displayImage->smoothScale( (int) currentWidth, (int) currentHeight));
418 imgFrame->resize( (int) currentWidth, (int) currentHeight);
420 update();
421 viewportResizeEvent (NULL);
422 //updateScrollBars();
425 void FITSImage::fitsZoomOut()
427 currentZoom--;
428 if (currentZoom < -5)
429 viewer->actionCollection()->action("view_zoom_out")->setEnabled (false);
430 viewer->actionCollection()->action("view_zoom_in")->setEnabled (true);
432 currentWidth /= zoomFactor; //pow(zoomFactor, abs(currentZoom));
433 currentHeight /= zoomFactor;//pow(zoomFactor, abs(currentZoom));
435 qpix = kpix.convertToPixmap (displayImage->smoothScale( (int) currentWidth, (int) currentHeight));
436 imgFrame->resize( (int) currentWidth, (int) currentHeight);
438 update();
439 viewportResizeEvent (NULL);
440 //updateScrollBars();
443 void FITSImage::fitsZoomDefault()
446 viewer->actionCollection()->action("view_zoom_out")->setEnabled (true);
447 viewer->actionCollection()->action("view_zoom_in")->setEnabled (true);
449 currentZoom = 0;
450 currentWidth = width;
451 currentHeight = height;
453 qpix = kpix.convertToPixmap (*displayImage);
454 imgFrame->resize( (int) currentWidth, (int) currentHeight);
456 update();
457 viewportResizeEvent (NULL);
458 //updateScrollBars();
462 FITSFrame::FITSFrame(FITSImage * img, QWidget * parent, const char * name) : QFrame(parent, name, Qt::WNoAutoErase)
464 image = img;
465 setPaletteBackgroundColor(image->viewport()->paletteBackgroundColor());
468 FITSFrame::~FITSFrame() {}
470 void FITSFrame::paintEvent(QPaintEvent * /*e*/)
473 bitBlt(this, 20, 20, &(image->qpix));
474 resize( (int) (image->currentWidth + 40), (int) (image->currentHeight + 40));
480 #include "fitsimage.moc"