From a536a271ab98ffe2e66a6c412a71072808649e79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Du=C5=A1an=20Poizl?= Date: Sun, 21 May 2023 19:33:36 +0200 Subject: [PATCH 1/6] Add StreamBuffer to optimize save/load from memory --- CMakeLists.txt | 2 + libxisf.cpp | 13 +++-- streambuffer.cpp | 144 +++++++++++++++++++++++++++++++++++++++++++++++ streambuffer.h | 33 +++++++++++ 4 files changed, 187 insertions(+), 5 deletions(-) create mode 100644 streambuffer.cpp create mode 100644 streambuffer.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 715ff45..be70469 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,6 +66,8 @@ add_library(XISF libXISF_global.h libxisf.cpp libxisf.h + streambuffer.cpp + streambuffer.h utils.cpp variant.cpp ${THIRD_PARTY_SRC} diff --git a/libxisf.cpp b/libxisf.cpp index b6b7310..c25293f 100644 --- a/libxisf.cpp +++ b/libxisf.cpp @@ -27,6 +27,7 @@ #include #include #include +#include "streambuffer.h" namespace LibXISF { @@ -532,6 +533,7 @@ private: Image parseImage(const pugi::xml_node &node); std::unique_ptr _io; + std::unique_ptr _buffer; std::vector _images; Image _thumbnail; std::vector _properties; @@ -548,8 +550,8 @@ void XISFReaderPrivate::open(const String &name) void XISFReaderPrivate::open(const ByteArray &data) { close(); - std::string str((char*)data.data(), data.size()); - _io = std::make_unique(str, std::ios_base::in | std::ios_base::binary); + _buffer = std::make_unique(data); + _io = std::make_unique(_buffer.get()); readSignature(); readXISFHeader(); } @@ -565,6 +567,7 @@ void XISFReaderPrivate::open(std::istream *io) void XISFReaderPrivate::close() { _io.reset(); + _buffer.reset(); _images.clear(); _properties.clear(); } @@ -839,10 +842,10 @@ void XISFWriterPrivate::save(const String &name) void XISFWriterPrivate::save(ByteArray &data) { - std::ostringstream oss; + StreamBuffer buffer; + std::ostream oss(&buffer); save(oss); - std::string str = oss.str(); - data = ByteArray(str.data(), str.size()); + data = buffer.byteArray(); } void XISFWriterPrivate::save(std::ostream &io) diff --git a/streambuffer.cpp b/streambuffer.cpp new file mode 100644 index 0000000..dcebdf8 --- /dev/null +++ b/streambuffer.cpp @@ -0,0 +1,144 @@ +#include "streambuffer.h" + +namespace LibXISF +{ + +StreamBuffer::StreamBuffer() +{ + setg(nullptr, nullptr, nullptr); + setp(nullptr, nullptr); +} + +StreamBuffer::StreamBuffer(const ByteArray &byteArray) : + _size(byteArray.size()), + _byteArray(byteArray) +{ + if(_byteArray.size()) + { + char *ptr = _byteArray.data(); + setg(ptr, ptr, ptr + _size); + setp(ptr, ptr + _size); + } + else + { + setg(nullptr, nullptr, nullptr); + setp(nullptr, nullptr); + } +} + +ByteArray StreamBuffer::byteArray() +{ + return _byteArray; +} + +StreamBuffer::pos_type StreamBuffer::seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode mode) +{ + pos_type ret = pos_type(off_type(-1)); + off_type newoffi = off; + off_type newoffo = off; + if(dir == std::ios_base::cur) + { + newoffi += gptr() - eback(); + newoffo += pptr() - pbase(); + } + else if(dir == std::ios_base::end) + newoffo = newoffi = _byteArray.size() - off; + + char *ptr = _byteArray.data(); + if(mode & std::ios_base::in && newoffi >= 0 && newoffi <= _size) + { + setg(ptr, ptr + newoffi, ptr + _size); + ret = pos_type(newoffi); + } + + if(mode & std::ios_base::out && newoffo >= 0 && newoffo <= _size) + { + setp(ptr, ptr + _size); + pbump(newoffo); + ret = pos_type(newoffo); + } + + return ret; +} + +StreamBuffer::pos_type StreamBuffer::seekpos(pos_type pos, std::ios_base::openmode mode) +{ + pos_type ret = pos_type(off_type(-1)); + off_type off = pos; + + if(off >= 0 && off <= (off_type)_byteArray.size()) + { + char *ptr = _byteArray.data(); + if(mode & std::ios_base::in) + setg(ptr, ptr + pos, ptr + _size); + + if(mode & std::ios_base::out) + { + setp(ptr, ptr + _size); + pbump(pos); + } + + ret = pos; + } + return ret; +} + +std::streamsize StreamBuffer::xsgetn(char_type *s, std::streamsize n) +{ + std::streamsize ret = 0; + std::streamsize len = egptr() - gptr(); + if(len > 0) + { + std::streamsize c = std::min(n, len); + std::memcpy(s, gptr(), c); + gbump(c); + ret = c; + } + return ret; +} + +StreamBuffer::int_type StreamBuffer::underflow() +{ + if(gptr() < egptr()) + return traits_type::to_int_type(*gptr()); + else + return traits_type::eof(); +} + +std::streamsize StreamBuffer::xsputn(const char_type *s, std::streamsize n) +{ + off_type len = epptr() - pptr(); + if(len < n) + { + _size += n - len; + _byteArray.resize(_size); + update_ptrs(); + } + std::memcpy(pptr(), s, n); + pbump(n); + return n; +} + +StreamBuffer::int_type StreamBuffer::overflow(int_type c) +{ + if(traits_type::eq_int_type(traits_type::eof(), c)) + return traits_type::eof(); + + _byteArray.append(c); + _size++; + pbump(1); + update_ptrs(); + return c; +} + +void StreamBuffer::update_ptrs() +{ + off_type ipos = gptr() - eback(); + off_type opos = pptr() - pbase(); + char *ptr = _byteArray.data(); + setg(ptr, ptr + ipos, ptr + _size); + setp(ptr, ptr + _size); + pbump(opos); +} + +} diff --git a/streambuffer.h b/streambuffer.h new file mode 100644 index 0000000..aff3920 --- /dev/null +++ b/streambuffer.h @@ -0,0 +1,33 @@ +#ifndef STREAMBUFFER_H +#define STREAMBUFFER_H + +#include +#include "libxisf.h" + +namespace LibXISF +{ + +class StreamBuffer : public std::streambuf +{ +public: + StreamBuffer(); + StreamBuffer(const ByteArray &byteArray); + ByteArray byteArray(); +protected: + pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) override; + pos_type seekpos(pos_type pos, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) override; + + std::streamsize xsgetn(char_type *s, std::streamsize n) override; + int_type underflow() override; + + std::streamsize xsputn(const char_type *s, std::streamsize n) override; + int_type overflow(int_type c = traits_type::eof()) override; +private: + void update_ptrs(); + off_type _size = 0; + ByteArray _byteArray; +}; + +} + +#endif // STREAMBUFFER_H From 0893bfa04883fb9b5756d0e1740c92e87d00f4ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Du=C5=A1an=20Poizl?= Date: Wed, 24 May 2023 16:27:28 +0200 Subject: [PATCH 2/6] Add method to for ICC profile --- CMakeLists.txt | 2 +- libxisf.cpp | 10 ++++++++++ libxisf.h | 2 ++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index be70469..0e37c44 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.14) -project(libXISF VERSION 0.2.4 LANGUAGES CXX C +project(libXISF VERSION 0.2.5 LANGUAGES CXX C HOMEPAGE_URL https://gitea.nouspiro.space/nou/libXISF DESCRIPTION "LibXISF is C++ library that can read and write XISF files produced by PixInsight.") diff --git a/libxisf.cpp b/libxisf.cpp index c25293f..2293a20 100644 --- a/libxisf.cpp +++ b/libxisf.cpp @@ -358,6 +358,16 @@ bool Image::addFITSKeywordAsProperty(const String &name, const String &value) return false; } +const ByteArray &Image::iccProfile() const +{ + return _iccProfile; +} + +void Image::setIccProfile(const ByteArray &iccProfile) +{ + _iccProfile = iccProfile; +} + void *Image::imageData() { return _dataBlock.data.size() ? _dataBlock.data.data() : nullptr; diff --git a/libxisf.h b/libxisf.h index 86d7223..89c5e14 100644 --- a/libxisf.h +++ b/libxisf.h @@ -301,6 +301,8 @@ public: * For example OBSERVER => Observer:Name, SITELAT => Observation:Location:Latitude */ bool addFITSKeywordAsProperty(const String &name, const String &value); + const ByteArray& iccProfile() const; + void setIccProfile(const ByteArray &iccProfile); void* imageData(); const void* imageData() const; From 5dcc383090dc5e17982ee6f4371de700e1790320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Du=C5=A1an=20Poizl?= Date: Mon, 29 May 2023 22:59:24 +0200 Subject: [PATCH 3/6] Fix generating pkgconfig file --- CMakeLists.txt | 3 +++ libxisf.pc.in | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e37c44..ea2d104 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,6 +108,9 @@ install(FILES ${XISF_PUBLIC_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libxisf.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) install(TARGETS XISF LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) +list(JOIN PC_LIBS_REQUIRE ", " PC_REQUIRE_STR) +list(TRANSFORM PC_LIBS_REQUIRE PREPEND "-l") +list(JOIN PC_LIBS_REQUIRE " " PC_LIBS_STR) configure_file(libxisf.pc.in libxisf.pc @ONLY) #testing diff --git a/libxisf.pc.in b/libxisf.pc.in index b0b8b53..7d58f56 100644 --- a/libxisf.pc.in +++ b/libxisf.pc.in @@ -7,7 +7,7 @@ Name: @PROJECT_NAME@ Description: @CMAKE_PROJECT_DESCRIPTION@ URL: @CMAKE_PROJECT_HOMEPAGE_URL@ Version: @PROJECT_VERSION@ -Requires.private: @PC_LIBS_REQUIRE@ +Requires.private: @PC_REQUIRE_STR@ Cflags: -I"${includedir}" Libs: -L"${libdir}" -lXISF -Libs.private: -L"${libdir}" @PC_LIBS_REQUIRE@ +Libs.private: -L"${libdir}" @PC_LIBS_STR@ From 0ddff094ef2a20bba5d749b23758471791a9d62a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Du=C5=A1an=20Poizl?= Date: Mon, 29 May 2023 23:16:53 +0200 Subject: [PATCH 4/6] Fix generating pkgconfig file --- CMakeLists.txt | 3 ++- libxisf.pc.in | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ea2d104..e505e78 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,7 +108,8 @@ install(FILES ${XISF_PUBLIC_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libxisf.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) install(TARGETS XISF LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) -list(JOIN PC_LIBS_REQUIRE ", " PC_REQUIRE_STR) +list(JOIN PC_LIBS_REQUIRE ", " PC_REQUIRE_STR2) +string(REPLACE "lz4" "liblz4" PC_REQUIRE_STR ${PC_REQUIRE_STR2}) list(TRANSFORM PC_LIBS_REQUIRE PREPEND "-l") list(JOIN PC_LIBS_REQUIRE " " PC_LIBS_STR) configure_file(libxisf.pc.in libxisf.pc @ONLY) diff --git a/libxisf.pc.in b/libxisf.pc.in index 7d58f56..a64b9d5 100644 --- a/libxisf.pc.in +++ b/libxisf.pc.in @@ -10,4 +10,3 @@ Version: @PROJECT_VERSION@ Requires.private: @PC_REQUIRE_STR@ Cflags: -I"${includedir}" Libs: -L"${libdir}" -lXISF -Libs.private: -L"${libdir}" @PC_LIBS_STR@ From cde2fc9a1799fa3bbe120d631966ac1873afc73f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Du=C5=A1an=20Poizl?= Date: Wed, 31 May 2023 14:56:26 +0200 Subject: [PATCH 5/6] Fix "string sub-command REPLACE requires at least four arguments" --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e505e78..166f62d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,7 +109,9 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libxisf.pc DESTINATION ${CMAKE_INSTALL install(TARGETS XISF LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) list(JOIN PC_LIBS_REQUIRE ", " PC_REQUIRE_STR2) -string(REPLACE "lz4" "liblz4" PC_REQUIRE_STR ${PC_REQUIRE_STR2}) +if(NOT PC_REQUIRE_STR2 STREQUAL "") + string(REPLACE "lz4" "liblz4" PC_REQUIRE_STR ${PC_REQUIRE_STR2}) +endif() list(TRANSFORM PC_LIBS_REQUIRE PREPEND "-l") list(JOIN PC_LIBS_REQUIRE " " PC_LIBS_STR) configure_file(libxisf.pc.in libxisf.pc @ONLY) From 76ee3f361cf74a67755b03e2e7c8f8059475ed3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Du=C5=A1an=20Poizl?= Date: Fri, 2 Jun 2023 08:50:37 +0200 Subject: [PATCH 6/6] Release 0.2.6 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 166f62d..29f31ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.14) -project(libXISF VERSION 0.2.5 LANGUAGES CXX C +project(libXISF VERSION 0.2.6 LANGUAGES CXX C HOMEPAGE_URL https://gitea.nouspiro.space/nou/libXISF DESCRIPTION "LibXISF is C++ library that can read and write XISF files produced by PixInsight.")