Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| faf4a2f4d5 | |||
| 29a467b694 | |||
| 2107d68e71 | |||
| 2e8bbf6e30 | |||
| a0968bba3a | |||
| 4f48eebb10 | |||
| 3141092456 | |||
| 02e3aba6a7 | |||
| 43af787370 | |||
| 5266ea4105 | |||
| d2c264fcc5 | |||
| d3559a1ebc |
+11
-3
@@ -1,6 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
project(libXISF VERSION 0.1.0 LANGUAGES CXX C)
|
||||
project(libXISF VERSION 0.1.2 LANGUAGES CXX C)
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
@@ -12,7 +12,9 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED)
|
||||
|
||||
add_library(XISF SHARED
|
||||
option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
|
||||
|
||||
add_library(XISF
|
||||
libXISF_global.h
|
||||
libxisf.cpp
|
||||
libxisf.h
|
||||
@@ -22,9 +24,15 @@ add_library(XISF SHARED
|
||||
lz4/lz4hc.h
|
||||
)
|
||||
|
||||
set_target_properties(XISF PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR})
|
||||
|
||||
target_link_libraries(XISF PUBLIC Qt${QT_VERSION_MAJOR}::Core)
|
||||
|
||||
target_compile_definitions(XISF PRIVATE LIBXISF_LIBRARY)
|
||||
if(BUILD_SHARED_LIBS)
|
||||
target_compile_definitions(XISF PRIVATE LIBXISF_LIBRARY)
|
||||
else(BUILD_SHARED_LIBS)
|
||||
target_compile_definitions(XISF PUBLIC LIBXISF_STATIC_LIB)
|
||||
endif(BUILD_SHARED_LIBS)
|
||||
|
||||
set(XISF_PUBLIC_HEADERS libxisf.h libXISF_global.h)
|
||||
|
||||
|
||||
Vendored
+18
@@ -1,3 +1,21 @@
|
||||
libxisf (0.1.3-ubuntu1) focal; urgency=medium
|
||||
|
||||
* Write missing pixelStorage attribute
|
||||
|
||||
-- Dušan Poizl <nou@nouspiro.space> Fri, 17 Feb 2023 16:57:30 +0100
|
||||
|
||||
libxisf (0.1.2-ubuntu1) focal; urgency=medium
|
||||
|
||||
* Add qtbase5-dev as dependency to libxisf-dev
|
||||
|
||||
-- Dušan Poizl <nou@nouspiro.space> Thu, 09 Feb 2023 21:28:45 +0100
|
||||
|
||||
libxisf (0.1.1-ubuntu1) focal; urgency=medium
|
||||
|
||||
* Fixed packaging
|
||||
|
||||
-- Dušan Poizl <nou@nouspiro.space> Wed, 08 Feb 2023 18:57:50 +0100
|
||||
|
||||
libxisf (0.1.0-ubuntu1) focal; urgency=low
|
||||
|
||||
* Initial release.
|
||||
|
||||
Vendored
+1
-1
@@ -14,7 +14,7 @@ Package: libxisf-dev
|
||||
Section: libdevel
|
||||
Architecture: any
|
||||
Multi-Arch: same
|
||||
Depends: libxisf (= ${binary:Version}), ${misc:Depends}
|
||||
Depends: libxisf (= ${binary:Version}), ${misc:Depends}, qtbase5-dev
|
||||
Description: Library to load and save XISF images
|
||||
Native format of PixInsight astroprocessing suite
|
||||
|
||||
|
||||
Vendored
+1
@@ -1 +1,2 @@
|
||||
usr/include
|
||||
usr/lib/*/*.so
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
usr/lib
|
||||
usr/lib/*/*.so.*
|
||||
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
activate-noawait ldconfig
|
||||
+6
-2
@@ -21,10 +21,14 @@
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#if defined(LIBXISF_LIBRARY)
|
||||
# define LIBXISF_EXPORT Q_DECL_EXPORT
|
||||
#ifdef LIBXISF_STATIC_LIB
|
||||
# define LIBXISF_EXPORT
|
||||
#else
|
||||
# if defined(LIBXISF_LIBRARY)
|
||||
# define LIBXISF_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define LIBXISF_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif // LIBXISF_GLOBAL_H
|
||||
|
||||
+51
-11
@@ -26,6 +26,7 @@
|
||||
#include <QElapsedTimer>
|
||||
#include <QFile>
|
||||
#include <QBuffer>
|
||||
#include <QProcessEnvironment>
|
||||
#include "lz4/lz4.h"
|
||||
#include "lz4/lz4hc.h"
|
||||
|
||||
@@ -89,6 +90,9 @@ static std::unordered_map<QString, Image::ColorSpace> colorSpaceToEnum;
|
||||
static std::unordered_map<Image::ColorSpace, QString> colorSpaceToString;
|
||||
static std::unordered_map<int, size_t> vectorTypeSizes;
|
||||
static std::unordered_map<int, size_t> matrixTypeSizes;
|
||||
static DataBlock::CompressionCodec compressionCodecOverride = DataBlock::None;
|
||||
static bool byteShuffleOverride = false;
|
||||
static int compressionLevelOverride = -1;
|
||||
|
||||
static const std::unordered_map<QString, std::pair<QString, int>> fitsNameToPropertyIdTypeConvert = {
|
||||
{"OBSERVER", {"Observer:Name", QMetaType::QString}},
|
||||
@@ -197,20 +201,22 @@ void DataBlock::decompress(const QByteArray &input, const QString &encoding)
|
||||
attachmentPos = 0;
|
||||
}
|
||||
|
||||
void DataBlock::compress()
|
||||
void DataBlock::compress(int sampleFormatSize)
|
||||
{
|
||||
QByteArray tmp = data;
|
||||
uncompressedSize = data.size();
|
||||
|
||||
byteShuffle(tmp, byteShuffling);
|
||||
byteShuffle(tmp, byteShuffleOverride ? sampleFormatSize : byteShuffling);
|
||||
|
||||
switch(codec)
|
||||
CompressionCodec useCodec = compressionCodecOverride != CompressionCodec::None ? compressionCodecOverride : codec;
|
||||
int cLevel = compressionLevelOverride != -1 ? compressionLevelOverride : compressLevel;
|
||||
switch(useCodec)
|
||||
{
|
||||
case None:
|
||||
data = tmp;
|
||||
break;
|
||||
case Zlib:
|
||||
data = qCompress(tmp);
|
||||
data = qCompress(tmp, cLevel);
|
||||
data.remove(0, sizeof(uint32_t));
|
||||
break;
|
||||
case LZ4:
|
||||
@@ -218,10 +224,10 @@ void DataBlock::compress()
|
||||
{
|
||||
int compSize = 0;
|
||||
data.resize(LZ4_compressBound(tmp.size()));
|
||||
if(codec == LZ4)
|
||||
if(useCodec == LZ4)
|
||||
compSize = LZ4_compress_default(tmp.constData(), data.data(), tmp.size(), data.size());
|
||||
else
|
||||
compSize = LZ4_compress_HC(tmp.constData(), data.data(), tmp.size(), data.size(), LZ4HC_CLEVEL_DEFAULT);
|
||||
compSize = LZ4_compress_HC(tmp.constData(), data.data(), tmp.size(), data.size(), cLevel < 0 ? LZ4HC_CLEVEL_DEFAULT : cLevel);
|
||||
|
||||
if(compSize <= 0)
|
||||
throw Error("LZ4 compression failed");
|
||||
@@ -327,6 +333,7 @@ Image::SampleFormat Image::sampleFormat() const
|
||||
void Image::setSampleFormat(SampleFormat newSampleFormat)
|
||||
{
|
||||
_sampleFormat = newSampleFormat;
|
||||
if(_dataBlock.byteShuffling)_dataBlock.byteShuffling = sampleFormatSize(_sampleFormat);
|
||||
_dataBlock.data.resize(_width * _height * _channelCount * sampleFormatSize(_sampleFormat));
|
||||
}
|
||||
|
||||
@@ -397,12 +404,12 @@ bool Image::addFITSKeywordAsProperty(const QString &name, const QVariant &value)
|
||||
|
||||
void *Image::imageData()
|
||||
{
|
||||
return _dataBlock.data.data();
|
||||
return _dataBlock.data.isNull() ? nullptr : _dataBlock.data.data();
|
||||
}
|
||||
|
||||
const void *Image::imageData() const
|
||||
{
|
||||
return _dataBlock.data.data();
|
||||
return _dataBlock.data.isNull() ? nullptr : _dataBlock.data.data();
|
||||
}
|
||||
|
||||
size_t Image::imageDataSize() const
|
||||
@@ -584,13 +591,13 @@ int XISFReader::imagesCount() const
|
||||
return _images.size();
|
||||
}
|
||||
|
||||
const Image& XISFReader::getImage(uint32_t n)
|
||||
const Image& XISFReader::getImage(uint32_t n, bool readPixels)
|
||||
{
|
||||
if(n >= _images.size())
|
||||
throw Error("Out of bounds");
|
||||
|
||||
Image &img = _images[n];
|
||||
if(img._dataBlock.attachmentPos)
|
||||
if(img._dataBlock.attachmentPos && readPixels)
|
||||
{
|
||||
_io->seek(img._dataBlock.attachmentPos);
|
||||
img._dataBlock.decompress(_io->read(img._dataBlock.attachmentSize));
|
||||
@@ -887,7 +894,7 @@ void XISFWriter::writeImage(const Image &image)
|
||||
{
|
||||
_images.push_back(image);
|
||||
_images.back()._dataBlock.attachmentPos = 1;
|
||||
_images.back()._dataBlock.compress();
|
||||
_images.back()._dataBlock.compress(image.sampleFormatSize(image.sampleFormat()));
|
||||
}
|
||||
|
||||
void XISFWriter::writeHeader()
|
||||
@@ -945,6 +952,7 @@ void XISFWriter::writeImageElement(const Image &image)
|
||||
_xml->writeAttribute("sampleFormat", Image::sampleFormatString(image._sampleFormat));
|
||||
_xml->writeAttribute("colorSpace", Image::colorSpaceString(image._colorSpace));
|
||||
_xml->writeAttribute("imageType", Image::imageTypeString(image._imageType));
|
||||
_xml->writeAttribute("pixelStorage", Image::pixelStorageString(image._pixelStorage));
|
||||
if((image._sampleFormat == Image::Float32 || image._sampleFormat == Image::Float64) ||
|
||||
image._bounds.first != 0.0 || image._bounds.second != 1.0)
|
||||
{
|
||||
@@ -959,6 +967,7 @@ void XISFWriter::writeImageElement(const Image &image)
|
||||
writeFITSKeyword(fitsKeyword);
|
||||
|
||||
writeCFA(image);
|
||||
writeICC(image._iccProfile);
|
||||
|
||||
_xml->writeEndElement();
|
||||
}
|
||||
@@ -1076,6 +1085,17 @@ void XISFWriter::writeCFA(const Image &image)
|
||||
}
|
||||
}
|
||||
|
||||
void XISFWriter::writeICC(const QByteArray &icc)
|
||||
{
|
||||
if(!icc.isEmpty())
|
||||
{
|
||||
QByteArray base64 = icc.toBase64();
|
||||
_xml->writeStartElement("ICCProfile");
|
||||
_xml->writeAttribute("location", "inline:base64");
|
||||
_xml->writeCharacters(base64);
|
||||
}
|
||||
}
|
||||
|
||||
#define REGISTER_METATYPE(type) { int id = qMetaTypeId<type>(); \
|
||||
typeToId.insert({#type, id}); idToType.insert({id, #type}); }
|
||||
|
||||
@@ -1214,6 +1234,26 @@ struct Init
|
||||
c.imag = s.rightRef(comma+1).toDouble();
|
||||
return c;
|
||||
});
|
||||
|
||||
QString compression = QProcessEnvironment::systemEnvironment().value("LIBXISF_COMPRESSION");
|
||||
if(!compression.isEmpty())
|
||||
{
|
||||
if(compression.startsWith("zlib"))
|
||||
compressionCodecOverride = DataBlock::Zlib;
|
||||
else if(compression.startsWith("lz4hc"))
|
||||
compressionCodecOverride = DataBlock::LZ4HC;
|
||||
else if(compression.startsWith("lz4"))
|
||||
compressionCodecOverride = DataBlock::LZ4;
|
||||
|
||||
if(compression.contains("+sh"))
|
||||
byteShuffleOverride = true;
|
||||
|
||||
int index = compression.lastIndexOf(":");
|
||||
if(index > 0)
|
||||
{
|
||||
compressionLevelOverride = compression.mid(index+1).toInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ struct DataBlock
|
||||
int compressLevel = -1;
|
||||
QByteArray data;
|
||||
void decompress(const QByteArray &input, const QString &encoding = "");
|
||||
void compress();
|
||||
void compress(int sampleFormatSize);
|
||||
};
|
||||
|
||||
struct LIBXISF_EXPORT Property
|
||||
@@ -227,7 +227,11 @@ public:
|
||||
void close();
|
||||
/** Return number of images inside file */
|
||||
int imagesCount() const;
|
||||
const Image& getImage(uint32_t n);
|
||||
/** Return reference to Image
|
||||
* @param n index of image
|
||||
* @param readPixel when false it will read pixel data from file and imageData()
|
||||
* will return nullptr */
|
||||
const Image& getImage(uint32_t n, bool readPixels = true);
|
||||
private:
|
||||
void readXISFHeader();
|
||||
void readSignature();
|
||||
@@ -262,6 +266,7 @@ private:
|
||||
void writeFITSKeyword(const FITSKeyword &keyword);
|
||||
void writeMetadata();
|
||||
void writeCFA(const Image &image);
|
||||
void writeICC(const QByteArray &icc);
|
||||
std::unique_ptr<QXmlStreamWriter> _xml;
|
||||
QByteArray _xisfHeader;
|
||||
QByteArray _attachmentsData;
|
||||
|
||||
Reference in New Issue
Block a user