Skip to content

Commit

Permalink
Update library to use definitions of ultrahdr_api everywhere
Browse files Browse the repository at this point in the history
This is a major change but maintains bitexactness with previous commit.
This change unifies legacy structure definitions with definitions of
ultrahdr_api.h. This helps for better extensibility for new features and
avoid redundancy.

Legacy structures are moved to ultrahdr.h. These are deprecated and only
retained for backward compatibility.

Briefly,
- unify ultrahdr_color_gamut with uhdr_color_gamut_t
- unify ultrahdr_transfer_function with uhdr_color_transfer_t
- unify ultrahdr_metadata_struct with uhdr_gainmap_metadata_t
- unify jpegr_uncompressed_struct with uhdr_raw_image_t
- unify jpegr_compressed_struct with uhdr_compressed_image_t
- unify jpegr_exif_struct with uhdr_mem_block_t
- unify status_t with uhdr_error_info_t
- Deprecate ultrahdr_output_format
- Added methods to Jpeg*Helper to simplify data translation between helper
  and its users
- Improved error propogation across library

Bug fix,
- For images with multi channel gainmap, decoded gainmap is not copied
  completely for getter functions. This is fixed.
- Add support for tonemapping linear transfer inputs
- Fixes oss-fuzz: 69287

Test: ./ultrahdr_unit_test
Test: ./ultrahdr_enc_fuzzer
Test: ./ultrahdr_dec_fuzzer
  • Loading branch information
ram-mohan committed Jun 27, 2024
1 parent fa1ac5f commit e1072d4
Show file tree
Hide file tree
Showing 28 changed files with 3,487 additions and 2,930 deletions.
15 changes: 12 additions & 3 deletions benchmark/benchmark_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -510,12 +510,21 @@ static void BM_Encode_Api4(benchmark::State& s) {
gainmapImg.data = gainmapImgInfo.imgData.data();
gainmapImg.maxLength = gainmapImg.length = gainmapImgInfo.imgData.size();
gainmapImg.colorGamut = ULTRAHDR_COLORGAMUT_UNSPECIFIED;
ultrahdr_metadata_struct uhdr_metadata;
if (!getMetadataFromXMP(gainmapImgInfo.xmpData.data(), gainmapImgInfo.xmpData.size(),
&uhdr_metadata)) {
uhdr_gainmap_metadata_ext_t meta;
if (getMetadataFromXMP(gainmapImgInfo.xmpData.data(), gainmapImgInfo.xmpData.size(), &meta)
.error_code != UHDR_CODEC_OK) {
s.SkipWithError("getMetadataFromXMP returned with error");
return;
}
ultrahdr_metadata_struct uhdr_metadata;
uhdr_metadata.version = meta.version;
uhdr_metadata.hdrCapacityMax = meta.hdr_capacity_max;
uhdr_metadata.hdrCapacityMin = meta.hdr_capacity_min;
uhdr_metadata.gamma = meta.gamma;
uhdr_metadata.offsetSdr = meta.offset_sdr;
uhdr_metadata.offsetHdr = meta.offset_hdr;
uhdr_metadata.maxContentBoost = meta.max_content_boost;
uhdr_metadata.minContentBoost = meta.min_content_boost;
for (auto _ : s) {
status = jpegHdr.encodeJPEGR(&primaryImg, &gainmapImg, &uhdr_metadata, &jpegImgR);
if (JPEGR_NO_ERROR != status) {
Expand Down
12 changes: 8 additions & 4 deletions fuzzer/ultrahdr_enc_fuzzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,10 @@ void UltraHdrEncFuzzer::process() {
yuv420ImgCopy.chroma_stride * yuv420ImgCopy.height / 2};
const size_t strides[3]{yuv420ImgCopy.luma_stride, yuv420ImgCopy.chroma_stride,
yuv420ImgCopy.chroma_stride};
if (encoder.compressImage(planes, strides, yuv420ImgCopy.width, yuv420ImgCopy.height,
UHDR_IMG_FMT_12bppYCbCr420, quality, nullptr, 0)) {
if (encoder
.compressImage(planes, strides, yuv420ImgCopy.width, yuv420ImgCopy.height,
UHDR_IMG_FMT_12bppYCbCr420, quality, nullptr, 0)
.error_code == UHDR_CODEC_OK) {
jpegImg.length = encoder.getCompressedImageSize();
jpegImg.maxLength = jpegImg.length;
jpegImg.data = encoder.getCompressedImagePtr();
Expand All @@ -266,8 +268,10 @@ void UltraHdrEncFuzzer::process() {
JpegEncoderHelper gainMapEncoder;
const uint8_t* planeGm[1]{reinterpret_cast<uint8_t*>(grayImg.data)};
const size_t strideGm[1]{grayImg.width};
if (gainMapEncoder.compressImage(planeGm, strideGm, grayImg.width, grayImg.height,
UHDR_IMG_FMT_8bppYCbCr400, quality, nullptr, 0)) {
if (gainMapEncoder
.compressImage(planeGm, strideGm, grayImg.width, grayImg.height,
UHDR_IMG_FMT_8bppYCbCr400, quality, nullptr, 0)
.error_code == UHDR_CODEC_OK) {
jpegGainMap.length = gainMapEncoder.getCompressedImageSize();
jpegGainMap.maxLength = jpegImg.length;
jpegGainMap.data = gainMapEncoder.getCompressedImagePtr();
Expand Down
60 changes: 31 additions & 29 deletions lib/include/ultrahdr/gainmapmath.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@

#include "ultrahdr_api.h"
#include "ultrahdr/ultrahdrcommon.h"
#include "ultrahdr/ultrahdr.h"
#include "ultrahdr/jpegr.h"

#if (defined(UHDR_ENABLE_INTRINSICS) && (defined(__ARM_NEON__) || defined(__ARM_NEON)))
Expand Down Expand Up @@ -176,23 +175,23 @@ inline uint16_t floatToHalf(float f) {
constexpr int32_t kGainFactorPrecision = 10;
constexpr int32_t kGainFactorNumEntries = 1 << kGainFactorPrecision;
struct GainLUT {
GainLUT(ultrahdr_metadata_ptr metadata) {
GainLUT(uhdr_gainmap_metadata_ext_t* metadata) {
this->mGammaInv = 1.0f / metadata->gamma;
for (int32_t idx = 0; idx < kGainFactorNumEntries; idx++) {
float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1);
float logBoost = log2(metadata->minContentBoost) * (1.0f - value) +
log2(metadata->maxContentBoost) * value;
float logBoost = log2(metadata->min_content_boost) * (1.0f - value) +
log2(metadata->max_content_boost) * value;
mGainTable[idx] = exp2(logBoost);
}
}

GainLUT(ultrahdr_metadata_ptr metadata, float displayBoost) {
GainLUT(uhdr_gainmap_metadata_ext_t* metadata, float displayBoost) {
this->mGammaInv = 1.0f / metadata->gamma;
float boostFactor = displayBoost > 0 ? displayBoost / metadata->maxContentBoost : 1.0f;
float boostFactor = displayBoost > 0 ? displayBoost / metadata->max_content_boost : 1.0f;
for (int32_t idx = 0; idx < kGainFactorNumEntries; idx++) {
float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1);
float logBoost = log2(metadata->minContentBoost) * (1.0f - value) +
log2(metadata->maxContentBoost) * value;
float logBoost = log2(metadata->min_content_boost) * (1.0f - value) +
log2(metadata->max_content_boost) * value;
mGainTable[idx] = exp2(logBoost * boostFactor);
}
}
Expand Down Expand Up @@ -432,7 +431,7 @@ inline Color identityConversion(Color e) { return e; }
/*
* Get the conversion to apply to the HDR image for gain map generation
*/
ColorTransformFn getHdrConversionFn(ultrahdr_color_gamut sdr_gamut, ultrahdr_color_gamut hdr_gamut);
ColorTransformFn getHdrConversionFn(uhdr_color_gamut_t sdr_gamut, uhdr_color_gamut_t hdr_gamut);

/*
* Convert between YUV encodings, according to ITU-R BT.709-6, ITU-R BT.601-7, and ITU-R BT.2100-2.
Expand Down Expand Up @@ -464,10 +463,10 @@ extern const int16_t kYuv2100To601_coeffs_neon[8];
*/
int16x8x3_t yuvConversion_neon(uint8x8_t y, int16x8_t u, int16x8_t v, int16x8_t coeffs);

void transformYuv420_neon(jr_uncompressed_ptr image, const int16_t* coeffs_ptr);
void transformYuv420_neon(uhdr_raw_image_t* image, const int16_t* coeffs_ptr);

status_t convertYuv_neon(jr_uncompressed_ptr image, ultrahdr_color_gamut src_encoding,
ultrahdr_color_gamut dst_encoding);
uhdr_error_info_t convertYuv_neon(uhdr_raw_image_t* image, uhdr_color_gamut_t src_encoding,
uhdr_color_gamut_t dst_encoding);
#endif

/*
Expand All @@ -479,7 +478,7 @@ status_t convertYuv_neon(jr_uncompressed_ptr image, ultrahdr_color_gamut src_enc
* The chroma channels should be less than or equal to half the image's width and height
* respectively, since input is 4:2:0 subsampled.
*/
void transformYuv420(jr_uncompressed_ptr image, const std::array<float, 9>& coeffs);
void transformYuv420(uhdr_raw_image_t* image, const std::array<float, 9>& coeffs);

////////////////////////////////////////////////////////////////////////////////
// Gain map calculations
Expand All @@ -492,8 +491,8 @@ void transformYuv420(jr_uncompressed_ptr image, const std::array<float, 9>& coef
* offsetHdr of 0.0, this function doesn't handle different metadata values for
* these fields.
*/
uint8_t encodeGain(float y_sdr, float y_hdr, ultrahdr_metadata_ptr metadata);
uint8_t encodeGain(float y_sdr, float y_hdr, ultrahdr_metadata_ptr metadata,
uint8_t encodeGain(float y_sdr, float y_hdr, uhdr_gainmap_metadata_ext_t* metadata);
uint8_t encodeGain(float y_sdr, float y_hdr, uhdr_gainmap_metadata_ext_t* metadata,
float log2MinContentBoost, float log2MaxContentBoost);

/*
Expand All @@ -504,8 +503,8 @@ uint8_t encodeGain(float y_sdr, float y_hdr, ultrahdr_metadata_ptr metadata,
* offsetSdr 0.0, offsetHdr 0.0, hdrCapacityMin 1.0, and hdrCapacityMax equal to
* gainMapMax, as this library encodes.
*/
Color applyGain(Color e, float gain, ultrahdr_metadata_ptr metadata);
Color applyGain(Color e, float gain, ultrahdr_metadata_ptr metadata, float displayBoost);
Color applyGain(Color e, float gain, uhdr_gainmap_metadata_ext_t* metadata);
Color applyGain(Color e, float gain, uhdr_gainmap_metadata_ext_t* metadata, float displayBoost);
Color applyGainLUT(Color e, float gain, GainLUT& gainLUT);

/*
Expand All @@ -516,46 +515,44 @@ Color applyGainLUT(Color e, float gain, GainLUT& gainLUT);
* offsetSdr 0.0, offsetHdr 0.0, hdrCapacityMin 1.0, and hdrCapacityMax equal to
* gainMapMax, as this library encodes.
*/
Color applyGain(Color e, Color gain, ultrahdr_metadata_ptr metadata);
Color applyGain(Color e, Color gain, ultrahdr_metadata_ptr metadata, float displayBoost);
Color applyGain(Color e, Color gain, uhdr_gainmap_metadata_ext_t* metadata);
Color applyGain(Color e, Color gain, uhdr_gainmap_metadata_ext_t* metadata, float displayBoost);
Color applyGainLUT(Color e, Color gain, GainLUT& gainLUT);

/*
* Helper for sampling from YUV 420 images.
*/
Color getYuv420Pixel(jr_uncompressed_ptr image, size_t x, size_t y);
Color getYuv420Pixel(uhdr_raw_image_t* image, size_t x, size_t y);

/*
* Helper for sampling from P010 images.
*
* Expect narrow-range image data for P010.
*/
Color getP010Pixel(jr_uncompressed_ptr image, size_t x, size_t y);
Color getP010Pixel(uhdr_raw_image_t* image, size_t x, size_t y);

/*
* Sample the image at the provided location, with a weighting based on nearby
* pixels and the map scale factor.
*/
Color sampleYuv420(jr_uncompressed_ptr map, size_t map_scale_factor, size_t x, size_t y);
Color sampleYuv420(uhdr_raw_image_t* map, size_t map_scale_factor, size_t x, size_t y);

/*
* Sample the image at the provided location, with a weighting based on nearby
* pixels and the map scale factor.
*
* Expect narrow-range image data for P010.
*/
Color sampleP010(jr_uncompressed_ptr map, size_t map_scale_factor, size_t x, size_t y);
Color sampleP010(uhdr_raw_image_t* map, size_t map_scale_factor, size_t x, size_t y);

/*
* Sample the gain value for the map from a given x,y coordinate on a scale
* that is map scale factor larger than the map size.
*/
float sampleMap(jr_uncompressed_ptr map, float map_scale_factor, size_t x, size_t y);
float sampleMap(jr_uncompressed_ptr map, size_t map_scale_factor, size_t x, size_t y,
float sampleMap(uhdr_raw_image_t* map, float map_scale_factor, size_t x, size_t y);
float sampleMap(uhdr_raw_image_t* map, size_t map_scale_factor, size_t x, size_t y,
ShepardsIDW& weightTables);
Color sampleMap3Channel(jr_uncompressed_ptr map, float map_scale_factor, size_t x, size_t y,
Color sampleMap3Channel(uhdr_raw_image_t* map, float map_scale_factor, size_t x, size_t y,
bool has_alpha);
Color sampleMap3Channel(jr_uncompressed_ptr map, size_t map_scale_factor, size_t x, size_t y,
Color sampleMap3Channel(uhdr_raw_image_t* map, size_t map_scale_factor, size_t x, size_t y,
ShepardsIDW& weightTables, bool has_alpha);

/*
Expand All @@ -572,6 +569,11 @@ uint32_t colorToRgba1010102(Color e_gamma);
*/
uint64_t colorToRgbaF16(Color e_gamma);

/*
* Helper for copying raw image descriptor
*/
uhdr_error_info_t copy_raw_image(uhdr_raw_image_t* src, uhdr_raw_image_t* dst);

/*
* Helper for preparing encoder raw inputs for encoding
*/
Expand Down
30 changes: 11 additions & 19 deletions lib/include/ultrahdr/gainmapmetadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,15 @@
#define ULTRAHDR_GAINMAPMETADATA_H

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

#include <memory>
#include <vector>

namespace ultrahdr {

#define JPEGR_CHECK(x) \
{ \
status_t status = (x); \
if ((status) != JPEGR_NO_ERROR) { \
return status; \
} \
}

// Gain map metadata, for tone mapping between SDR and HDR.
// This is the fraction version of {@code ultrahdr_metadata_struct}.
struct gain_map_metadata {
// This is the fraction version of {@code uhdr_gainmap_metadata_ext_t}.
struct uhdr_gainmap_metadata_frac {
uint32_t gainMapMinN[3];
uint32_t gainMapMinD[3];
uint32_t gainMapMaxN[3];
Expand All @@ -56,17 +47,17 @@ struct gain_map_metadata {
bool backwardDirection;
bool useBaseColorSpace;

static status_t encodeGainmapMetadata(const gain_map_metadata* gain_map_metadata,
std::vector<uint8_t>& out_data);
static uhdr_error_info_t encodeGainmapMetadata(const uhdr_gainmap_metadata_frac* in_metadata,
std::vector<uint8_t>& out_data);

static status_t decodeGainmapMetadata(const std::vector<uint8_t>& data,
gain_map_metadata* out_gain_map_metadata);
static uhdr_error_info_t decodeGainmapMetadata(const std::vector<uint8_t>& in_data,
uhdr_gainmap_metadata_frac* out_metadata);

static status_t gainmapMetadataFractionToFloat(const gain_map_metadata* from,
ultrahdr_metadata_ptr to);
static uhdr_error_info_t gainmapMetadataFractionToFloat(const uhdr_gainmap_metadata_frac* from,
uhdr_gainmap_metadata_ext_t* to);

static status_t gainmapMetadataFloatToFraction(const ultrahdr_metadata_ptr from,
gain_map_metadata* to);
static uhdr_error_info_t gainmapMetadataFloatToFraction(const uhdr_gainmap_metadata_ext_t* from,
uhdr_gainmap_metadata_frac* to);

void dump() const {
ALOGD("GAIN MAP METADATA: \n");
Expand Down Expand Up @@ -98,6 +89,7 @@ struct gain_map_metadata {
ALOGD("use base color space: %s\n", useBaseColorSpace ? "true" : "false");
}
};

} // namespace ultrahdr

#endif // ULTRAHDR_GAINMAPMETADATA_H
14 changes: 7 additions & 7 deletions lib/include/ultrahdr/icc.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
#define Endian_SwapBE16(n) (n)
#endif

#include "ultrahdr/ultrahdr.h"
#include "ultrahdr/jpegr.h"
#include "ultrahdr/gainmapmath.h"
#include "ultrahdr/jpegrutils.h"
Expand Down Expand Up @@ -227,12 +226,12 @@ class IccHelper {
static constexpr size_t kNumChannels = 3;

static std::shared_ptr<DataStruct> write_text_tag(const char* text);
static std::string get_desc_string(const ultrahdr_transfer_function tf,
const ultrahdr_color_gamut gamut);
static std::string get_desc_string(const uhdr_color_transfer_t tf,
const uhdr_color_gamut_t gamut);
static std::shared_ptr<DataStruct> write_xyz_tag(float x, float y, float z);
static std::shared_ptr<DataStruct> write_trc_tag(const int table_entries, const void* table_16);
static std::shared_ptr<DataStruct> write_trc_tag(const TransferFunction& fn);
static float compute_tone_map_gain(const ultrahdr_transfer_function tf, float L);
static float compute_tone_map_gain(const uhdr_color_transfer_t tf, float L);
static std::shared_ptr<DataStruct> write_cicp_tag(uint32_t color_primaries,
uint32_t transfer_characteristics);
static std::shared_ptr<DataStruct> write_mAB_or_mBA_tag(uint32_t type, bool has_a_curves,
Expand All @@ -249,13 +248,14 @@ class IccHelper {
public:
// Output includes JPEG embedding identifier and chunk information, but not
// APPx information.
static std::shared_ptr<DataStruct> writeIccProfile(const ultrahdr_transfer_function tf,
const ultrahdr_color_gamut gamut);
static std::shared_ptr<DataStruct> writeIccProfile(const uhdr_color_transfer_t tf,
const uhdr_color_gamut_t gamut);
// NOTE: this function is not robust; it can infer gamuts that IccHelper
// writes out but should not be considered a reference implementation for
// robust parsing of ICC profiles or their gamuts.
static ultrahdr_color_gamut readIccColorGamut(void* icc_data, size_t icc_size);
static uhdr_color_gamut_t readIccColorGamut(void* icc_data, size_t icc_size);
};

} // namespace ultrahdr

#endif // ULTRAHDR_ICC_H
Loading

0 comments on commit e1072d4

Please sign in to comment.