File _service:download_files:931a40a..823918e.patch of Package exiv2
From 04e4923bbdbd420b76f86960f5f32e3f07151495 Mon Sep 17 00:00:00 2001
From: antermin <103918092+antermin@users.noreply.github.com>
Date: Thu, 8 Jun 2023 20:16:05 +0900
Subject: [PATCH 1/3] Add getUint64_t
---
src/helper_functions.cpp | 9 +++++++++
src/helper_functions.hpp | 5 +++++
2 files changed, 14 insertions(+)
diff --git a/src/helper_functions.cpp b/src/helper_functions.cpp
index 6894ab3911..804b64140a 100644
--- a/src/helper_functions.cpp
+++ b/src/helper_functions.cpp
@@ -62,4 +62,13 @@ std::string getAspectRatio(uint64_t width, uint64_t height) {
return std::to_string(ratioWidth) + ":" + std::to_string(ratioHeight);
}
+uint64_t getUint64_t(Exiv2::DataBuf& buf) {
+ uint64_t temp = 0;
+
+ for(size_t i = 0; i < buf.size(); ++i){
+ temp = temp + static_cast<uint64_t>((buf.read_uint8(i))*(pow(static_cast<float>(256), static_cast<float>(i))));
+ }
+ return temp;
+}
+
} // namespace Exiv2
diff --git a/src/helper_functions.hpp b/src/helper_functions.hpp
index a7c820e917..a56e80fab0 100644
--- a/src/helper_functions.hpp
+++ b/src/helper_functions.hpp
@@ -47,5 +47,10 @@ static constexpr size_t GUID = 0x10;
*/
[[nodiscard]] std::string getAspectRatio(uint64_t width, uint64_t height);
+/*!
+ @brief Converts buffer data into 64-bit Integer, information stored in littleEndian format
+ */
+[[nodiscard]] uint64_t getUint64_t(Exiv2::DataBuf& buf);
+
} // namespace Exiv2
#endif // HELPER_FUNCTIONS_HPP
From 27a99a3f8bd009048e31ce8061d8b0b84da6ba46 Mon Sep 17 00:00:00 2001
From: antermin <103918092+antermin@users.noreply.github.com>
Date: Thu, 8 Jun 2023 20:16:36 +0900
Subject: [PATCH 2/3] Experimental JXL/codestream support
---
include/exiv2/image_types.hpp | 1 +
include/exiv2/jxlimage.hpp | 85 ++++++++++++++++++++++++++++
src/CMakeLists.txt | 3 +
src/image.cpp | 2 +
src/jxlimage.cpp | 103 ++++++++++++++++++++++++++++++++++
src/jxlimage_int.cpp | 67 ++++++++++++++++++++++
src/jxlimage_int.hpp | 25 +++++++++
7 files changed, 286 insertions(+)
create mode 100644 include/exiv2/jxlimage.hpp
create mode 100644 src/jxlimage.cpp
create mode 100644 src/jxlimage_int.cpp
create mode 100644 src/jxlimage_int.hpp
diff --git a/include/exiv2/image_types.hpp b/include/exiv2/image_types.hpp
index 93502c2b48..ebf556f8bf 100644
--- a/include/exiv2/image_types.hpp
+++ b/include/exiv2/image_types.hpp
@@ -20,6 +20,7 @@ enum class ImageType {
gif, ///< GIF
jp2, ///< JPEG-2000
jpeg,
+ jxl, ///< JPEG XL (JXL)
mrw,
nef,
orf,
diff --git a/include/exiv2/jxlimage.hpp b/include/exiv2/jxlimage.hpp
new file mode 100644
index 0000000000..1db2966eb4
--- /dev/null
+++ b/include/exiv2/jxlimage.hpp
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/*!
+ @author antermin
+ @date 18-Mar-2023, antermin: created
+ */
+#ifndef JXLIMAGE_HPP_
+#define JXLIMAGE_HPP_
+
+// *****************************************************************************
+#include "exiv2lib_export.h"
+
+// included header files
+#include "image.hpp"
+
+// *****************************************************************************
+// namespace extensions
+namespace Exiv2 {
+// *****************************************************************************
+// class definitions
+
+/*!
+ @brief Class to access JPEG XL bare codestream. This is just a stub - we only
+ read width and height.
+*/
+class EXIV2API JxlImage : public Image {
+ public:
+ //! @name Creators
+ //@{
+ /*!
+ @brief Constructor to open a JPEG XL bare codestream. Since the
+ constructor can not return a result, callers should check the
+ good() method after object construction to determine success
+ or failure.
+ @param io An auto-pointer that owns a BasicIo instance used for
+ reading and writing image metadata. \b Important: The constructor
+ takes ownership of the passed in BasicIo instance through the
+ auto-pointer. Callers should not continue to use the BasicIo
+ instance after it is passed to this method. Use the Image::io()
+ method to get a temporary reference.
+ */
+ explicit JxlImage(BasicIo::UniquePtr io);
+ //@}
+
+ //! @name Manipulators
+ //@{
+ void readMetadata() override;
+
+ /// @throws Error(ErrorCode::kerWritingImageFormatUnsupported).
+ void writeMetadata() override;
+
+ /// @throws Error(ErrorCode::kerInvalidSettingForImage)
+ void setExifData(const ExifData& exifData) override;
+
+ /// @throws Error(ErrorCode::kerInvalidSettingForImage)
+ void setIptcData(const IptcData& iptcData) override;
+
+ /// @throws Error(ErrorCode::kerInvalidSettingForImage)
+ void setComment(const std::string&) override;
+ //@}
+
+ //! @name Accessors
+ //@{
+ [[nodiscard]] std::string mimeType() const override;
+ //@}
+}; // class JxlImage
+
+// *****************************************************************************
+// template, inline and free functions
+
+// These could be static private functions on Image subclasses but then
+// ImageFactory needs to be made a friend.
+/*!
+ @brief Create a new JxlImage instance and return an auto-pointer to it.
+ Caller owns the returned object and the auto-pointer ensures that
+ it will be deleted.
+ */
+EXIV2API Image::UniquePtr newJxlInstance(BasicIo::UniquePtr io, bool create);
+
+//! Check if the file iIo is a JPEG XL bare codestream.
+EXIV2API bool isJxlType(BasicIo& iIo, bool advance);
+
+} // namespace Exiv2
+
+#endif // #ifndef JXLIMAGE_HPP_
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 41a672e89e..1dccdd7c1a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -18,6 +18,7 @@ add_library( exiv2lib_int OBJECT
helper_functions.cpp helper_functions.hpp
image_int.cpp image_int.hpp
jp2image_int.cpp jp2image_int.hpp
+ jxlimage_int.cpp jxlimage_int.hpp
makernote_int.cpp makernote_int.hpp
minoltamn_int.cpp minoltamn_int.hpp
nikonmn_int.cpp nikonmn_int.hpp
@@ -60,6 +61,7 @@ set(PUBLIC_HEADERS
../include/exiv2/iptc.hpp
../include/exiv2/jp2image.hpp
../include/exiv2/jpgimage.hpp
+ ../include/exiv2/jxlimage.hpp
../include/exiv2/metadatum.hpp
../include/exiv2/mrwimage.hpp
../include/exiv2/orfimage.hpp
@@ -103,6 +105,7 @@ add_library( exiv2lib
iptc.cpp
jp2image.cpp
jpgimage.cpp
+ jxlimage.cpp
metadatum.cpp
mrwimage.cpp
orfimage.cpp
diff --git a/src/image.cpp b/src/image.cpp
index 05d8345f9d..9b1d2a053d 100644
--- a/src/image.cpp
+++ b/src/image.cpp
@@ -26,6 +26,7 @@
#include "bmpimage.hpp"
#include "gifimage.hpp"
#include "jp2image.hpp"
+#include "jxlimage.hpp"
#include "nikonmn_int.hpp"
#include "orfimage.hpp"
#include "pgfimage.hpp"
@@ -103,6 +104,7 @@ constexpr Registry registry[] = {
{ImageType::tga, newTgaInstance, isTgaType, amNone, amNone, amNone, amNone},
{ImageType::bmp, newBmpInstance, isBmpType, amNone, amNone, amNone, amNone},
{ImageType::jp2, newJp2Instance, isJp2Type, amReadWrite, amReadWrite, amReadWrite, amNone},
+ {ImageType::jxl, newJxlInstance, isJxlType, amNone, amNone, amNone, amNone},
// needs to be before bmff because some ftyp files are handled as qt and
// the rest should fall through to bmff
#ifdef EXV_ENABLE_VIDEO
diff --git a/src/jxlimage.cpp b/src/jxlimage.cpp
new file mode 100644
index 0000000000..484a64cb61
--- /dev/null
+++ b/src/jxlimage.cpp
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ File: jxlimage.cpp
+ Author(s): antermin
+ History: 18-Mar-2023, antermin: created
+ */
+
+// included header files
+#include "jxlimage.hpp"
+#include "jxlimage_int.hpp"
+
+#include "config.h"
+
+#include "basicio.hpp"
+#include "error.hpp"
+#include "futils.hpp"
+#include "helper_functions.hpp"
+#include "image.hpp"
+
+// + standard includes
+#include <cstring>
+#include <iostream>
+#include <string>
+
+// *****************************************************************************
+// class member definitions
+namespace Exiv2 {
+JxlImage::JxlImage(BasicIo::UniquePtr io) : Image(ImageType::jxl, mdNone, std::move(io)) {
+}
+
+std::string JxlImage::mimeType() const {
+ return "image/jxl";
+}
+
+void JxlImage::setExifData(const ExifData& /*exifData*/) {
+ throw(Error(ErrorCode::kerInvalidSettingForImage, "Exif metadata", "JXL"));
+}
+
+void JxlImage::setIptcData(const IptcData& /*iptcData*/) {
+ throw(Error(ErrorCode::kerInvalidSettingForImage, "IPTC metadata", "JXL"));
+}
+
+void JxlImage::setComment(const std::string&) {
+ throw(Error(ErrorCode::kerInvalidSettingForImage, "Image comment", "JXL"));
+}
+
+void JxlImage::readMetadata() {
+#ifdef EXIV2_DEBUG_MESSAGES
+ std::cerr << "Exiv2::JxlImage::readMetadata: Reading JXL bare codestream " << io_->path() << "\n";
+#endif
+ if (io_->open() != 0) {
+ throw Error(ErrorCode::kerDataSourceOpenFailed, io_->path(), strError());
+ }
+ IoCloser closer(*io_);
+
+ // Ensure that this is the correct image type
+ if (!isJxlType(*io_, false)) {
+ if (io_->error() || io_->eof())
+ throw Error(ErrorCode::kerFailedToReadImageData);
+ throw Error(ErrorCode::kerNotAnImage, "JXL");
+ }
+ clearMetadata();
+
+ DataBuf data(11); // Takes up to 11 bytes to parse width and height
+ if (io_->read(data.data(), data.size())) {
+ Internal::JxlStream jxlstream;
+ jxlstream.databits = getUint64_t(data);
+ Internal::parseJxlDimensions(&jxlstream, false); // false: !nosig
+ pixelHeight_ = jxlstream.height;
+ pixelWidth_ = jxlstream.width;
+ }
+}
+
+void JxlImage::writeMetadata() {
+ /// \todo implement me!
+ throw(Error(ErrorCode::kerWritingImageFormatUnsupported, "JXL"));
+}
+
+// *************************************************************************
+// free functions
+Image::UniquePtr newJxlInstance(BasicIo::UniquePtr io, bool /*create*/) {
+ auto image = std::make_unique<JxlImage>(std::move(io));
+ if (!image->good()) {
+ return nullptr;
+ }
+ return image;
+}
+
+bool isJxlType(BasicIo& iIo, bool advance) {
+ const int32_t len = 2;
+ const unsigned char JxlImageId[2] = { 0xFF, 0x0A };
+ byte buf[len];
+ iIo.read(buf, len);
+ if (iIo.error() || iIo.eof()) {
+ return false;
+ }
+ bool matched = (memcmp(buf, JxlImageId, len) == 0);
+ if (!advance || !matched) {
+ iIo.seek(-len, BasicIo::cur);
+ }
+ return matched;
+}
+} // namespace Exiv2
diff --git a/src/jxlimage_int.cpp b/src/jxlimage_int.cpp
new file mode 100644
index 0000000000..260d2b0277
--- /dev/null
+++ b/src/jxlimage_int.cpp
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "jxlimage_int.hpp"
+
+#include "error.hpp"
+#include "types.hpp"
+
+#include <cassert>
+
+namespace Exiv2::Internal {
+
+uint64_t JxlStream::getBits(int length) {
+ uint64_t bitmask = (1 << length) -1;
+ uint64_t value = (databits >> position) & bitmask;
+ position += length; //advance position after getting bits
+ return value;
+}
+
+uint64_t JxlStream::readU32(int c0, int u0, int c1, int u1, int c2, int u2, int c3, int u3) {
+ int dist = getBits(2);
+ int c[] = {c0, c1, c2, c3};
+ int u[] = {u0, u1, u2, u3};
+ return c[dist] + getBits(u[dist]);
+}
+
+void parseJxlDimensions(JxlStream *stream, bool nosig) {
+ // if stream has signature, we need to skip it
+ nosig ? stream->position = 0 : stream->position = 16;
+
+ int div8 = stream->getBits(1);
+ if (div8) {
+ stream->height = (1 + stream->getBits(5)) << 3; // multiply 8
+ } else {
+ stream->height = stream->readU32(1, 9, 1, 13, 1, 18, 1, 30);
+ }
+ int ratio = stream->getBits(3);
+ if ((div8) && (!ratio)) {
+ stream->width = (1 + stream->getBits(5)) << 3; // multiply 8
+ } else if (!ratio) {
+ stream->width = stream->readU32(1, 9, 1, 13, 1, 18, 1, 30);
+ } else {
+ switch (ratio) {
+ case 1:
+ stream->width = stream->height;
+ break;
+ case 2:
+ stream->width = (stream->height * 12) / 10;
+ break;
+ case 3:
+ stream->width = (stream->height * 4) / 3;
+ break;
+ case 4:
+ stream->width = (stream->height * 3) / 2;
+ break;
+ case 5:
+ stream->width = (stream->height * 16) / 9;
+ break;
+ case 6:
+ stream->width = (stream->height * 5) / 4;
+ break;
+ case 7:
+ stream->width = (stream->height * 2);
+ break;
+ }
+ }
+}
+} // namespace Exiv2::Internal
diff --git a/src/jxlimage_int.hpp b/src/jxlimage_int.hpp
new file mode 100644
index 0000000000..8c7f55413b
--- /dev/null
+++ b/src/jxlimage_int.hpp
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#ifndef JXLIMAGE_INT_HPP
+#define JXLIMAGE_INT_HPP
+
+#include <stdint.h>
+#include <vector>
+
+namespace Exiv2::Internal {
+
+class JxlStream {
+ public:
+ uint64_t databits;
+ int position;
+ uint64_t width;
+ uint64_t height;
+ uint64_t getBits(int);
+ uint64_t readU32(int, int, int, int, int, int, int, int);
+}; // class JxlStream
+
+void parseJxlDimensions(JxlStream *stream, bool nosig);
+
+} // namespace Exiv2::Internal
+
+#endif // JXLIMAGE_INT_HPP
From 823918e9e6ca9cc29b5917607fb56a3346ba6f7b Mon Sep 17 00:00:00 2001
From: antermin <103918092+antermin@users.noreply.github.com>
Date: Thu, 8 Jun 2023 20:18:40 +0900
Subject: [PATCH 3/3] Experimental jxlp and jxlc support
---
include/exiv2/bmffimage.hpp | 1 +
src/bmffimage.cpp | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 35 insertions(+)
diff --git a/include/exiv2/bmffimage.hpp b/include/exiv2/bmffimage.hpp
index b634953925..4a407152c0 100644
--- a/include/exiv2/bmffimage.hpp
+++ b/include/exiv2/bmffimage.hpp
@@ -148,6 +148,7 @@ class EXIV2API BmffImage : public Image {
static bool superBox(uint32_t box);
static bool fullBox(uint32_t box);
static std::string uuidName(const Exiv2::DataBuf& uuid);
+ bool hasJxlHeader(const Exiv2::DataBuf& jxlpdata);
/*!
@brief Wrapper around brotli to uncompress JXL brob content.
diff --git a/src/bmffimage.cpp b/src/bmffimage.cpp
index 3698d57e09..677b584e79 100644
--- a/src/bmffimage.cpp
+++ b/src/bmffimage.cpp
@@ -11,10 +11,12 @@
#include "image.hpp"
#include "image_int.hpp"
#include "safe_op.hpp"
+#include "jxlimage_int.hpp"
#include "tiffimage.hpp"
#include "tiffimage_int.hpp"
#include "types.hpp"
#include "utils.hpp"
+#include "helper_functions.hpp"
#ifdef EXV_HAVE_BROTLI
#include <brotli/decode.h> // for JXL brob
@@ -40,6 +42,8 @@ enum {
TAG_mif1 = 0x6d696631U, ///< "mif1" HEIF */
TAG_crx = 0x63727820U, ///< "crx " Canon CR3 */
TAG_jxl = 0x6a786c20U, ///< "jxl " JPEG XL file type */
+ TAG_jxlc = 0x6a786c63U, ///< "jxlc" JPEG XL codestream */
+ TAG_jxlp = 0x6a786c70U, ///< "jxlp" JPEG XL partial codestream */
TAG_moov = 0x6d6f6f76U, ///< "moov" Movie */
TAG_meta = 0x6d657461U, ///< "meta" Metadata */
TAG_mdat = 0x6d646174U, ///< "mdat" Media data */
@@ -163,6 +167,11 @@ std::string BmffImage::uuidName(const Exiv2::DataBuf& uuid) {
return "";
}
+bool BmffImage::hasJxlHeader(const Exiv2::DataBuf& jxlpdata) {
+ const char* JxlHeader = "\x00\x00\x00\x00\xFF\x0A";
+ return (jxlpdata.cmpBytes(0, JxlHeader, 6) == 0 ? true : false);
+}
+
#ifdef EXV_HAVE_BROTLI
// Wrapper class for BrotliDecoderState that automatically calls
@@ -570,6 +579,31 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
break;
}
break;
+ case TAG_jxlp: {
+ DataBuf sig(6); // 4 bytes padding + 2 bytes sig
+ io_->read(sig.data(), sig.size());
+ if (hasJxlHeader(sig)) {
+#ifdef EXIV2_DEBUG_MESSAGES
+ std::cerr << "Exiv2::BmffImage::boxHandler: JXL Header found in this jxlp box" << "\n";
+#endif
+ DataBuf streamdata(9); // Max 11 bytes - 2 bytes sig
+ io_->read(streamdata.data(), streamdata.size());
+ Internal::JxlStream jxlstream;
+ jxlstream.databits = getUint64_t(streamdata);
+ Internal::parseJxlDimensions(&jxlstream, true); // true: nosig
+ pixelHeight_ = jxlstream.height;
+ pixelWidth_ = jxlstream.width;
+ }
+ } break;
+ case TAG_jxlc: {
+ DataBuf streamdata(11);
+ io_->read(streamdata.data(), streamdata.size());
+ Internal::JxlStream jxlstream;
+ jxlstream.databits = getUint64_t(streamdata);
+ Internal::parseJxlDimensions(&jxlstream, false); // false: !nosig
+ pixelHeight_ = jxlstream.height;
+ pixelWidth_ = jxlstream.width;
+ } break;
default:
break; /* do nothing */