Kstars

fitsview.h
1 /*
2  SPDX-FileCopyrightText: 2003-2017 Jasem Mutlaq <[email protected]>
3  SPDX-FileCopyrightText: 2016-2017 Robert Lancaster <[email protected]>
4 
5  SPDX-License-Identifier: GPL-2.0-or-later
6 */
7 
8 #pragma once
9 
10 #include "fitscommon.h"
11 
12 #include <config-kstars.h>
13 #include "stretch.h"
14 
15 #ifdef HAVE_DATAVISUALIZATION
16 #include "starprofileviewer.h"
17 #endif
18 
19 #include <QFutureWatcher>
20 #include <QPixmap>
21 #include <QScrollArea>
22 #include <QStack>
23 #include <QTimer>
24 #include <QPointer>
25 
26 #ifdef WIN32
27 // avoid compiler warning when windows.h is included after fitsio.h
28 #include <windows.h>
29 #endif
30 
31 #include <fitsio.h>
32 
33 #include <memory>
34 
35 class QAction;
36 class QEvent;
37 class QGestureEvent;
38 class QImage;
39 class QLabel;
40 class QPinchGesture;
41 class QResizeEvent;
42 class QToolBar;
43 
44 class FITSData;
45 class FITSLabel;
46 
47 class FITSView : public QScrollArea
48 {
49  Q_OBJECT
50  Q_PROPERTY(bool suspended MEMBER m_Suspended)
51 
52  public:
53  explicit FITSView(QWidget *parent = nullptr, FITSMode fitsMode = FITS_NORMAL, FITSScale filterType = FITS_NONE);
54  virtual ~FITSView() override;
55 
56  typedef enum {dragCursor, selectCursor, scopeCursor, crosshairCursor } CursorMode;
57 
58  /**
59  * @brief loadFITS Loads FITS data and displays it in a FITSView frame
60  * @param inFilename FITS File name
61  * @note If image is successfully, loaded() signal is emitted, otherwise failed() signal is emitted.
62  * Obtain error by calling lastError()
63  */
64  void loadFile(const QString &inFilename);
65 
66  /**
67  * @brief loadFITSFromData Takes ownership of the FITSData instance passed in and displays it in a FITSView frame
68  * @param data pointer to FITSData objects
69  */
70  bool loadData(const QSharedPointer<FITSData> &data);
71 
72  /**
73  * @brief clearView Reset view to NO IMAGE
74  */
75  void clearData();
76 
77  // Save FITS
78  bool saveImage(const QString &newFilename);
79  // Rescale image lineary from image_buffer, fit to window if desired
80  bool rescale(FITSZoom type);
81 
82  const QSharedPointer<FITSData> &imageData() const
83  {
84  return m_ImageData;
85  }
86 
87  double getCurrentZoom() const
88  {
89  return currentZoom;
90  }
91  const QImage &getDisplayImage() const
92  {
93  return rawImage;
94  }
95  const QPixmap &getDisplayPixmap() const
96  {
97  return displayPixmap;
98  }
99 
100  // Tracking square
101  void setTrackingBoxEnabled(bool enable);
102  bool isTrackingBoxEnabled() const
103  {
104  return trackingBoxEnabled;
105  }
106  QPixmap &getTrackingBoxPixmap(uint8_t margin = 0);
107  void setTrackingBox(const QRect &rect);
108  const QRect &getTrackingBox() const
109  {
110  return trackingBox;
111  }
112 
113  // last error
114  const QString &lastError() const
115  {
116  return m_LastError;
117  }
118 
119  // Overlay
120  virtual void drawOverlay(QPainter *, double scale);
121 
122  // Overlay objects
123  void drawStarFilter(QPainter *, double scale);
124  void drawStarCentroid(QPainter *, double scale);
125  void drawClipping(QPainter *);
126  void drawTrackingBox(QPainter *, double scale);
127  void drawMarker(QPainter *, double scale);
128  void drawCrosshair(QPainter *, double scale);
129 
130 #if !defined(KSTARS_LITE) && defined(HAVE_WCSLIB)
131  void drawEQGrid(QPainter *, double scale);
132 #endif
133  void drawObjectNames(QPainter *painter, double scale);
134  void drawPixelGrid(QPainter *painter, double scale);
135  void drawMagnifyingGlass(QPainter *painter, double scale);
136  bool isImageStretched();
137  bool isCrosshairShown();
138  bool isClippingShown();
139  bool areObjectsShown();
140  bool isEQGridShown();
141  bool isSelectionRectShown();
142  bool isPixelGridShown();
143  bool imageHasWCS();
144 
145  // Setup the graphics.
146  void updateFrame(bool now = false);
147 
148  // Telescope
149  bool isTelescopeActive();
150  void updateScopeButton();
151  void setScopeButton(QAction *action)
152  {
153  centerTelescopeAction = action;
154  }
155 
156  // Events Management
157  void enterEvent(QEvent *event) override;
158  void leaveEvent(QEvent *event) override;
159  CursorMode getCursorMode();
160  void setCursorMode(CursorMode mode);
161  void updateMouseCursor();
162 
163  // Zoom related
164  void cleanUpZoom(QPoint viewCenter = QPoint());
165  QPoint getImagePoint(QPoint viewPortPoint);
166  uint16_t zoomedWidth()
167  {
168  return currentWidth;
169  }
170  uint16_t zoomedHeight()
171  {
172  return currentHeight;
173  }
174  double ZoomFactor() const
175  {
176  return m_ZoomFactor;
177  }
178 
179  // Star Detection
180  QFuture<bool> findStars(StarAlgorithm algorithm = ALGORITHM_CENTROID, const QRect &searchBox = QRect());
181  void toggleStars(bool enable);
182  void searchStars();
183  void setStarsEnabled(bool enable);
184  void setStarsHFREnabled(bool enable);
185  void setStarFilterRange(float const innerRadius, float const outerRadius);
186  int filterStars();
187 
188  // FITS Mode
189  void updateMode(FITSMode fmode);
190  FITSMode getMode()
191  {
192  return mode;
193  }
194 
195  void setFilter(FITSScale newFilter)
196  {
197  filter = newFilter;
198  }
199 
200  void setFirstLoad(bool value);
201 
202  void pushFilter(FITSScale value)
203  {
204  filterStack.push(value);
205  }
206  FITSScale popFilter()
207  {
208  return filterStack.pop();
209  }
210 
211  CursorMode lastMouseMode { selectCursor };
212  bool isStarProfileShown()
213  {
214  return showStarProfile;
215  }
216  // Floating toolbar
217  void createFloatingToolBar();
218 
219  //void setLoadWCSEnabled(bool value);
220 
221  // Returns the params set to stretch the image.
222  StretchParams getStretchParams() const
223  {
224  return stretchParams;
225  }
226 
227  // Returns true if we're automatically generating stretch parameters.
228  // Note: this is not whether we're stretching, that's controlled by stretchImage.
229  bool getAutoStretch() const
230  {
231  return autoStretch;
232  }
233 
234  // Sets the params for stretching. Will also stretch and re-display the image.
235  // This only sets the first channel stretch params. For RGB images, the G&B channel
236  // stretch parameters are a function of the Red input param and the existing RGB params.
237  void setStretchParams(const StretchParams &params);
238 
239  // Sets whether to stretch the image or not.
240  // Will also re-display the image if onOff != stretchImage.
241  void setStretch(bool onOff);
242 
243  // Automatically generates stretch parameters and use them to re-display the image.
244  void setAutoStretchParams();
245 
246  // When sampling is > 1, we will display the image at a lower resolution.
247  // When sampling = 0, reset to the adaptive sampling value
248  void setPreviewSampling(uint8_t value)
249  {
250  if (value == 0)
251  {
252  m_PreviewSampling = m_AdaptiveSampling;
253  m_StretchingInProgress = false;
254  }
255  else
256  {
257  m_PreviewSampling = value * m_AdaptiveSampling;
258  m_StretchingInProgress = true;
259  }
260  }
261 
262  // Returns the number of clipped pixels, if that's being computed.
263  int getNumClipped()
264  {
265  return m_NumClipped;
266  }
267 
268  QRect getSelectionRegion() const
269  {
270  return selectionRectangleRaw;
271  }
272 
273  public slots:
274  void wheelEvent(QWheelEvent *event) override;
275  void resizeEvent(QResizeEvent *event) override;
276  void ZoomIn();
277  void ZoomOut();
278  void ZoomDefault();
279  void ZoomToFit();
280  void updateMagnifyingGlass(int x, int y);
281 
282  // Grids
283  void toggleEQGrid();
284  void toggleObjects();
285  void togglePixelGrid();
286  void toggleCrosshair();
287 
288  //Selection Rectngle
289  void toggleSelectionMode();
290 
291  // Stars
292  void toggleStars();
293  void toggleStarProfile();
294  void viewStarProfile();
295 
296  void centerTelescope();
297 
298  void toggleStretch();
299  void toggleClipping();
300 
301  virtual void processPointSelection(int x, int y);
302  virtual void processMarkerSelection(int x, int y);
303 
304  void move3DTrackingBox(int x, int y);
305  void resizeTrackingBox(int newSize);
306  void processRectangle(QPoint p1, QPoint p2, bool refreshCenter = false);
307  void processRectangleFixed(int s);
308 
309  protected slots:
310  /**
311  * @brief syncWCSState Update toolbar and actions depending on whether WCS is available or not
312  */
313  void syncWCSState();
314 
315  bool event(QEvent *event) override;
316  bool gestureEvent(QGestureEvent *event);
317  void pinchTriggered(QPinchGesture *gesture);
318 
319  protected:
320  double average();
321  double stddev();
322  void calculateMaxPixel(double min, double max);
323  void initDisplayImage();
324 
325  QPointF getPointForGridLabel(QPainter *painter, const QString &str, double scale);
326  bool pointIsInImage(QPointF pt, double scale);
327 
328  void loadInFrame();
329 
330  double getScale();
331 
332  /// selectionRectangleRaw is used to do the calculations, this rectangle remains the same when user changes the zoom
333  QRect selectionRectangleRaw;
334  /// Floating toolbar
335  QToolBar *floatingToolBar { nullptr };
336  /// WCS Future Watcher
337  QFutureWatcher<bool> wcsWatcher;
338  /// FITS Future Watcher
339  QFutureWatcher<bool> fitsWatcher;
340  /// Cross hair
341  QPointF markerCrosshair;
342  /// Pointer to FITSData object
343  QSharedPointer<FITSData> m_ImageData;
344  /// Current zoom level
345  double currentZoom { 0 };
346  // The maximum percent zoom. The value is recalculated in the constructor
347  // based on the amount of physical memory.
348  int zoomMax { 400 };
349  /// Image Buffer if Selection is to be done
350  uint8_t *m_ImageRoiBuffer { nullptr };
351  /// Above buffer size in bytes
352  uint32_t m_ImageRoiBufferSize { 0 };
353 
354  private:
355  bool processData();
356  void doStretch(QImage *outputImage);
357  double scaleSize(double size);
358  bool isLargeImage();
359  void updateFrameLargeImage();
360  void updateFrameSmallImage();
361  bool drawHFR(QPainter * painter, const QString &hfr, int x, int y);
362 
363  QPointer<QLabel> noImageLabel;
364  QPixmap noImage;
365  QPointer<FITSLabel> m_ImageFrame;
366  QVector<QPointF> eqGridPoints;
367 
368  /// Current width due to zoom
369  uint16_t currentWidth { 0 };
370  /// Current height due to zoom
371  uint16_t currentHeight { 0 };
372  /// Image zoom factor
373  const double m_ZoomFactor;
374 
375  // Original full-size image
376  QImage rawImage;
377  // Actual pixmap after all the overlays
378  QPixmap displayPixmap;
379 
380  bool firstLoad { true };
381  bool markStars { false };
382  bool showStarProfile { false };
383  bool showCrosshair { false };
384  bool showObjects { false };
385  bool showEQGrid { false };
386  bool showPixelGrid { false };
387  bool showStarsHFR { false };
388  bool showClipping { false };
389 
390  int m_NumClipped { 0 };
391 
392  bool showSelectionRect { false };
393 
394  // Should the image be displayed in linear (false) or stretched (true).
395  // Initial value controlled by Options::autoStretch.
396  bool stretchImage { false };
397 
398  // When stretching, should we automatically compute parameters.
399  // When first displaying, this should be true, but may be set to false
400  // if the user has overridden the automatically set parameters.
401  bool autoStretch { true };
402 
403  // Params for stretching image.
404  StretchParams stretchParams;
405 
406  // Resolution for display. Sampling=2 means display every other sample.
407  uint8_t m_PreviewSampling { 1 };
408  bool m_StretchingInProgress { false};
409  // Adaptive sampling is based on available RAM
410  uint8_t m_AdaptiveSampling {1};
411 
412  struct
413  {
414  bool used() const
415  {
416  return innerRadius != 0.0f || outerRadius != 1.0f;
417  }
418  float innerRadius { 0.0f };
419  float outerRadius { 1.0f };
420  } starFilter;
421 
422  CursorMode cursorMode { selectCursor };
423  bool zooming { false };
424  int zoomTime { 0 };
425  QPoint zoomLocation;
426 
427  QString filename;
428  FITSMode mode;
429  FITSScale filter;
430  QString m_LastError;
431  QTimer m_UpdateFrameTimer;
432 
433  QStack<FITSScale> filterStack;
434 
435  // Tracking box
436  bool trackingBoxEnabled { false };
437  QRect trackingBox;
438  QPixmap trackingBoxPixmap;
439 
440  // Scope pixmap
441  QPixmap redScopePixmap;
442  // Magenta Scope Pixmap
443  QPixmap magentaScopePixmap;
444 
445  QAction *centerTelescopeAction { nullptr };
446  QAction *toggleEQGridAction { nullptr };
447  QAction *toggleObjectsAction { nullptr };
448  QAction *toggleStarsAction { nullptr };
449  QAction *toggleProfileAction { nullptr };
450  QAction *toggleStretchAction { nullptr };
451 
452  // State for the magnifying glass overlay.
453  int magnifyingGlassX { -1 };
454  int magnifyingGlassY { -1 };
455  bool showMagnifyingGlass { false };
456  bool m_Suspended {false};
457 
458  QMutex updateMutex;
459 
460  //Star Profile Viewer
461 #ifdef HAVE_DATAVISUALIZATION
462  QPointer<StarProfileViewer> starProfileWidget;
463 #endif
464 
465  signals:
466  void newStatus(const QString &msg, FITSBar id);
467  void debayerToggled(bool);
468  void wcsToggled(bool);
469  void actionUpdated(const QString &name, bool enable);
470  void trackingStarSelected(int x, int y);
471  void loaded();
472  void failed(const QString &error);
473  void starProfileWindowClosed();
474  void rectangleUpdated(QRect roi);
475  void setRubberBand(QRect rect);
476  void showRubberBand(bool on = false);
477  void zoomRubberBand(double scale);
478 
479  friend class FITSLabel;
480 };
Q_OBJECTQ_OBJECT
Q_PROPERTY(...)
virtual void leaveEvent(QEvent *event)
virtual void wheelEvent(QWheelEvent *e) override
virtual void enterEvent(QEvent *event)
virtual void resizeEvent(QResizeEvent *) override
QFuture< void > filter(Sequence &sequence, KeepFunctor filterFunction)
virtual bool event(QEvent *e) override
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Mon Aug 15 2022 04:04:01 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.