Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions lib/include/ultrahdr/avifultrahdr.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ class AvifUltraHdr : public UltraHdr {
*/
uhdr_error_info_t encodeAvifUltraHdr(uhdr_raw_image_t* hdr_intent, uhdr_compressed_image_t* dest,
int quality, uhdr_mem_block_t* exif);
// The owned-output variant resets dest on entry and leaves it empty on failure.
uhdr_error_info_t encodeAvifUltraHdrToOwnedBuffer(uhdr_raw_image_t* hdr_intent,
uhdr_owned_buffer_t* dest, int quality,
uhdr_mem_block_t* exif);

/*!\brief Encode API-1.
*
Expand All @@ -93,6 +97,11 @@ class AvifUltraHdr : public UltraHdr {
*/
uhdr_error_info_t encodeAvifUltraHdr(uhdr_raw_image_t* hdr_intent, uhdr_raw_image_t* sdr_intent,
uhdr_compressed_image_t* dest, int quality, uhdr_mem_block_t* exif);
// The owned-output variant resets dest on entry and leaves it empty on failure.
uhdr_error_info_t encodeAvifUltraHdrToOwnedBuffer(uhdr_raw_image_t* hdr_intent,
uhdr_raw_image_t* sdr_intent,
uhdr_owned_buffer_t* dest, int quality,
uhdr_mem_block_t* exif);

/*!\brief Decode API.
*
Expand Down Expand Up @@ -153,7 +162,7 @@ class AvifUltraHdr : public UltraHdr {
* 8-bit alpha in the base image
* \param[in] gainmap_img gainmap raw image descriptor
* \param[in] metadata gainmap metadata descriptor
* \param[in, out] dest output image descriptor to store compressed ultrahdr image
* \param[in, out] dest owned output buffer for compressed ultrahdr image
* \param[in] quality quality factor for sdr intent heif/avif compression
* \param[in] exif optional exif metadata that needs to be inserted in
* compressed output
Expand All @@ -166,7 +175,7 @@ class AvifUltraHdr : public UltraHdr {
uhdr_raw_image_t* base_alpha_source,
uhdr_raw_image_t* gainmap_img,
uhdr_gainmap_metadata_ext_t* metadata,
uhdr_compressed_image_t* dest, int quality,
uhdr_owned_buffer_t* dest, int quality,
uhdr_mem_block_t* exif, DataStruct* baseIcc,
DataStruct* alternateIcc);

Expand Down
13 changes: 11 additions & 2 deletions lib/include/ultrahdr/heifultrahdr.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ class HeifUltraHdr : public UltraHdr {
*/
uhdr_error_info_t encodeHeicUltraHdr(uhdr_raw_image_t* hdr_intent, uhdr_compressed_image_t* dest,
int quality, uhdr_mem_block_t* exif);
// The owned-output variant resets dest on entry and leaves it empty on failure.
uhdr_error_info_t encodeHeicUltraHdrToOwnedBuffer(uhdr_raw_image_t* hdr_intent,
uhdr_owned_buffer_t* dest, int quality,
uhdr_mem_block_t* exif);

/*!\brief Encode API-1.
*
Expand All @@ -93,6 +97,11 @@ class HeifUltraHdr : public UltraHdr {
*/
uhdr_error_info_t encodeHeicUltraHdr(uhdr_raw_image_t* hdr_intent, uhdr_raw_image_t* sdr_intent,
uhdr_compressed_image_t* dest, int quality, uhdr_mem_block_t* exif);
// The owned-output variant resets dest on entry and leaves it empty on failure.
uhdr_error_info_t encodeHeicUltraHdrToOwnedBuffer(uhdr_raw_image_t* hdr_intent,
uhdr_raw_image_t* sdr_intent,
uhdr_owned_buffer_t* dest, int quality,
uhdr_mem_block_t* exif);

/*!\brief Decode API.
*
Expand Down Expand Up @@ -153,7 +162,7 @@ class HeifUltraHdr : public UltraHdr {
* 8-bit alpha in the base image
* \param[in] gainmap_img gainmap raw image descriptor
* \param[in] metadata gainmap metadata descriptor
* \param[in, out] dest output image descriptor to store compressed ultrahdr image
* \param[in, out] dest owned output buffer for compressed ultrahdr image
* \param[in] quality quality factor for sdr intent heif/avif compression
* \param[in] exif optional exif metadata that needs to be inserted in
* compressed output
Expand All @@ -166,7 +175,7 @@ class HeifUltraHdr : public UltraHdr {
uhdr_raw_image_t* base_alpha_source,
uhdr_raw_image_t* gainmap_img,
uhdr_gainmap_metadata_ext_t* metadata,
uhdr_compressed_image_t* dest, int quality,
uhdr_owned_buffer_t* dest, int quality,
uhdr_mem_block_t* exif, DataStruct* baseIcc,
DataStruct* alternateIcc);

Expand Down
27 changes: 27 additions & 0 deletions lib/include/ultrahdr/ultrahdrcommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,30 @@ typedef struct uhdr_memory_block {
size_t m_capacity; /**< capacity */
} uhdr_memory_block_t; /**< alias for struct uhdr_memory_block */

/**\brief move-only buffer for transferring malloc-owned encoded output */
typedef struct uhdr_owned_buffer {
uhdr_owned_buffer() noexcept;
~uhdr_owned_buffer();

uhdr_owned_buffer(const uhdr_owned_buffer&) = delete;
uhdr_owned_buffer& operator=(const uhdr_owned_buffer&) = delete;
uhdr_owned_buffer(uhdr_owned_buffer&& other) noexcept;
uhdr_owned_buffer& operator=(uhdr_owned_buffer&& other) noexcept;

/** Releases prior ownership and adopts malloc/free-compatible storage. */
void reset(uint8_t* data = nullptr, size_t size = 0) noexcept;
uint8_t* data() const noexcept { return m_data; }
size_t size() const noexcept { return m_size; }

private:
uint8_t* m_data;
size_t m_size;
} uhdr_owned_buffer_t; /**< alias for struct uhdr_owned_buffer */

uhdr_error_info_t invalidOutputDestination();
uhdr_error_info_t copyOwnedBufferToCompressedImage(const uhdr_owned_buffer_t& source,
uhdr_compressed_image_t* dest);

/**\brief extended raw image descriptor */
typedef struct uhdr_raw_image_ext : uhdr_raw_image_t {
uhdr_raw_image_ext(uhdr_img_fmt_t fmt, uhdr_color_gamut_t cg, uhdr_color_transfer_t ct,
Expand All @@ -189,9 +213,12 @@ typedef struct uhdr_raw_image_ext : uhdr_raw_image_t {
typedef struct uhdr_compressed_image_ext : uhdr_compressed_image_t {
uhdr_compressed_image_ext(uhdr_color_gamut_t cg, uhdr_color_transfer_t ct,
uhdr_color_range_t range, size_t sz);
uhdr_compressed_image_ext(uhdr_color_gamut_t cg, uhdr_color_transfer_t ct,
uhdr_color_range_t range, uhdr_owned_buffer_t&& buffer);

private:
std::unique_ptr<ultrahdr::uhdr_memory_block> m_block;
uhdr_owned_buffer_t m_owned_buffer;
} uhdr_compressed_image_ext_t; /**< alias for struct uhdr_compressed_image_ext */

/*!\brief forward declaration for image effect descriptor */
Expand Down
74 changes: 61 additions & 13 deletions lib/src/avifultrahdr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,15 @@ class MemoryWriter {

~MemoryWriter() { free(data_); }

const uint8_t* data() const { return data_; }
MemoryWriter(const MemoryWriter&) = delete;
MemoryWriter& operator=(const MemoryWriter&) = delete;

size_t size() const { return size_; }
void release(uhdr_owned_buffer_t* output) {
output->reset(data_, size_);
data_ = nullptr;
size_ = 0;
capacity_ = 0;
}

struct heif_error write(const void* data, size_t size) {
if (size == 0) return {heif_error_Ok, heif_suberror_Unspecified, nullptr};
Expand Down Expand Up @@ -343,6 +349,30 @@ AvifUltraHdr::AvifUltraHdr(void* uhdrGLESCtxt, int mapDimensionScaleFactor, int
/* Encode API-0 */
uhdr_error_info_t AvifUltraHdr::encodeAvifUltraHdr(uhdr_raw_image_t* hdr_intent, uhdr_compressed_image_t* dest,
int quality, uhdr_mem_block_t* exif) {
uhdr_owned_buffer_t output;
if (dest == nullptr || dest->data == nullptr) {
return invalidOutputDestination();
}
uhdr_error_info_t status = encodeAvifUltraHdrToOwnedBuffer(hdr_intent, &output, quality, exif);
if (status.error_code != UHDR_CODEC_OK) return status;
return copyOwnedBufferToCompressedImage(output, dest);
}

uhdr_error_info_t AvifUltraHdr::encodeAvifUltraHdrToOwnedBuffer(uhdr_raw_image_t* hdr_intent,
uhdr_owned_buffer_t* dest,
int quality,
uhdr_mem_block_t* exif) {
if (dest == nullptr) {
return invalidOutputDestination();
}
dest->reset();
if (hdr_intent == nullptr) {
uhdr_error_info_t status = g_no_error;
status.error_code = UHDR_CODEC_INVALID_PARAM;
status.has_detail = 1;
snprintf(status.detail, sizeof status.detail, "hdr intent is null");
return status;
}
uhdr_img_fmt_t sdr_intent_fmt;
if (hdr_intent->fmt == UHDR_IMG_FMT_24bppYCbCrP010) {
sdr_intent_fmt = UHDR_IMG_FMT_12bppYCbCr420;
Expand Down Expand Up @@ -401,6 +431,30 @@ uhdr_error_info_t AvifUltraHdr::encodeAvifUltraHdr(uhdr_raw_image_t* hdr_intent,
uhdr_error_info_t AvifUltraHdr::encodeAvifUltraHdr(uhdr_raw_image_t* hdr_intent, uhdr_raw_image_t* sdr_intent,
uhdr_compressed_image_t* dest, int quality,
uhdr_mem_block_t* exif) {
uhdr_owned_buffer_t output;
if (dest == nullptr || dest->data == nullptr) {
return invalidOutputDestination();
}
uhdr_error_info_t status =
encodeAvifUltraHdrToOwnedBuffer(hdr_intent, sdr_intent, &output, quality, exif);
if (status.error_code != UHDR_CODEC_OK) return status;
return copyOwnedBufferToCompressedImage(output, dest);
}

uhdr_error_info_t AvifUltraHdr::encodeAvifUltraHdrToOwnedBuffer(
uhdr_raw_image_t* hdr_intent, uhdr_raw_image_t* sdr_intent, uhdr_owned_buffer_t* dest,
int quality, uhdr_mem_block_t* exif) {
if (dest == nullptr) {
return invalidOutputDestination();
}
dest->reset();
if (hdr_intent == nullptr || sdr_intent == nullptr) {
uhdr_error_info_t status = g_no_error;
status.error_code = UHDR_CODEC_INVALID_PARAM;
status.has_detail = 1;
snprintf(status.detail, sizeof status.detail, "hdr or sdr intent is null");
return status;
}
// generate gain map
uhdr_gainmap_metadata_ext_t metadata(kJpegrVersion);
std::unique_ptr<uhdr_raw_image_ext_t> gainmap;
Expand Down Expand Up @@ -430,10 +484,13 @@ uhdr_error_info_t AvifUltraHdr::encodeAvifUltraHdr(uhdr_raw_image_t* sdr_intent,
uhdr_raw_image_t* base_alpha_source,
uhdr_raw_image_t* gainmap_img,
uhdr_gainmap_metadata_ext_t* metadata,
uhdr_compressed_image_t* dest, int quality,
uhdr_owned_buffer_t* dest, int quality,
uhdr_mem_block_t* exif, DataStruct* baseIcc,
DataStruct* alternateIcc) {
uhdr_error_info_t status = g_no_error;
if (dest == nullptr) {
return invalidOutputDestination();
}
heif_encoder* encoder = nullptr;
heif_encoding_options* options = nullptr;
heif_color_profile_nclx* sdrNclx = nullptr;
Expand Down Expand Up @@ -607,16 +664,7 @@ uhdr_error_info_t AvifUltraHdr::encodeAvifUltraHdr(uhdr_raw_image_t* sdr_intent,
snprintf(status.detail, sizeof status.detail, "%s", write_err.message);
goto CleanUp;
}
if (writer.size() > dest->capacity) {
status.error_code = UHDR_CODEC_MEM_ERROR;
status.has_detail = 1;
snprintf(status.detail, sizeof status.detail,
"destination buffer is too small, capacity is %zu, required size is %zu",
dest->capacity, writer.size());
goto CleanUp;
}
memcpy(dest->data, writer.data(), writer.size());
dest->data_sz = writer.size();
writer.release(dest);

CleanUp:
if (baseImage) heif_image_release(baseImage);
Expand Down
74 changes: 61 additions & 13 deletions lib/src/heifultrahdr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,15 @@ class MemoryWriter {

~MemoryWriter() { free(data_); }

const uint8_t* data() const { return data_; }
MemoryWriter(const MemoryWriter&) = delete;
MemoryWriter& operator=(const MemoryWriter&) = delete;

size_t size() const { return size_; }
void release(uhdr_owned_buffer_t* output) {
output->reset(data_, size_);
data_ = nullptr;
size_ = 0;
capacity_ = 0;
}

struct heif_error write(const void* data, size_t size) {
if (size == 0) return {heif_error_Ok, heif_suberror_Unspecified, nullptr};
Expand Down Expand Up @@ -343,6 +349,30 @@ HeifUltraHdr::HeifUltraHdr(void* uhdrGLESCtxt, int mapDimensionScaleFactor, int
/* Encode API-0 */
uhdr_error_info_t HeifUltraHdr::encodeHeicUltraHdr(uhdr_raw_image_t* hdr_intent, uhdr_compressed_image_t* dest,
int quality, uhdr_mem_block_t* exif) {
uhdr_owned_buffer_t output;
if (dest == nullptr || dest->data == nullptr) {
return invalidOutputDestination();
}
uhdr_error_info_t status = encodeHeicUltraHdrToOwnedBuffer(hdr_intent, &output, quality, exif);
if (status.error_code != UHDR_CODEC_OK) return status;
return copyOwnedBufferToCompressedImage(output, dest);
}

uhdr_error_info_t HeifUltraHdr::encodeHeicUltraHdrToOwnedBuffer(uhdr_raw_image_t* hdr_intent,
uhdr_owned_buffer_t* dest,
int quality,
uhdr_mem_block_t* exif) {
if (dest == nullptr) {
return invalidOutputDestination();
}
dest->reset();
if (hdr_intent == nullptr) {
uhdr_error_info_t status = g_no_error;
status.error_code = UHDR_CODEC_INVALID_PARAM;
status.has_detail = 1;
snprintf(status.detail, sizeof status.detail, "hdr intent is null");
return status;
}
uhdr_img_fmt_t sdr_intent_fmt;
if (hdr_intent->fmt == UHDR_IMG_FMT_24bppYCbCrP010) {
sdr_intent_fmt = UHDR_IMG_FMT_12bppYCbCr420;
Expand Down Expand Up @@ -401,6 +431,30 @@ uhdr_error_info_t HeifUltraHdr::encodeHeicUltraHdr(uhdr_raw_image_t* hdr_intent,
uhdr_error_info_t HeifUltraHdr::encodeHeicUltraHdr(uhdr_raw_image_t* hdr_intent, uhdr_raw_image_t* sdr_intent,
uhdr_compressed_image_t* dest, int quality,
uhdr_mem_block_t* exif) {
uhdr_owned_buffer_t output;
if (dest == nullptr || dest->data == nullptr) {
return invalidOutputDestination();
}
uhdr_error_info_t status =
encodeHeicUltraHdrToOwnedBuffer(hdr_intent, sdr_intent, &output, quality, exif);
if (status.error_code != UHDR_CODEC_OK) return status;
return copyOwnedBufferToCompressedImage(output, dest);
}

uhdr_error_info_t HeifUltraHdr::encodeHeicUltraHdrToOwnedBuffer(
uhdr_raw_image_t* hdr_intent, uhdr_raw_image_t* sdr_intent, uhdr_owned_buffer_t* dest,
int quality, uhdr_mem_block_t* exif) {
if (dest == nullptr) {
return invalidOutputDestination();
}
dest->reset();
if (hdr_intent == nullptr || sdr_intent == nullptr) {
uhdr_error_info_t status = g_no_error;
status.error_code = UHDR_CODEC_INVALID_PARAM;
status.has_detail = 1;
snprintf(status.detail, sizeof status.detail, "hdr or sdr intent is null");
return status;
}
// generate gain map
uhdr_gainmap_metadata_ext_t metadata(kJpegrVersion);
std::unique_ptr<uhdr_raw_image_ext_t> gainmap;
Expand Down Expand Up @@ -430,10 +484,13 @@ uhdr_error_info_t HeifUltraHdr::encodeHeicUltraHdr(uhdr_raw_image_t* sdr_intent,
uhdr_raw_image_t* base_alpha_source,
uhdr_raw_image_t* gainmap_img,
uhdr_gainmap_metadata_ext_t* metadata,
uhdr_compressed_image_t* dest, int quality,
uhdr_owned_buffer_t* dest, int quality,
uhdr_mem_block_t* exif, DataStruct* baseIcc,
DataStruct* alternateIcc) {
uhdr_error_info_t status = g_no_error;
if (dest == nullptr) {
return invalidOutputDestination();
}
heif_encoder* encoder = nullptr;
heif_encoding_options* options = nullptr;
heif_color_profile_nclx* sdrNclx = nullptr;
Expand Down Expand Up @@ -607,16 +664,7 @@ uhdr_error_info_t HeifUltraHdr::encodeHeicUltraHdr(uhdr_raw_image_t* sdr_intent,
snprintf(status.detail, sizeof status.detail, "%s", write_err.message);
goto CleanUp;
}
if (writer.size() > dest->capacity) {
status.error_code = UHDR_CODEC_MEM_ERROR;
status.has_detail = 1;
snprintf(status.detail, sizeof status.detail,
"destination buffer is too small, capacity is %zu, required size is %zu",
dest->capacity, writer.size());
goto CleanUp;
}
memcpy(dest->data, writer.data(), writer.size());
dest->data_sz = writer.size();
writer.release(dest);

CleanUp:
if (baseImage) heif_image_release(baseImage);
Expand Down
Loading
Loading