5 Commits

Author SHA1 Message Date
nou 7b70b6a081 More precise std::to_char support 2025-11-02 23:00:46 +01:00
nou 2e74d94641 Fix bug in XISFModify that corrupted files 2025-10-20 17:51:43 +02:00
nou 556bb22d26 Do not use bundled zlib by default 2025-08-12 18:37:58 +02:00
nou c6581e1122 Add method to modify XISF Property 2025-08-03 20:40:56 +02:00
nou fa39440b9e Add SSE optimized byte unshuffling 2025-07-24 20:21:34 +02:00
4 changed files with 95 additions and 10 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
option(USE_BUNDLED_LIBS "Use bundled LZ4 PugiXML and Zlib. You can still exclude some" ON) option(USE_BUNDLED_LIBS "Use bundled LZ4 PugiXML and Zlib. You can still exclude some" ON)
cmake_dependent_option(USE_BUNDLED_LZ4 "Use bundled LZ4" ON "USE_BUNDLED_LIBS" OFF) cmake_dependent_option(USE_BUNDLED_LZ4 "Use bundled LZ4" ON "USE_BUNDLED_LIBS" OFF)
cmake_dependent_option(USE_BUNDLED_PUGIXML "Use bundled PugiXML" ON "USE_BUNDLED_LIBS" OFF) cmake_dependent_option(USE_BUNDLED_PUGIXML "Use bundled PugiXML" ON "USE_BUNDLED_LIBS" OFF)
cmake_dependent_option(USE_BUNDLED_ZLIB "Use bundled Zlib" ON "USE_BUNDLED_LIBS" OFF) cmake_dependent_option(USE_BUNDLED_ZLIB "Use bundled Zlib" OFF "USE_BUNDLED_LIBS" OFF)
find_package(PkgConfig) find_package(PkgConfig)
+87 -6
View File
@@ -101,6 +101,51 @@ static void byteShuffle(ByteArray &data, int itemSize)
} }
} }
#ifdef __SSE2__
#include <x86intrin.h>
template<int itemSize>
size_t byteUnshuffleSSE(const char *in, char *out, size_t num)
{
//size_t size = num;
const __m128i *_in[4] = {(const __m128i*)in,
(const __m128i*)(in + num),
(const __m128i*)(in + num * 2),
(const __m128i*)(in + num * 3)};
__m128i *_out = (__m128i*)out;
num /= 16;
for(size_t i = 0; i < num; i++)
{
if constexpr(itemSize == 4)
{
__m128i a = _mm_loadu_si128(_in[0] + i);
__m128i b = _mm_loadu_si128(_in[1] + i);
__m128i c = _mm_loadu_si128(_in[2] + i);
__m128i d = _mm_loadu_si128(_in[3] + i);
__m128i x = _mm_unpacklo_epi8(a, b);
__m128i y = _mm_unpackhi_epi8(a, b);
__m128i z = _mm_unpacklo_epi8(c, d);
__m128i w = _mm_unpackhi_epi8(c, d);
_mm_storeu_si128(_out + i * 4, _mm_unpacklo_epi16(x, z));
_mm_storeu_si128(_out + i * 4 + 1, _mm_unpackhi_epi16(x, z));
_mm_storeu_si128(_out + i * 4 + 2, _mm_unpacklo_epi16(y, w));
_mm_storeu_si128(_out + i * 4 + 3, _mm_unpackhi_epi16(y, w));
}
if constexpr(itemSize == 2)
{
__m128i a = _mm_loadu_si128(_in[0] + i);
__m128i b = _mm_loadu_si128(_in[1] + i);
__m128i x = _mm_unpacklo_epi8(a, b);
__m128i y = _mm_unpackhi_epi8(a, b);
_mm_storeu_si128(_out + i * 2, x);
_mm_storeu_si128(_out + i * 2 + 1, y);
}
}
return num * 16 * itemSize;
}
#endif
static void byteUnshuffle(ByteArray &data, int itemSize) static void byteUnshuffle(ByteArray &data, int itemSize)
{ {
if(itemSize > 1) if(itemSize > 1)
@@ -108,11 +153,19 @@ static void byteUnshuffle(ByteArray &data, int itemSize)
ByteArray &input = data; ByteArray &input = data;
ByteArray output(input.size()); ByteArray output(input.size());
size_t num = input.size() / itemSize; size_t num = input.size() / itemSize;
const char *s = input.constData(); size_t off = 0;
#ifdef __SSE2__
if(itemSize == 4)
off = byteUnshuffleSSE<4>(input.data(), output.data(), num);
if(itemSize == 2)
off = byteUnshuffleSSE<2>(input.data(), output.data(), num);
#endif
const char *s = input.constData() + off;
for(int i=0; i<itemSize; i++) for(int i=0; i<itemSize; i++)
{ {
char *u = output.data() + i; char *u = output.data() + i + off;
for(size_t o=0; o<num; o++, s++, u += itemSize) for(size_t o = off / itemSize; o < num; o++, s++, u += itemSize)
*u = *s; *u = *s;
} }
memcpy(output.data() + num * itemSize, s, input.size() % itemSize); memcpy(output.data() + num * itemSize, s, input.size() % itemSize);
@@ -981,11 +1034,11 @@ public:
void save(std::ostream &io); void save(std::ostream &io);
void writeImage(const Image &image); void writeImage(const Image &image);
static void writeFITSKeyword(pugi::xml_node &node, const FITSKeyword &keyword); static void writeFITSKeyword(pugi::xml_node &node, const FITSKeyword &keyword);
static void writePropertyElement(pugi::xml_node &node, const Property &property);
private: private:
void writeHeader(); void writeHeader();
void writeImageElement(pugi::xml_node &node, const Image &image); void writeImageElement(pugi::xml_node &node, const Image &image);
void writeDataBlockAttributes(pugi::xml_node &image_node, const DataBlock &dataBlock); void writeDataBlockAttributes(pugi::xml_node &image_node, const DataBlock &dataBlock);
void writePropertyElement(pugi::xml_node &node, const Property &property);
void writeMetadata(pugi::xml_node &node); void writeMetadata(pugi::xml_node &node);
void updateImageAttachmentPos(pugi::xml_node &root, size_t offset); void updateImageAttachmentPos(pugi::xml_node &root, size_t offset);
ByteArray _xisfHeader; ByteArray _xisfHeader;
@@ -1318,6 +1371,7 @@ public:
void addFITSKeyword(uint32_t image, const FITSKeyword &keyword); void addFITSKeyword(uint32_t image, const FITSKeyword &keyword);
void updateFITSKeyword(uint32_t image, const FITSKeyword &keyword, bool add); void updateFITSKeyword(uint32_t image, const FITSKeyword &keyword, bool add);
void removeFITSKeyword(uint32_t image, const String &name); void removeFITSKeyword(uint32_t image, const String &name);
void updateProperty(uint32_t image, const Property &property);
private: private:
void readXISFHeader(); void readXISFHeader();
void parseAttachmentPos(pugi::xml_node &root); void parseAttachmentPos(pugi::xml_node &root);
@@ -1329,7 +1383,6 @@ private:
pugi::xml_document _doc; pugi::xml_document _doc;
pugi::xml_node _root; pugi::xml_node _root;
std::map<int, std::pair<uint64_t, uint64_t>> _attachmentPos;// pair contain position and size std::map<int, std::pair<uint64_t, uint64_t>> _attachmentPos;// pair contain position and size
std::map<int, std::pair<uint64_t, uint64_t>> _attachmentPosNew;
}; };
@@ -1392,6 +1445,8 @@ void XISFModifyPrivate::save(std::ostream &io)
doc.append_child(pugi::node_comment).set_value("\nExtensible Image Serialization Format - XISF version 1.0\nCreated with libXISF - https://nouspiro.space\n"); doc.append_child(pugi::node_comment).set_value("\nExtensible Image Serialization Format - XISF version 1.0\nCreated with libXISF - https://nouspiro.space\n");
pugi::xml_node root_copy = doc.append_copy(_root); pugi::xml_node root_copy = doc.append_copy(_root);
parseAttachmentPos(_root);
uint32_t size = 0; uint32_t size = 0;
std::string header; std::string header;
while(true) while(true)
@@ -1498,6 +1553,27 @@ void XISFModifyPrivate::removeFITSKeyword(uint32_t image, const String &name)
imageNode.remove_child(keywordNode); imageNode.remove_child(keywordNode);
} }
void XISFModifyPrivate::updateProperty(uint32_t image, const Property &property)
{
if(!_root)
throw Error("No input file opened");
pugi::xpath_node_set images = _root.select_nodes("//Image");
if(image >= images.size())
throw Error("Out of bounds");
pugi::xpath_variable_set variables;
variables.set("id", property.id.c_str());
pugi::xml_node imageNode = images[image].node();
pugi::xml_node propertyNode = imageNode.select_node("Property[@id=string($id)]", &variables).node();
if(propertyNode)
imageNode.remove_child(propertyNode);
XISFWriterPrivate::writePropertyElement(imageNode, property);
}
void XISFModifyPrivate::readXISFHeader() void XISFModifyPrivate::readXISFHeader()
{ {
char signature[8]; char signature[8];
@@ -1526,6 +1602,7 @@ void XISFModifyPrivate::readXISFHeader()
void XISFModifyPrivate::parseAttachmentPos(pugi::xml_node &root) void XISFModifyPrivate::parseAttachmentPos(pugi::xml_node &root)
{ {
_attachmentPos.clear();
pugi::xpath_node_set locationAttributes = root.select_nodes("//@location"); pugi::xpath_node_set locationAttributes = root.select_nodes("//@location");
int i = 0; int i = 0;
for(auto &attr : locationAttributes) for(auto &attr : locationAttributes)
@@ -1550,7 +1627,6 @@ void XISFModifyPrivate::updateAttachmentPos(pugi::xml_node &root, size_t offset)
pugi::xml_attribute attr = locationAttributes[pos.first].attribute(); pugi::xml_attribute attr = locationAttributes[pos.first].attribute();
uint64_t attachmentSize = pos.second.second; uint64_t attachmentSize = pos.second.second;
std::string locationStr = "attachment:" + std::to_string(offset) + ":" + std::to_string(attachmentSize); std::string locationStr = "attachment:" + std::to_string(offset) + ":" + std::to_string(attachmentSize);
_attachmentPosNew[pos.first] = pos.second;
offset += attachmentSize; offset += attachmentSize;
attr.set_value(locationStr.c_str()); attr.set_value(locationStr.c_str());
} }
@@ -1616,6 +1692,11 @@ void XISFModify::removeFITSKeyword(uint32_t image, const String &name)
p->removeFITSKeyword(image, name); p->removeFITSKeyword(image, name);
} }
void XISFModify::updateProperty(uint32_t image, const Property &property)
{
p->updateProperty(image, property);
}
#define STRING_ENUM(map, map2, c, e) { map.insert({#e, c::e}); map2.insert({c::e, #e}); } #define STRING_ENUM(map, map2, c, e) { map.insert({#e, c::e}); map2.insert({c::e, #e}); }
struct Init struct Init
+6
View File
@@ -443,6 +443,12 @@ public:
* @param name of keyword that will be removed * @param name of keyword that will be removed
*/ */
void removeFITSKeyword(uint32_t image, const String &name); void removeFITSKeyword(uint32_t image, const String &name);
/**
* @brief updateProperty add new or update existing XISF Property
* @param image index of image to update
* @param property new value of property
*/
void updateProperty(uint32_t image, const Property &property);
private: private:
XISFModifyPrivate *p; XISFModifyPrivate *p;
}; };
+1 -3
View File
@@ -17,7 +17,6 @@
************************************************************************/ ************************************************************************/
#include <charconv> #include <charconv>
#include <type_traits>
#include <map> #include <map>
#include <regex> #include <regex>
#include <iomanip> #include <iomanip>
@@ -403,7 +402,6 @@ Variant variantFromString(Variant::Type type, const String &str)
Variant::Type Variant::type() const Variant::Type Variant::type() const
{ {
int idx = _value.index();
return (Variant::Type)_value.index(); return (Variant::Type)_value.index();
} }
@@ -442,7 +440,7 @@ String Variant::toString() const
ss << "{"; ss << "{";
for(int o=0; o<matrix.cols(); o++) for(int o=0; o<matrix.cols(); o++)
{ {
#if __GNUC__ >= 11 || __clang__ #if __GNUC__ >= 11 || __clang_major__ >= 15
char str[128] = {0}; char str[128] = {0};
char *end = str + sizeof(str); char *end = str + sizeof(str);
std::to_chars(str, end, matrix(i, o)); std::to_chars(str, end, matrix(i, o));