Replace PCL with LibXISF
This commit is contained in:
+93
-120
@@ -9,14 +9,13 @@
|
||||
#include <iostream>
|
||||
#include <libexif/exif-data.h>
|
||||
#include <fitsio2.h>
|
||||
#include <pcl/XISF.h>
|
||||
#include <libxisf.h>
|
||||
#include "rawimage.h"
|
||||
#include "starfit.h"
|
||||
#include "wcslib/wcshdr.h"
|
||||
|
||||
#ifdef COLOR_MANAGMENT
|
||||
#include <QColorSpace>
|
||||
static pcl::ICCProfile sRgbIccProfile((void*)QColorSpace(QColorSpace::SRgb).iccProfile().data());
|
||||
#endif
|
||||
|
||||
LoadRunable::LoadRunable(const QString &file, Image *receiver, AnalyzeLevel level, bool thumbnail) :
|
||||
@@ -286,97 +285,82 @@ bool loadFITS(const QString path, ImageInfoData &info, RawImage **image)
|
||||
return true;
|
||||
}
|
||||
|
||||
#include "pcl/ICCProfileTransformation.h"
|
||||
|
||||
template<typename T, typename PCLtype, int CVtype>
|
||||
bool loadPCLImage(pcl::XISFReader &xisf, RawImage **image)
|
||||
{
|
||||
PCLtype pclImage;
|
||||
xisf.ReadImage(pclImage);
|
||||
pclImage.Status().DisableInitialization();
|
||||
|
||||
#ifdef COLOR_MANAGMENT
|
||||
pcl::ICCProfile iccProfile = xisf.ReadICCProfile();
|
||||
if(iccProfile.IsProfile() && iccProfile != sRgbIccProfile)
|
||||
{
|
||||
pcl::ICCProfileTransformation iccTran;
|
||||
iccTran.DisableParallelProcessing();
|
||||
iccTran.Add(iccProfile);
|
||||
iccTran.Add(sRgbIccProfile);
|
||||
iccTran >> pclImage;
|
||||
}
|
||||
#endif
|
||||
|
||||
int numChannels = pclImage.NumberOfChannels();
|
||||
cv::Mat cvImg[numChannels];
|
||||
for(int i=0; i<numChannels; i++)
|
||||
{
|
||||
T *p = pclImage.PixelData(i);
|
||||
cvImg[i].create(pclImage.Height(), pclImage.Width(), CVtype);
|
||||
memcpy(cvImg[i].ptr(0), p, pclImage.Width()*pclImage.Height()*sizeof(T));
|
||||
}
|
||||
|
||||
if(numChannels==3)
|
||||
{
|
||||
cv::Mat merged;
|
||||
cv::merge(cvImg, 3, merged);
|
||||
*image = new RawImage(merged);
|
||||
return true;
|
||||
}
|
||||
if(numChannels==1)
|
||||
{
|
||||
*image = new RawImage(cvImg[0]);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool loadXISF(const QString &path, ImageInfoData &info, RawImage **image)
|
||||
{
|
||||
try
|
||||
{
|
||||
pcl::XISF::EnsurePTLUTInitialized();
|
||||
pcl::String pclPath = path.utf16();
|
||||
pcl::XISFReader xisf;
|
||||
xisf.Open(pclPath);
|
||||
uint8_t bps = xisf.ImageOptions().bitsPerSample;
|
||||
bool floatType = xisf.ImageOptions().ieeefpSampleFormat;
|
||||
bool signedInt = xisf.ImageOptions().signedIntegers;
|
||||
bool complex = xisf.ImageOptions().complexSample;
|
||||
LibXISF::XISFReader xisf;
|
||||
xisf.open(path);
|
||||
|
||||
auto fitskeywords = xisf.ReadFITSKeywords();
|
||||
const LibXISF::Image &xisfImage = xisf.getImage(0);
|
||||
|
||||
auto fitskeywords = xisfImage.fitsKeywords();
|
||||
for(auto fits : fitskeywords)
|
||||
{
|
||||
info.fitsHeader.append(fits);
|
||||
}
|
||||
auto imageproperties = xisf.ReadImageProperties();
|
||||
auto imageproperties = xisfImage.imageProperties();
|
||||
for(auto prop : imageproperties)
|
||||
{
|
||||
info.fitsHeader.append(prop);
|
||||
}
|
||||
|
||||
info.wcs = std::make_shared<WCSData>(xisf.ImageInfo().width, xisf.ImageInfo().height, info.fitsHeader);
|
||||
info.info.append({QObject::tr("Width"), QString::number(xisf.ImageInfo().width)});
|
||||
info.info.append({QObject::tr("Height"), QString::number(xisf.ImageInfo().height)});
|
||||
info.wcs = std::make_shared<WCSData>(xisfImage.width(), xisfImage.height(), info.fitsHeader);
|
||||
info.info.append({QObject::tr("Width"), QString::number(xisfImage.width())});
|
||||
info.info.append({QObject::tr("Height"), QString::number(xisfImage.height())});
|
||||
if(!info.wcs->valid())info.wcs.reset();
|
||||
|
||||
if(floatType && bps == 32)
|
||||
return loadPCLImage<float, pcl::FImage, CV_32F>(xisf, image);
|
||||
if(!complex && !signedInt)
|
||||
if(xisfImage.channelCount() == 1)
|
||||
{
|
||||
switch(bps)
|
||||
switch(xisfImage.sampleFormat())
|
||||
{
|
||||
case 8:
|
||||
return loadPCLImage<uint8_t, pcl::UInt8Image, CV_8U>(xisf, image);
|
||||
case 16:
|
||||
return loadPCLImage<uint16_t, pcl::UInt16Image, CV_16U>(xisf, image);
|
||||
case LibXISF::Image::UInt8:
|
||||
*image = new RawImage(xisfImage.width(), xisfImage.height(), RawImage::UINT8);
|
||||
std::memcpy((*image)->data(), xisfImage.imageData(), xisfImage.imageDataSize());
|
||||
break;
|
||||
case LibXISF::Image::UInt16:
|
||||
*image = new RawImage(xisfImage.width(), xisfImage.height(), RawImage::UINT16);
|
||||
std::memcpy((*image)->data(), xisfImage.imageData(), xisfImage.imageDataSize());
|
||||
break;
|
||||
case LibXISF::Image::Float32:
|
||||
*image = new RawImage(xisfImage.width(), xisfImage.height(), RawImage::FLOAT32);
|
||||
std::memcpy((*image)->data(), xisfImage.imageData(), xisfImage.imageDataSize());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(xisfImage.channelCount() == 3)
|
||||
{
|
||||
LibXISF::Image tmpImage = xisfImage;
|
||||
tmpImage.convertPixelStorageTo(LibXISF::Image::Normal);
|
||||
|
||||
switch(tmpImage.sampleFormat())
|
||||
{
|
||||
case LibXISF::Image::UInt8:
|
||||
*image = new RawImage(tmpImage.width(), tmpImage.height(), RawImage::UINT8C3);
|
||||
std::memcpy((*image)->data(), tmpImage.imageData(), tmpImage.imageDataSize());
|
||||
break;
|
||||
case LibXISF::Image::UInt16:
|
||||
*image = new RawImage(tmpImage.width(), tmpImage.height(), RawImage::UINT16C3);
|
||||
std::memcpy((*image)->data(), tmpImage.imageData(), tmpImage.imageDataSize());
|
||||
break;
|
||||
case LibXISF::Image::Float32:
|
||||
*image = new RawImage(tmpImage.width(), tmpImage.height(), RawImage::FLOAT32C3);
|
||||
std::memcpy((*image)->data(), tmpImage.imageData(), tmpImage.imageDataSize());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(*image)
|
||||
return true;
|
||||
}
|
||||
catch (pcl::Error err)
|
||||
catch (LibXISF::Error &err)
|
||||
{
|
||||
info.info.append(QPair<QString, QString>("Error", err.FormatInfo().ToUTF8().c_str()));
|
||||
qDebug() << "Failed to load XISF" << err.FormatInfo().ToUTF8().c_str();
|
||||
info.info.append(QPair<QString, QString>("Error", err.what()));
|
||||
qDebug() << "Failed to load XISF" << err.what();
|
||||
return false;
|
||||
}
|
||||
info.info.append({QObject::tr("Error"), QObject::tr("Unsupported sample format")});
|
||||
return false;
|
||||
@@ -433,6 +417,7 @@ void LoadRunable::run()
|
||||
exif_data_free(exif);
|
||||
}
|
||||
rawImage = new RawImage(img);
|
||||
qDebug() << "LoadQImage" << timer.elapsed();
|
||||
}
|
||||
|
||||
if(rawImage && m_analyzeLevel >= Statistics && !m_thumbnail)
|
||||
@@ -541,27 +526,27 @@ bool readXISFHeader(const QString &path, ImageInfoData &info)
|
||||
{
|
||||
try
|
||||
{
|
||||
pcl::String pclPath = path.utf16();
|
||||
pcl::XISFReader xisf;
|
||||
xisf.Open(pclPath);
|
||||
LibXISF::XISFReader xisf;
|
||||
const LibXISF::Image &image = xisf.getImage(0, false);
|
||||
xisf.open(path);
|
||||
|
||||
auto fitskeywords = xisf.ReadFITSKeywords();
|
||||
auto fitskeywords = image.fitsKeywords();
|
||||
for(auto fits : fitskeywords)
|
||||
{
|
||||
info.fitsHeader.append(fits);
|
||||
}
|
||||
|
||||
auto imageproperties = xisf.ReadImageProperties();
|
||||
auto imageproperties = image.fitsKeywords();
|
||||
for(auto prop : imageproperties)
|
||||
{
|
||||
info.fitsHeader.append(prop);
|
||||
}
|
||||
info.wcs = std::make_shared<WCSData>(xisf.ImageInfo().width, xisf.ImageInfo().height, info.fitsHeader);
|
||||
info.wcs = std::make_shared<WCSData>(image.width(), image.height(), info.fitsHeader);
|
||||
if(!info.wcs->valid())info.wcs.reset();
|
||||
}
|
||||
catch (pcl::Error err)
|
||||
catch (LibXISF::Error &err)
|
||||
{
|
||||
qDebug() << err.FormatInfo().ToUTF8().c_str();
|
||||
qDebug() << err.what();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -574,26 +559,6 @@ ConvertRunable::ConvertRunable(const QString &in, const QString &out, const QStr
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void writeXISFImage(pcl::XISFWriter &writer, RawImage *rawimg)
|
||||
{
|
||||
const cv::Mat &cvmat = rawimg->mat();
|
||||
T pclimg(rawimg->width(), rawimg->height(), cvmat.channels() == 1 ? pcl::ColorSpace::Gray : pcl::ColorSpace::RGB);
|
||||
if(cvmat.channels() == 1)
|
||||
{
|
||||
memcpy(pclimg.PixelData(0), rawimg->data(), rawimg->size()*sizeof(typename T::sample));
|
||||
}
|
||||
if(cvmat.channels() == 3)
|
||||
{
|
||||
std::vector<cv::Mat> channels;
|
||||
cv::split(cvmat, channels);
|
||||
memcpy(pclimg.PixelData(0), channels[0].data, rawimg->size()*sizeof(typename T::sample));
|
||||
memcpy(pclimg.PixelData(1), channels[1].data, rawimg->size()*sizeof(typename T::sample));
|
||||
memcpy(pclimg.PixelData(2), channels[2].data, rawimg->size()*sizeof(typename T::sample));
|
||||
}
|
||||
writer.WriteImage(pclimg);
|
||||
}
|
||||
|
||||
void writeFITSImage(fitsfile *fw, RawImage *rawimage, ImageInfoData &imageinfo)
|
||||
{
|
||||
static QStringList skipKeys = {"SIMPLE", "BITPIX", "NAXIS", "NAXIS1", "NAXIS2", "NAXIS3", "BZERO", "BSCALE", "EXTEND"};
|
||||
@@ -677,29 +642,37 @@ void ConvertRunable::run()
|
||||
{
|
||||
if(m_format == "XISF")
|
||||
{
|
||||
pcl::XISFOptions options;
|
||||
pcl::FITSKeywordArray fitskeywords;
|
||||
for(auto &record : imageinfo.fitsHeader)
|
||||
try
|
||||
{
|
||||
pcl::FITSHeaderKeyword key(pcl::IsoString(record.key.data()), pcl::IsoString(record.valueToByteArray().data()), pcl::IsoString(record.comment.data()));
|
||||
fitskeywords.Append(key);
|
||||
}
|
||||
pcl::XISFWriter xisf;
|
||||
xisf.Create(m_outfile.utf16(), 1);
|
||||
xisf.WriteFITSKeywords(fitskeywords);
|
||||
switch(CV_MAT_DEPTH(rawimage->dataType()))
|
||||
{
|
||||
case CV_8U:
|
||||
writeXISFImage<pcl::UInt8Image>(xisf, rawimage);
|
||||
break;
|
||||
case CV_16U:
|
||||
writeXISFImage<pcl::UInt16Image>(xisf, rawimage);
|
||||
break;
|
||||
case CV_32F:
|
||||
writeXISFImage<pcl::Image>(xisf, rawimage);
|
||||
break;
|
||||
}
|
||||
LibXISF::XISFWriter xisf;
|
||||
int channelCount = rawimage->mat().channels();
|
||||
LibXISF::Image::SampleFormat sampleFormat;
|
||||
switch(CV_MAT_DEPTH(rawimage->dataType()))
|
||||
{
|
||||
case CV_8U: sampleFormat = LibXISF::Image::UInt8; break;
|
||||
case CV_16U: sampleFormat = LibXISF::Image::UInt16; break;
|
||||
case CV_32F: sampleFormat = LibXISF::Image::Float32; break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
LibXISF::Image image(rawimage->width(), rawimage->height(), channelCount, sampleFormat, channelCount == 1 ? LibXISF::Image::Gray : LibXISF::Image::RGB, LibXISF::Image::Normal);
|
||||
std::memcpy(image.imageData(), rawimage->data(), image.imageDataSize());
|
||||
for(auto &record : imageinfo.fitsHeader)
|
||||
{
|
||||
if(record.value.type() == QVariant::Bool)
|
||||
image.addFITSKeyword({record.key, record.value.toBool() ? "T" : "F", record.comment});
|
||||
else
|
||||
image.addFITSKeyword({record.key, record.value.toString(), record.comment});
|
||||
}
|
||||
|
||||
xisf.writeImage(image);
|
||||
xisf.save(m_outfile);
|
||||
}
|
||||
catch(LibXISF::Error &err)
|
||||
{
|
||||
qDebug() << "Failed to save XISF image" << err.what();
|
||||
delete rawimage;
|
||||
}
|
||||
}
|
||||
|
||||
if(m_format == "FITS")
|
||||
|
||||
Reference in New Issue
Block a user