Add support for WCS

This commit is contained in:
2022-06-13 18:02:58 +02:00
parent 701a425cc7
commit 6b9ea5e4b9
7 changed files with 162 additions and 13 deletions
+2 -1
View File
@@ -19,6 +19,7 @@ find_library(GSLCBLAS_LIB gslcblas REQUIRED)
find_library(EXIF_LIB exif REQUIRED)
find_library(FITS_LIB cfitsio REQUIRED)
find_library(RAW_LIB NAMES raw_r REQUIRED)
find_library(WCS_LIB wcs REQUIRED)
set(TENMON_SRC
about.cpp
@@ -58,7 +59,7 @@ else()
target_link_directories(tenmon PRIVATE 3rdparty/lib/Linux)
endif()
target_link_libraries(tenmon Qt5::Widgets Qt5::Sql ${OpenCV_LIBS} ${GSL_LIB} ${GSLCBLAS_LIB} ${EXIF_LIB} ${FITS_LIB} ${RAW_LIB})
target_link_libraries(tenmon Qt5::Widgets Qt5::Sql ${OpenCV_LIBS} ${GSL_LIB} ${GSLCBLAS_LIB} ${EXIF_LIB} ${FITS_LIB} ${RAW_LIB} ${WCS_LIB})
target_link_libraries(tenmon PCL lcms lz4 RFC6234 zlib)
if(LIBRAW_STATIC)
+90
View File
@@ -1,6 +1,9 @@
#include "imageinfo.h"
#include <QSettings>
#include <QTime>
#include <QHeaderView>
#include <wcslib/wcshdr.h>
#include <wcslib/wcsfix.h>
static const QVector<QByteArray> noEditableKey = {"SIMPLE", "BITPIX", "NAXIS", "NAXIS1", "NAXIS2", "NAXIS3", "EXTEND", "BZERO", "BSCALE"};
@@ -47,3 +50,90 @@ void ImageInfo::setInfo(const ImageInfoData &info)
}
expandAll();
}
void WCSData::freeWCS()
{
wcsvfree(&nwcs, &wcs);
nwcs = 0;
wcs = nullptr;
}
WCSData::WCSData(char *header, int nrec)
{
int stat[NWCSFIX];
int nreject = 0;
int status = wcspih(header, nrec, 1, 0, &nreject, &nwcs, &wcs);
if(status != 0)
{
freeWCS();
return;
}
status = wcsfix(0, 0, wcs, stat);
if(status != 0 || wcs->crpix[0] == 0)
freeWCS();
}
WCSData::~WCSData()
{
if(wcs)
freeWCS();
}
SkyPoint WCSData::pixelToWorld(QPointF pixel) const
{
if(wcs == nullptr)return SkyPoint();
double pixcrd[2] = {pixel.x(), pixel.y()};
double imgcrd[8] = {0};
double phi = 0;
double theta = 0;
double world[8] = {0};
int stat[NWCSFIX] = {0};
int status = wcsp2s(wcs, 1, 2, pixcrd, imgcrd, &phi, &theta, world, stat);
if(status == 0)
{
return SkyPoint(world[0], world[1]);
}
return SkyPoint();
}
QPointF WCSData::worldToPixel(SkyPoint point) const
{
return QPointF();
}
void WCSData::calculateBounds(double &minRa, double &maxRa, double &minDec, double &maxDec)
{
minRa = -1000;
maxRa = 1000;
minDec = -1000;
maxDec = 1000;
}
SkyPoint::SkyPoint() : ra(NAN), dec(NAN)
{
}
SkyPoint::SkyPoint(double ra, double dec) : ra(ra), dec(dec)
{
}
void SkyPoint::set(double ra, double dec)
{
this->ra = ra;
this->dec = dec;
}
QString SkyPoint::toString() const
{
if(std::isnan(ra) || std::isnan(dec))
return QString();
QTime t(0, 0);
t = t.addSecs(ra * 240);
double deg, min, sec;
min = std::modf(dec, &deg) * 60;
sec = std::modf(min, &min) * 60;
return QString("RA: %1 DEC: %2° %3' %4\"").arg(t.toString("HH'h' mm'm' ss's'")).arg(deg, 2, 'f', 0, '0').arg(min, 2, 'f', 0, '0').arg(sec, 2, 'f', 0, '0');
}
+30
View File
@@ -2,6 +2,8 @@
#define IMAGEINFO_H
#include <QTreeWidget>
#include <wcslib/wcs.h>
#include <cmath>
struct FITSRecord
{
@@ -11,10 +13,38 @@ struct FITSRecord
bool editable() const;
};
class SkyPoint
{
double ra = NAN;
double dec = NAN;
public:
SkyPoint();
SkyPoint(double ra, double dec);
void set(double ra, double dec);
double RA() const { return ra; }
double DEC() const { return dec; }
QString toString() const;
};
class WCSData
{
int nwcs = 0;
struct wcsprm *wcs = nullptr;
void freeWCS();
public:
WCSData();
WCSData(char *header, int nrec);
~WCSData();
SkyPoint pixelToWorld(QPointF pixel) const;
QPointF worldToPixel(SkyPoint point) const;
void calculateBounds(double &minRa, double &maxRa, double &minDec, double &maxDec);
};
struct ImageInfoData
{
QVector<FITSRecord> fitsHeader;
QVector<QPair<QString, QString>> info;
std::shared_ptr<WCSData> wcs;
};
Q_DECLARE_METATYPE(ImageInfoData);
+23 -7
View File
@@ -85,7 +85,7 @@ ImageWidget::~ImageWidget()
makeCurrent();
}
void ImageWidget::setImage(std::shared_ptr<RawImage> &image, int index)
void ImageWidget::setImage(std::shared_ptr<RawImage> image, int index)
{
if(image == nullptr)return;
@@ -112,6 +112,11 @@ void ImageWidget::setImage(std::shared_ptr<RawImage> &image, int index)
update();
}
void ImageWidget::setWCS(std::shared_ptr<WCSData> wcs)
{
m_wcs = wcs;
}
void ImageWidget::setScale(float scale)
{
m_scale = scale;
@@ -456,12 +461,19 @@ void ImageWidget::mouseMoveEvent(QMouseEvent *event)
QVector2D pos = QVector2D(event->pos());
QVector2D pix = (pos + offset) / m_scale;
QVector3D rgb;
SkyPoint sky;
if(m_wcs)
{
sky = m_wcs->pixelToWorld(QPointF(pix.x(), pix.y()));
}
if(m_rawImage->pixel(pix.x(), pix.y(), rgb))
{
if(m_bwImg)
emit status(tr("L: %1").arg(rgb.x()));
emit status(tr("L:%1 %2 X:%3 Y:%4").arg(rgb.x()).arg(sky.toString()).arg((int)pix.x()).arg((int)pix.y()));
else
emit status(tr("R: %1 G: %2 B: %3").arg(rgb.x()).arg(rgb.y()).arg(rgb.z()));
emit status(tr("R:%1 G:%2 B:%3 %4 X:%5 Y:%6").arg(rgb.x()).arg(rgb.y()).arg(rgb.z()).arg(sky.toString()).arg((int)pix.x()).arg((int)pix.y()));
}
}
}
@@ -551,14 +563,18 @@ ImageScrollAreaGL::~ImageScrollAreaGL()
}
void ImageScrollAreaGL::setImage(std::shared_ptr<RawImage> image, int index)
void ImageScrollAreaGL::setImage(Image *image)
{
m_imageWidget->setImage(image, index);
m_imgWidth = image->width();
m_imgHeight = image->height();
if(image && image->rawImage())
{
m_imageWidget->setImage(image->rawImage(), image->number());
m_imageWidget->setWCS(image->info().wcs);
m_imgWidth = image->rawImage()->width();
m_imgHeight = image->rawImage()->height();
if(m_bestFit)bestFit();
updateScrollbars();
}
}
ImageWidget *ImageScrollAreaGL::imageWidget()
{
+4 -2
View File
@@ -40,6 +40,7 @@ class ImageWidget : public QOpenGLWidget
std::unique_ptr<QOpenGLPixelTransferOptions> m_transferOptions;
std::unique_ptr<QOpenGLTexture> m_thumbnailTexture;
std::shared_ptr<RawImage> m_rawImage;
std::shared_ptr<WCSData> m_wcs;
int m_width, m_height;
int m_imgWidth, m_imgHeight;
int m_currentImg;
@@ -61,8 +62,9 @@ class ImageWidget : public QOpenGLWidget
public:
explicit ImageWidget(Database *database, QWidget *parent = nullptr);
~ImageWidget() override;
void setImage(std::shared_ptr<RawImage> &image, int index);
void setImage(std::shared_ptr<RawImage> image, int index);
void setImage(const QPixmap &pixmap);
void setWCS(std::shared_ptr<WCSData> wcs);
void setScale(float scale);
void blockRepaint(bool block);
void allocateThumbnails(const QStringList &paths);
@@ -103,7 +105,7 @@ class ImageScrollAreaGL : public QWidget
public:
explicit ImageScrollAreaGL(Database *database, QWidget *parent = nullptr);
~ImageScrollAreaGL() override;
void setImage(std::shared_ptr<RawImage> image, int index);
void setImage(Image *image);
ImageWidget* imageWidget();
void setThumbnails(int count);
protected:
+10
View File
@@ -12,6 +12,7 @@
#include <pcl/XISF.h>
#include "rawimage.h"
#include "starfit.h"
#include "wcslib/wcshdr.h"
LoadRunable::LoadRunable(const QString &file, Image *receiver, AnalyzeLevel level, bool thumbnail) :
m_file(file),
@@ -166,6 +167,15 @@ int loadFITSHeader(fitsfile *file, ImageInfoData &info)
return status;
}
}
char *header = nullptr;
int nrec = 0;
fits_hdr2str(file, TRUE, nullptr, 0, &header, &nrec, &status);
if(status == 0)
{
info.wcs = std::make_shared<WCSData>(header, nrec);
}
fits_free_memory(header, &status);
return status;
}
+1 -1
View File
@@ -341,7 +341,7 @@ void MainWindow::pixmapLoaded(Image *image)
{
if(image->rawImage())
{
m_imageGL->setImage(image->rawImage(), image->number());
m_imageGL->setImage(image);
}
}