diff --git a/CMakeLists.txt b/CMakeLists.txt index 715ff45..29f31ab 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.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.") @@ -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} @@ -106,6 +108,12 @@ 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_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) #testing diff --git a/debian/changelog b/debian/changelog index a7d3ef1..563eaeb 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +libxisf (0.2.6-ubuntu1) focal; urgency=medium + + * Add method for ICC profile + * pkg-config file support + + -- DuĊĦan Poizl Fri, 02 Jun 2023 09:16:59 +0200 + libxisf (0.2.4-ubuntu1) focal; urgency=medium * Add getThumbnail method diff --git a/libxisf.cpp b/libxisf.cpp index b6b7310..2293a20 100644 --- a/libxisf.cpp +++ b/libxisf.cpp @@ -27,6 +27,7 @@ #include #include #include +#include "streambuffer.h" namespace LibXISF { @@ -357,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; @@ -532,6 +543,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 +560,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 +577,7 @@ void XISFReaderPrivate::open(std::istream *io) void XISFReaderPrivate::close() { _io.reset(); + _buffer.reset(); _images.clear(); _properties.clear(); } @@ -839,10 +852,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/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; diff --git a/libxisf.pc.in b/libxisf.pc.in index b0b8b53..a64b9d5 100644 --- a/libxisf.pc.in +++ b/libxisf.pc.in @@ -7,7 +7,6 @@ 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@ 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