Skip to content
Merged
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
38 changes: 19 additions & 19 deletions lib/include/ultrahdr/gainmapmetadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,25 @@ constexpr uint8_t kUseBaseColorSpaceMask = (1u << 6);
// Gain map metadata, for tone mapping between SDR and HDR.
// This is the fraction version of {@code uhdr_gainmap_metadata_ext_t}.
struct uhdr_gainmap_metadata_frac {
int32_t gainMapMinN[3];
uint32_t gainMapMinD[3];
int32_t gainMapMaxN[3];
uint32_t gainMapMaxD[3];
uint32_t gainMapGammaN[3];
uint32_t gainMapGammaD[3];

int32_t baseOffsetN[3];
uint32_t baseOffsetD[3];
int32_t alternateOffsetN[3];
uint32_t alternateOffsetD[3];

uint32_t baseHdrHeadroomN;
uint32_t baseHdrHeadroomD;
uint32_t alternateHdrHeadroomN;
uint32_t alternateHdrHeadroomD;

bool backwardDirection;
bool useBaseColorSpace;
int32_t gainMapMinN[3] = {0, 0, 0};
uint32_t gainMapMinD[3] = {1, 1, 1};
int32_t gainMapMaxN[3] = {1, 1, 1};
uint32_t gainMapMaxD[3] = {1, 1, 1};
uint32_t gainMapGammaN[3] = {1, 1, 1};
uint32_t gainMapGammaD[3] = {1, 1, 1};

int32_t baseOffsetN[3] = {0, 0, 0};
uint32_t baseOffsetD[3] = {1, 1, 1};
int32_t alternateOffsetN[3] = {0, 0, 0};
uint32_t alternateOffsetD[3] = {1, 1, 1};

uint32_t baseHdrHeadroomN = 0;
uint32_t baseHdrHeadroomD = 1;
uint32_t alternateHdrHeadroomN = 1;
uint32_t alternateHdrHeadroomD = 1;

bool backwardDirection = false;
bool useBaseColorSpace = true;

static uhdr_error_info_t encodeGainmapMetadata(const uhdr_gainmap_metadata_frac* in_metadata,
std::vector<uint8_t>& out_data);
Expand Down
3 changes: 2 additions & 1 deletion lib/src/gainmapmetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include "ultrahdr/gainmapmath.h"
#include "ultrahdr/gainmapmetadata.h"
#include "ultrahdr/ultrahdrcommon.h"

namespace ultrahdr {

Expand Down Expand Up @@ -342,7 +343,7 @@ uhdr_error_info_t uhdr_gainmap_metadata_frac::gainmapMetadataFractionToFloat(
to->hdr_capacity_min = exp2((float)from->baseHdrHeadroomN / from->baseHdrHeadroomD);
to->use_base_cg = from->useBaseColorSpace;

return g_no_error;
return uhdr_validate_gainmap_metadata_descriptor(to);
}

uhdr_error_info_t uhdr_gainmap_metadata_frac::gainmapMetadataFloatToFraction(
Expand Down
2 changes: 1 addition & 1 deletion lib/src/jpegrutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -870,7 +870,7 @@ uhdr_error_info_t getMetadataFromXMP(uint8_t* xmp_data, size_t xmp_size, uint8_t
std::fill_n(metadata->offset_hdr + 1, 2, metadata->offset_hdr[0]);
std::fill_n(metadata->offset_sdr + 1, 2, metadata->offset_sdr[0]);

return g_no_error;
return uhdr_validate_gainmap_metadata_descriptor(metadata);
}

string generateXmpForPrimaryImage(size_t secondary_image_length,
Expand Down
23 changes: 12 additions & 11 deletions lib/src/ultrahdr_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1721,17 +1721,18 @@ uhdr_error_info_t uhdr_dec_probe(uhdr_codec_private_t* dec) {
ultrahdr::uhdr_gainmap_metadata_frac frac;
if (ultrahdr::uhdr_gainmap_metadata_frac::decodeGainmapMetadata(meta, &frac).error_code == UHDR_CODEC_OK) {
ultrahdr::uhdr_gainmap_metadata_ext_t metadata;
ultrahdr::uhdr_gainmap_metadata_frac::gainmapMetadataFractionToFloat(&frac, &metadata);
std::copy(metadata.max_content_boost, metadata.max_content_boost + 3,
handle->m_metadata.max_content_boost);
std::copy(metadata.min_content_boost, metadata.min_content_boost + 3,
handle->m_metadata.min_content_boost);
std::copy(metadata.gamma, metadata.gamma + 3, handle->m_metadata.gamma);
std::copy(metadata.offset_sdr, metadata.offset_sdr + 3, handle->m_metadata.offset_sdr);
std::copy(metadata.offset_hdr, metadata.offset_hdr + 3, handle->m_metadata.offset_hdr);
handle->m_metadata.hdr_capacity_min = metadata.hdr_capacity_min;
handle->m_metadata.hdr_capacity_max = metadata.hdr_capacity_max;
handle->m_metadata.use_base_cg = metadata.use_base_cg;
if (ultrahdr::uhdr_gainmap_metadata_frac::gainmapMetadataFractionToFloat(&frac, &metadata).error_code == UHDR_CODEC_OK) {
std::copy(metadata.max_content_boost, metadata.max_content_boost + 3,
handle->m_metadata.max_content_boost);
std::copy(metadata.min_content_boost, metadata.min_content_boost + 3,
handle->m_metadata.min_content_boost);
std::copy(metadata.gamma, metadata.gamma + 3, handle->m_metadata.gamma);
std::copy(metadata.offset_sdr, metadata.offset_sdr + 3, handle->m_metadata.offset_sdr);
std::copy(metadata.offset_hdr, metadata.offset_hdr + 3, handle->m_metadata.offset_hdr);
handle->m_metadata.hdr_capacity_min = metadata.hdr_capacity_min;
handle->m_metadata.hdr_capacity_max = metadata.hdr_capacity_max;
handle->m_metadata.use_base_cg = metadata.use_base_cg;
}
}
}
heif_image_handle_release(gainmap_handle);
Expand Down
39 changes: 37 additions & 2 deletions tests/gainmapmetadata_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ TEST_F(GainMapMetadataTest, encodeMetadataThenDecode) {
data.clear();
for (int i = 0; i < 3; i++) {
expected.min_content_boost[i] = 0.000578369f + i * 0.001f;
expected.offset_sdr[i] = -0.0625f + i * 0.001f;
expected.offset_hdr[i] = -0.0625f + i * 0.001f;
expected.offset_sdr[i] = 0.0625f + i * 0.001f;
expected.offset_hdr[i] = 0.0625f + i * 0.001f;
}
expected.hdr_capacity_max = 1000.0f / 203.0f;
expected.use_base_cg = true;
Expand Down Expand Up @@ -112,4 +112,39 @@ TEST_F(GainMapMetadataTest, encodeMetadataThenDecode) {
EXPECT_EQ(expected.use_base_cg, decodedUHdrMetadata.use_base_cg);
}

TEST(GainmapMetadataTest, RejectsMalformedISO21496_1Ratios) {
uhdr_gainmap_metadata_frac frac{};
for (int i = 0; i < 3; ++i) {
frac.gainMapMaxN[i] = 1;
frac.gainMapMaxD[i] = 1;
frac.gainMapMinN[i] = 0;
frac.gainMapMinD[i] = 1;
frac.gainMapGammaN[i] = 1;
frac.gainMapGammaD[i] = 1;
frac.baseOffsetN[i] = 0;
frac.baseOffsetD[i] = 1;
frac.alternateOffsetN[i] = 0;
frac.alternateOffsetD[i] = 1;
}
frac.baseHdrHeadroomN = 0;
frac.baseHdrHeadroomD = 1;
frac.alternateHdrHeadroomN = 1;
frac.alternateHdrHeadroomD = 1;

// Test 1: max_content_boost < min_content_boost
frac.gainMapMaxN[0] = 0; // log2(max_boost) = 0 -> max_boost = 1.0
frac.gainMapMinN[0] = 2; // log2(min_boost) = 2 -> min_boost = 4.0
uhdr_gainmap_metadata_ext_t float_meta;
EXPECT_EQ(uhdr_gainmap_metadata_frac::gainmapMetadataFractionToFloat(&frac, &float_meta).error_code,
UHDR_CODEC_INVALID_PARAM);

// Test 2: Inverted HDR capacity range (max <= min)
frac.gainMapMaxN[0] = 1;
frac.gainMapMinN[0] = 0;
frac.alternateHdrHeadroomN = 0; // log2(headroom_max) = 0 -> 1.0
frac.baseHdrHeadroomN = 1; // log2(headroom_min) = 1 -> 2.0
EXPECT_EQ(uhdr_gainmap_metadata_frac::gainmapMetadataFractionToFloat(&frac, &float_meta).error_code,
UHDR_CODEC_INVALID_PARAM);
}

} // namespace ultrahdr
Loading