Add support for WCS
This commit is contained in:
+2
-1
@@ -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)
|
||||
|
||||
@@ -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, °) * 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
@@ -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
@@ -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
@@ -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:
|
||||
|
||||
@@ -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
@@ -341,7 +341,7 @@ void MainWindow::pixmapLoaded(Image *image)
|
||||
{
|
||||
if(image->rawImage())
|
||||
{
|
||||
m_imageGL->setImage(image->rawImage(), image->number());
|
||||
m_imageGL->setImage(image);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user