File indexing completed on 2024-04-21 14:45:47
0001 /* 0002 SPDX-FileCopyrightText: 2004 Jasem Mutlaq <mutlaqja@ikarustech.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 0006 Some code fragments were adapted from Peter Kirchgessner's FITS plugin 0007 SPDX-FileCopyrightText: Peter Kirchgessner <http://members.aol.com/pkirchg> 0008 */ 0009 0010 #pragma once 0011 0012 #include "config-kstars.h" 0013 0014 // From StellarSolver 0015 #ifdef HAVE_STELLARSOLVER 0016 #include <structuredefinitions.h> 0017 #else 0018 #include "structuredefinitions.h" 0019 #endif 0020 0021 #include "kstarsdatetime.h" 0022 #include "bayer.h" 0023 #include "skybackground.h" 0024 #include "fitscommon.h" 0025 #include "fitsstardetector.h" 0026 #include "auxiliary/imagemask.h" 0027 0028 #ifdef WIN32 0029 // This header must be included before fitsio.h to avoid compiler errors with Visual Studio 0030 #include <windows.h> 0031 #endif 0032 0033 #include <fitsio.h> 0034 0035 #include <QFuture> 0036 #include <QObject> 0037 #include <QRect> 0038 #include <QVariant> 0039 #include <QTemporaryFile> 0040 0041 #ifndef KSTARS_LITE 0042 #include <kxmlguiwindow.h> 0043 #ifdef HAVE_WCSLIB 0044 #include <wcs.h> 0045 #endif 0046 #endif 0047 0048 #include "fitsskyobject.h" 0049 0050 class QProgressDialog; 0051 0052 class SkyPoint; 0053 class FITSHistogramData; 0054 class Edge; 0055 0056 class FITSData : public QObject 0057 { 0058 Q_OBJECT 0059 0060 // Name of FITS file 0061 Q_PROPERTY(QString filename READ filename) 0062 // Extension 0063 Q_PROPERTY(QString extension READ extension) 0064 // Size of file in bytes 0065 Q_PROPERTY(qint64 size READ size) 0066 // Width in pixels 0067 Q_PROPERTY(quint16 width READ width) 0068 // Height in pixels 0069 Q_PROPERTY(quint16 height READ height) 0070 // FITS MODE --> Normal, Focus, Guide..etc 0071 Q_PROPERTY(FITSMode mode MEMBER m_Mode) 0072 // 1 channel (grayscale) or 3 channels (RGB) 0073 Q_PROPERTY(quint8 channels READ channels) 0074 // Bits per pixel 0075 Q_PROPERTY(quint8 bpp READ bpp) 0076 // Does FITS have WSC header? 0077 Q_PROPERTY(bool hasWCS READ hasWCS) 0078 // Does FITS have bayer data? 0079 Q_PROPERTY(bool hasDebayer READ hasDebayer) 0080 0081 public: 0082 explicit FITSData(FITSMode fitsMode = FITS_NORMAL); 0083 explicit FITSData(const QSharedPointer<FITSData> &other); 0084 ~FITSData() override; 0085 0086 /** Object to hold FITS Header records */ 0087 struct Record 0088 { 0089 Record() = default; 0090 Record(QString k, QString v, QString c) : key(k), value(v), comment(c) {} 0091 QString key; /** FITS Header Key */ 0092 QVariant value; /** FITS Header Value */ 0093 QString comment; /** FITS Header Comment, if any */ 0094 }; 0095 0096 typedef enum 0097 { 0098 Idle, 0099 Busy, 0100 Success, 0101 Failure 0102 } WCSState; 0103 0104 //////////////////////////////////////////////////////////////////////////////////////// 0105 //////////////////////////////////////////////////////////////////////////////////////// 0106 /// Read and Write file/buffer Functions. 0107 //////////////////////////////////////////////////////////////////////////////////////// 0108 //////////////////////////////////////////////////////////////////////////////////////// 0109 /** 0110 * @brief loadFITS Loading FITS file asynchronously. 0111 * @param inFilename Path to FITS file (or compressed fits.gz) 0112 * @return A QFuture that can be watched until the async operation is complete. 0113 */ 0114 QFuture<bool> loadFromFile(const QString &inFilename); 0115 0116 /** 0117 * @brief loadFITSFromMemory Loading FITS from memory buffer. 0118 * @param buffer The memory buffer containing the fits data. 0119 * @param extension file extension (e.g. "jpg", "fits", "cr2"...etc) 0120 * @param inFilename Set filename metadata, does not load from file. 0121 * @return bool indicating success or failure. 0122 */ 0123 bool loadFromBuffer(const QByteArray &buffer, const QString &extension, const QString &inFilename = QString()); 0124 0125 /** 0126 * @brief parseSolution Parse the WCS solution information from the header into the given struct. 0127 * @param solution Solution structure to fill out. 0128 * @return True if parsing successful, false otherwise. 0129 */ 0130 bool parseSolution(FITSImage::Solution &solution) const; 0131 0132 /* Save FITS or JPG/PNG*/ 0133 bool saveImage(const QString &newFilename); 0134 0135 // Access functions 0136 void clearImageBuffers(); 0137 void setImageBuffer(uint8_t *buffer); 0138 uint8_t const *getImageBuffer() const; 0139 uint8_t *getWritableImageBuffer(); 0140 0141 //////////////////////////////////////////////////////////////////////////////////////// 0142 //////////////////////////////////////////////////////////////////////////////////////// 0143 /// Statistics Functions. 0144 //////////////////////////////////////////////////////////////////////////////////////// 0145 //////////////////////////////////////////////////////////////////////////////////////// 0146 // Calculate stats 0147 void calculateStats(bool refresh = false, bool roi = false); 0148 void saveStatistics(FITSImage::Statistic &other); 0149 void restoreStatistics(FITSImage::Statistic &other); 0150 FITSImage::Statistic const &getStatistics() const 0151 { 0152 return m_Statistics; 0153 } 0154 0155 uint16_t width(bool roi = false) const 0156 { 0157 return roi ? m_ROIStatistics.width : m_Statistics.width; 0158 } 0159 uint16_t height(bool roi = false) const 0160 { 0161 return roi ? m_ROIStatistics.height : m_Statistics.height; 0162 } 0163 int64_t size(bool roi = false) const 0164 { 0165 return roi ? m_ROIStatistics.size : m_Statistics.size; 0166 } 0167 int channels() const 0168 { 0169 return m_Statistics.channels; 0170 } 0171 uint32_t samplesPerChannel(bool roi = false) const 0172 { 0173 return roi ? m_ROIStatistics.samples_per_channel : m_Statistics.samples_per_channel; 0174 } 0175 uint32_t dataType() const 0176 { 0177 return m_Statistics.dataType; 0178 } 0179 double getMin(uint8_t channel = 0, bool roi = false) const 0180 { 0181 return roi ? m_ROIStatistics.min[channel] : m_Statistics.min[channel]; 0182 } 0183 double getMax(uint8_t channel = 0, bool roi = false) const 0184 { 0185 return roi ? m_ROIStatistics.max[channel] : m_Statistics.max[channel]; 0186 0187 } 0188 void setMinMax(double newMin, double newMax, uint8_t channel = 0); 0189 void getMinMax(double *min, double *max, uint8_t channel = 0) const 0190 { 0191 *min = m_Statistics.min[channel]; 0192 *max = m_Statistics.max[channel]; 0193 } 0194 void setStdDev(double value, uint8_t channel = 0) 0195 { 0196 m_Statistics.stddev[channel] = value; 0197 } 0198 double getStdDev(uint8_t channel = 0, bool roi = false ) const 0199 { 0200 return roi ? m_ROIStatistics.stddev[channel] : m_Statistics.stddev[channel]; 0201 } 0202 double getAverageStdDev(bool roi = false) const; 0203 void setMean(double value, uint8_t channel = 0) 0204 { 0205 m_Statistics.mean[channel] = value; 0206 } 0207 double getMean(uint8_t channel = 0, bool roi = false) const 0208 { 0209 return roi ? m_ROIStatistics.mean[channel] : m_Statistics.mean[channel]; 0210 } 0211 // for single channel, just return the mean for channel zero 0212 // for color, return the average 0213 double getAverageMean(bool roi = false) const; 0214 void setMedian(double val, uint8_t channel = 0) 0215 { 0216 m_Statistics.median[channel] = val; 0217 } 0218 // for single channel, just return the median for channel zero 0219 // for color, return the average 0220 double getAverageMedian(bool roi = false) const; 0221 double getMedian(uint8_t channel = 0, bool roi = false) const 0222 { 0223 return roi ? m_ROIStatistics.median[channel] : m_Statistics.median[channel]; 0224 } 0225 0226 int getBytesPerPixel() const 0227 { 0228 return m_Statistics.bytesPerPixel; 0229 } 0230 void setSNR(double val) 0231 { 0232 m_Statistics.SNR = val; 0233 } 0234 double getSNR() const 0235 { 0236 return m_Statistics.SNR; 0237 } 0238 uint32_t bpp() const 0239 { 0240 switch(m_Statistics.dataType) 0241 { 0242 case TBYTE: 0243 return 8; 0244 case TSHORT: 0245 case TUSHORT: 0246 return 16; 0247 case TLONG: 0248 case TULONG: 0249 case TFLOAT: 0250 return 32; 0251 case TLONGLONG: 0252 case TDOUBLE: 0253 return 64; 0254 default: 0255 return 8; 0256 } 0257 } 0258 double getADU() const; 0259 0260 //////////////////////////////////////////////////////////////////////////////////////// 0261 //////////////////////////////////////////////////////////////////////////////////////// 0262 /// FITS Header Functions. 0263 //////////////////////////////////////////////////////////////////////////////////////// 0264 //////////////////////////////////////////////////////////////////////////////////////// 0265 // FITS Record 0266 bool getRecordValue(const QString &key, QVariant &value) const; 0267 const QList<Record> &getRecords() const 0268 { 0269 return m_HeaderRecords; 0270 } 0271 0272 //////////////////////////////////////////////////////////////////////////////////////// 0273 //////////////////////////////////////////////////////////////////////////////////////// 0274 /// Star Search & HFR Functions. 0275 //////////////////////////////////////////////////////////////////////////////////////// 0276 //////////////////////////////////////////////////////////////////////////////////////// 0277 // Star Detection - Native KStars implementation 0278 void setStarAlgorithm(StarAlgorithm algorithm) 0279 { 0280 starAlgorithm = algorithm; 0281 } 0282 int getDetectedStars() const 0283 { 0284 return starCenters.count(); 0285 } 0286 bool areStarsSearched() const 0287 { 0288 return starsSearched; 0289 } 0290 void appendStar(Edge *newCenter) 0291 { 0292 starCenters.append(newCenter); 0293 } 0294 const QList<Edge *> &getStarCenters() const 0295 { 0296 return starCenters; 0297 } 0298 QList<Edge *> getStarCentersInSubFrame(QRect subFrame) const; 0299 0300 void setStarCenters(const QList<Edge*> ¢ers) 0301 { 0302 qDeleteAll(starCenters); 0303 starCenters = centers; 0304 } 0305 QFuture<bool> findStars(StarAlgorithm algorithm = ALGORITHM_CENTROID, const QRect &trackingBox = QRect()); 0306 0307 void setSkyBackground(const SkyBackground &bg) 0308 { 0309 m_SkyBackground = bg; 0310 } 0311 const SkyBackground &getSkyBackground() const 0312 { 0313 return m_SkyBackground; 0314 } 0315 const QVariantMap &getSourceExtractorSettings() const 0316 { 0317 return m_SourceExtractorSettings; 0318 } 0319 void setSourceExtractorSettings(const QVariantMap &settings) 0320 { 0321 m_SourceExtractorSettings = settings; 0322 } 0323 // Use SEP (Sextractor Library) to find stars 0324 template <typename T> 0325 void getFloatBuffer(float *buffer, int x, int y, int w, int h) const; 0326 //int findSEPStars(QList<Edge*> &, const int8_t &boundary = int8_t()) const; 0327 0328 // filter all stars that are visible through the given mask 0329 int filterStars(QSharedPointer<ImageMask> mask); 0330 0331 // Half Flux Radius 0332 const Edge &getSelectedHFRStar() const 0333 { 0334 return m_SelectedHFRStar; 0335 } 0336 0337 // Calculates the median star eccentricity. 0338 double getEccentricity(); 0339 0340 double getHFR(HFRType type = HFR_AVERAGE); 0341 double getHFR(int x, int y, double scale = 1.0); 0342 0343 //////////////////////////////////////////////////////////////////////////////////////// 0344 //////////////////////////////////////////////////////////////////////////////////////// 0345 /// Date & Time (WCS) Functions. 0346 //////////////////////////////////////////////////////////////////////////////////////// 0347 //////////////////////////////////////////////////////////////////////////////////////// 0348 0349 const KStarsDateTime &getDateTime() const 0350 { 0351 return m_DateTime; 0352 } 0353 0354 // Set the time, for testing (doesn't set header field) 0355 void setDateTime(const KStarsDateTime &t) 0356 { 0357 m_DateTime = t; 0358 } 0359 0360 const QPoint getRoiCenter() const 0361 { 0362 return roiCenter; 0363 } 0364 0365 void setRoiCenter(QPoint c) 0366 { 0367 roiCenter = c; 0368 } 0369 0370 //////////////////////////////////////////////////////////////////////////////////////// 0371 //////////////////////////////////////////////////////////////////////////////////////// 0372 /// World Coordinate System (WCS) Functions. 0373 //////////////////////////////////////////////////////////////////////////////////////// 0374 //////////////////////////////////////////////////////////////////////////////////////// 0375 // Check if a particular point exists within the image 0376 bool contains(const QPointF &point) const; 0377 // Does image have valid WCS? 0378 bool hasWCS() 0379 { 0380 return HasWCS; 0381 } 0382 // Load WCS data 0383 bool loadWCS(); 0384 // Get WCS State 0385 WCSState getWCSState() const 0386 { 0387 return m_WCSState; 0388 } 0389 0390 /** 0391 * @brief wcsToPixel Given J2000 (RA0,DE0) coordinates. Find in the image the corresponding pixel coordinates. 0392 * @param wcsCoord Coordinates of target 0393 * @param wcsPixelPoint Return XY FITS coordinates 0394 * @param wcsImagePoint Return XY Image coordinates 0395 * @return True if conversion is successful, false otherwise. 0396 */ 0397 bool wcsToPixel(const SkyPoint &wcsCoord, QPointF &wcsPixelPoint, QPointF &wcsImagePoint); 0398 0399 /** 0400 * @brief pixelToWCS Convert Pixel coordinates to J2000 world coordinates 0401 * @param wcsPixelPoint Pixel coordinates in XY Image space. 0402 * @param wcsCoord Store back WCS world coordinate in wcsCoord 0403 * @return True if successful, false otherwise. 0404 */ 0405 bool pixelToWCS(const QPointF &wcsPixelPoint, SkyPoint &wcsCoord); 0406 0407 /** 0408 * @brief injectWCS Add WCS keywords 0409 * @param orientation Solver orientation, degrees E of N. 0410 * @param ra J2000 Right Ascension 0411 * @param dec J2000 Declination 0412 * @param pixscale Pixel scale in arcsecs per pixel 0413 * @param eastToTheRight if true, then when the image is rotated so that north is up, then east would be to the right on the image. 0414 */ 0415 void injectWCS(double orientation, double ra, double dec, double pixscale, bool eastToTheRight); 0416 0417 //////////////////////////////////////////////////////////////////////////////////////// 0418 //////////////////////////////////////////////////////////////////////////////////////// 0419 /// Debayering Functions 0420 //////////////////////////////////////////////////////////////////////////////////////// 0421 //////////////////////////////////////////////////////////////////////////////////////// 0422 0423 // Debayer 0424 bool hasDebayer() 0425 { 0426 return HasDebayer; 0427 } 0428 0429 /** 0430 * @brief debayer the 1-channel data to 3-channel RGB using the default debayer pattern detected in the FITS header. 0431 * @param reload If true, it will read the image again from disk before performing debayering. This is necessary to attempt 0432 * subsequent debayering processes on an already debayered image. 0433 */ 0434 bool debayer(bool reload = false); 0435 bool debayer_8bit(); 0436 bool debayer_16bit(); 0437 void getBayerParams(BayerParams *param); 0438 void setBayerParams(BayerParams *param); 0439 0440 //////////////////////////////////////////////////////////////////////////////////////// 0441 //////////////////////////////////////////////////////////////////////////////////////// 0442 /// Public Histogram Functions 0443 //////////////////////////////////////////////////////////////////////////////////////// 0444 //////////////////////////////////////////////////////////////////////////////////////// 0445 0446 void resetHistogram() 0447 { 0448 m_HistogramConstructed = false; 0449 } 0450 double getHistogramBinWidth(int channel = 0) 0451 { 0452 return m_HistogramBinWidth[channel]; 0453 } 0454 0455 // Returns a vector with the counts (y-axis values) for the histogram. 0456 const QVector<uint32_t> &getCumulativeFrequency(uint8_t channel = 0) const 0457 { 0458 return m_CumulativeFrequency[channel]; 0459 } 0460 // Returns a vector with the values (x-axis values) for the histogram. 0461 // The value returned is the low end of the histogram interval. 0462 // The high end is this intensity plus the value returned by getHistogramBinWidth(). 0463 const QVector<double> &getHistogramIntensity(uint8_t channel = 0) const 0464 { 0465 return m_HistogramIntensity[channel]; 0466 } 0467 const QVector<double> &getHistogramFrequency(uint8_t channel = 0) const 0468 { 0469 return m_HistogramFrequency[channel]; 0470 } 0471 int getHistogramBinCount() const 0472 { 0473 return m_HistogramBinCount; 0474 } 0475 0476 // Returns the histogram bin for the pixel at location x,y in the given channel. 0477 int32_t histogramBin(int x, int y, int channel) const; 0478 0479 /** 0480 * @brief getJMIndex Overall contrast of the image used in find centeroid algorithm. i.e. is the image diffuse? 0481 * @return Value of JMIndex 0482 */ 0483 double getJMIndex() const 0484 { 0485 return m_JMIndex; 0486 } 0487 0488 bool isHistogramConstructed() const 0489 { 0490 return m_HistogramConstructed; 0491 } 0492 void constructHistogram(); 0493 0494 //////////////////////////////////////////////////////////////////////////////////////// 0495 //////////////////////////////////////////////////////////////////////////////////////// 0496 /// Filters and Rotations Functions. 0497 //////////////////////////////////////////////////////////////////////////////////////// 0498 //////////////////////////////////////////////////////////////////////////////////////// 0499 // Filter 0500 void applyFilter(FITSScale type, uint8_t *image = nullptr, QVector<double> *targetMin = nullptr, 0501 QVector<double> *targetMax = nullptr); 0502 0503 // Rotation counter. We keep count to rotate WCS keywords on save 0504 int getRotCounter() const; 0505 void setRotCounter(int value); 0506 0507 // Filename 0508 const QString &filename() const 0509 { 0510 return m_Filename; 0511 } 0512 const QString &compressedFilename() const 0513 { 0514 return m_compressedFilename; 0515 } 0516 bool isCompressed() const 0517 { 0518 return m_isCompressed; 0519 } 0520 // Extension 0521 const QString &extension() const 0522 { 0523 return m_Extension; 0524 } 0525 0526 // Horizontal flip counter. We keep count to rotate WCS keywords on save 0527 int getFlipHCounter() const; 0528 void setFlipHCounter(int value); 0529 0530 // Horizontal flip counter. We keep count to rotate WCS keywords on save 0531 int getFlipVCounter() const; 0532 void setFlipVCounter(int value); 0533 0534 //////////////////////////////////////////////////////////////////////////////////////// 0535 //////////////////////////////////////////////////////////////////////////////////////// 0536 /// Object Search Functions. 0537 //////////////////////////////////////////////////////////////////////////////////////// 0538 //////////////////////////////////////////////////////////////////////////////////////// 0539 #ifndef KSTARS_LITE 0540 #ifdef HAVE_WCSLIB 0541 bool searchObjects(); 0542 bool findObjectsInImage(SkyPoint startPoint, SkyPoint endPoint); 0543 bool findWCSBounds(double &minRA, double &maxRA, double &minDec, double &maxDec); 0544 #endif 0545 #endif 0546 const QList<FITSSkyObject *> &getSkyObjects() const 0547 { 0548 return m_SkyObjects; 0549 } 0550 0551 //////////////////////////////////////////////////////////////////////////////////////// 0552 //////////////////////////////////////////////////////////////////////////////////////// 0553 /// Image Conversion Functions. 0554 //////////////////////////////////////////////////////////////////////////////////////// 0555 //////////////////////////////////////////////////////////////////////////////////////// 0556 // Create autostretch image from FITS File 0557 static QImage FITSToImage(const QString &filename); 0558 0559 /** 0560 * @brief ImageToFITS Convert an image file with supported format to a FITS file. 0561 * @param filename full path to filename without extension 0562 * @param format file extension. Supported formats are whatever supported by Qt (e.g. PNG, JPG,..etc) 0563 * @param output Output temporary file path. The created file is generated by the function and store in output. 0564 * @return True if conversion is successful, false otherwise. 0565 */ 0566 static bool ImageToFITS(const QString &filename, const QString &format, QString &output); 0567 0568 QString getLastError() const; 0569 0570 static bool readableFilename(const QString &filename); 0571 0572 signals: 0573 void converted(QImage); 0574 0575 /** 0576 * @brief histogramReady Sends signal when histogram construction is complete. 0577 */ 0578 void histogramReady(); 0579 0580 /** 0581 * @brief dataChanged Send signal when undelying raw data buffer data changed. 0582 */ 0583 void dataChanged(); 0584 public slots: 0585 void makeRoiBuffer(QRect roi); 0586 0587 private: 0588 void loadCommon(const QString &inFilename); 0589 /** 0590 * @brief privateLoad Load an image (FITS, RAW, or images supported by Qt like jpeg, png). 0591 * @param Buffer pointer to image data. If buffer is emtpy, read from disk (m_Filename). 0592 * @return true if successfully loaded, false otherwise. 0593 */ 0594 bool privateLoad(const QByteArray &buffer); 0595 0596 // Load Qt-supported images. 0597 bool loadCanonicalImage(const QByteArray &buffer); 0598 // Load FITS images. 0599 bool loadFITSImage(const QByteArray &buffer, const bool isCompressed = false); 0600 // Load XISF images. 0601 bool loadXISFImage(const QByteArray &buffer); 0602 // Save XISF images. 0603 bool saveXISFImage(const QString &newFilename); 0604 // Load RAW images. 0605 bool loadRAWImage(const QByteArray &buffer); 0606 0607 void rotWCSFITS(int angle, int mirror); 0608 void calculateMinMax(bool refresh = false, bool roi = false); 0609 void calculateMedian(bool refresh = false, bool roi = false); 0610 bool checkDebayer(); 0611 void readWCSKeys(); 0612 0613 // Record last FITS error 0614 void recordLastError(int errorCode); 0615 void logOOMError(uint32_t requiredMemory = 0); 0616 0617 // FITS Record 0618 bool parseHeader(); 0619 //int getFITSRecord(QString &recordList, int &nkeys); 0620 0621 // Templated functions 0622 template <typename T> 0623 bool debayer(); 0624 0625 template <typename T> 0626 bool rotFITS(int rotate, int mirror); 0627 0628 // Apply Filter 0629 template <typename T> 0630 void applyFilter(FITSScale type, uint8_t *targetImage, QVector<double> * min = nullptr, QVector<double> * max = nullptr); 0631 0632 template <typename T> 0633 void calculateMinMax(bool roi = false); 0634 template <typename T> 0635 void calculateMedian(bool roi = false); 0636 0637 template <typename T> 0638 QPair<T, T> getParitionMinMax(uint32_t start, uint32_t stride, bool roi); 0639 0640 /* Calculate the Gaussian blur matrix and apply it to the image using the convolution filter */ 0641 QVector<double> createGaussianKernel(int size, double sigma); 0642 template <typename T> 0643 void convolutionFilter(const QVector<double> &kernel, int kernelSize); 0644 template <typename T> 0645 void gaussianBlur(int kernelSize, double sigma); 0646 0647 /* Calculate running average & standard deviation */ 0648 template <typename T> 0649 void calculateStdDev( bool roi = false ); 0650 0651 template <typename T> 0652 void convertToQImage(double dataMin, double dataMax, double scale, double zero, QImage &image); 0653 0654 //////////////////////////////////////////////////////////////////////////////////////// 0655 //////////////////////////////////////////////////////////////////////////////////////// 0656 /// Private Histogram Functions. 0657 //////////////////////////////////////////////////////////////////////////////////////// 0658 //////////////////////////////////////////////////////////////////////////////////////// 0659 template <typename T> void constructHistogramInternal(); 0660 template <typename T> int32_t histogramBinInternal(T value, int channel) const; 0661 template <typename T> int32_t histogramBinInternal(int x, int y, int channel) const; 0662 0663 /// Pointer to CFITSIO FITS file struct 0664 fitsfile *fptr { nullptr }; 0665 /// Generic data image buffer 0666 uint8_t *m_ImageBuffer { nullptr }; 0667 /// Above buffer size in bytes 0668 uint32_t m_ImageBufferSize { 0 }; 0669 /// Image Buffer if Selection is to be done 0670 uint8_t *m_ImageRoiBuffer { nullptr }; 0671 /// Above buffer size in bytes 0672 uint32_t m_ImageRoiBufferSize { 0 }; 0673 /// Is this a temporary file or one loaded from disk? 0674 bool m_isTemporary { false }; 0675 /// is this file compress (.fits.fz)? 0676 bool m_isCompressed { false }; 0677 /// Did we search for stars yet? 0678 bool starsSearched { false }; 0679 ///Star Selection Algorithm 0680 StarAlgorithm starAlgorithm { ALGORITHM_GRADIENT }; 0681 /// Do we have WCS keywords in this FITS data? 0682 bool HasWCS { false }; /// Do we have WCS keywords in this FITS data? 0683 /// Is the image debayarable? 0684 bool HasDebayer { false }; 0685 /// Buffer to hold fpack uncompressed data 0686 uint8_t *m_PackBuffer {nullptr}; 0687 0688 /// Our very own file name 0689 QString m_Filename, m_compressedFilename, m_Extension; 0690 /// FITS Mode (Normal, WCS, Guide, Focus..etc) 0691 FITSMode m_Mode; 0692 // FITS Observed UTC date time 0693 KStarsDateTime m_DateTime; 0694 0695 /// How many times the image was rotated? Useful for WCS keywords rotation on save. 0696 int rotCounter { 0 }; 0697 /// How many times the image was flipped horizontally? 0698 int flipHCounter { 0 }; 0699 /// How many times the image was flipped vertically? 0700 int flipVCounter { 0 }; 0701 0702 /// WCS Struct 0703 struct wcsprm *m_WCSHandle 0704 { 0705 nullptr 0706 }; 0707 /// Number of coordinate representations found. 0708 int m_nwcs {0}; 0709 WCSState m_WCSState { Idle }; 0710 /// All the stars we detected, if any. 0711 QList<Edge *> starCenters; 0712 QList<Edge *> localStarCenters; 0713 /// The biggest fattest star in the image. 0714 Edge m_SelectedHFRStar; 0715 0716 /// Bayer parameters 0717 BayerParams debayerParams; 0718 QTemporaryFile m_TemporaryDataFile; 0719 0720 /// Data type of fits pixel in the image. Used when saving FITS again. 0721 /// There is bit depth and also data type. They're not the same. 0722 /// 16bit can be either SHORT_IMG or USHORT_IMG, so m_FITSBITPIX specifies which is 0723 int m_FITSBITPIX {USHORT_IMG}; 0724 FITSImage::Statistic m_Statistics; 0725 FITSImage::Statistic m_ROIStatistics; 0726 0727 // A list of header records 0728 QList<Record> m_HeaderRecords; 0729 0730 QList<FITSSkyObject *> m_SkyObjects; 0731 bool m_ObjectsSearched {false}; 0732 0733 QString m_LastError; 0734 0735 //////////////////////////////////////////////////////////////////////////////////////// 0736 //////////////////////////////////////////////////////////////////////////////////////// 0737 /// Histogram Variables 0738 //////////////////////////////////////////////////////////////////////////////////////// 0739 //////////////////////////////////////////////////////////////////////////////////////// 0740 QVector<QVector<uint32_t>> m_CumulativeFrequency; 0741 QVector<QVector<double>> m_HistogramIntensity; 0742 QVector<QVector<double>> m_HistogramFrequency; 0743 QVector<double> m_HistogramBinWidth; 0744 uint16_t m_HistogramBinCount { 0 }; 0745 double m_JMIndex { 1 }; 0746 bool m_HistogramConstructed { false }; 0747 0748 //////////////////////////////////////////////////////////////////////////////////////// 0749 //////////////////////////////////////////////////////////////////////////////////////// 0750 /// Star Detector 0751 //////////////////////////////////////////////////////////////////////////////////////// 0752 //////////////////////////////////////////////////////////////////////////////////////// 0753 // Sky Background 0754 SkyBackground m_SkyBackground; 0755 // Detector Settings 0756 QVariantMap m_SourceExtractorSettings; 0757 QFuture<bool> m_StarFindFuture; 0758 QScopedPointer<FITSStarDetector, QScopedPointerDeleteLater> m_StarDetector; 0759 0760 // Cached values for hfr and eccentricity computations 0761 double cacheHFR { -1 }; 0762 HFRType cacheHFRType { HFR_AVERAGE }; 0763 double cacheEccentricity { -1 }; 0764 QPoint roiCenter; 0765 };