Commit 72672c1c for libheif
commit 72672c1cb3c059158eaa663661a967d52f2a75ee
Author: Dirk Farin <dirk.farin@gmail.com>
Date: Sat Apr 4 03:10:09 2026 +0200
unci: refactor to opaque component ids (wip)
diff --git a/examples/heif_gen_bayer.cc b/examples/heif_gen_bayer.cc
index c59f1b81..f07265b2 100644
--- a/examples/heif_gen_bayer.cc
+++ b/examples/heif_gen_bayer.cc
@@ -50,7 +50,7 @@ struct PatternDefinition
std::string name;
uint16_t width;
uint16_t height;
- std::vector<heif_uncompressed_component_type> cpat;
+ std::vector<heif_unci_component_type> cpat;
};
@@ -61,10 +61,10 @@ static const PatternDefinition patterns[] = {
{
"rggb", 2, 2,
{
- heif_uncompressed_component_type_red,
- heif_uncompressed_component_type_green,
- heif_uncompressed_component_type_green,
- heif_uncompressed_component_type_blue,
+ heif_unci_component_type_red,
+ heif_unci_component_type_green,
+ heif_unci_component_type_green,
+ heif_unci_component_type_blue,
}
},
@@ -77,25 +77,25 @@ static const PatternDefinition patterns[] = {
{
"rgbw", 4, 4,
{
- heif_uncompressed_component_type_Y,
- heif_uncompressed_component_type_green,
- heif_uncompressed_component_type_Y,
- heif_uncompressed_component_type_red,
-
- heif_uncompressed_component_type_green,
- heif_uncompressed_component_type_Y,
- heif_uncompressed_component_type_blue,
- heif_uncompressed_component_type_Y,
-
- heif_uncompressed_component_type_Y,
- heif_uncompressed_component_type_blue,
- heif_uncompressed_component_type_Y,
- heif_uncompressed_component_type_green,
-
- heif_uncompressed_component_type_red,
- heif_uncompressed_component_type_Y,
- heif_uncompressed_component_type_green,
- heif_uncompressed_component_type_Y,
+ heif_unci_component_type_Y,
+ heif_unci_component_type_green,
+ heif_unci_component_type_Y,
+ heif_unci_component_type_red,
+
+ heif_unci_component_type_green,
+ heif_unci_component_type_Y,
+ heif_unci_component_type_blue,
+ heif_unci_component_type_Y,
+
+ heif_unci_component_type_Y,
+ heif_unci_component_type_blue,
+ heif_unci_component_type_Y,
+ heif_unci_component_type_green,
+
+ heif_unci_component_type_red,
+ heif_unci_component_type_Y,
+ heif_unci_component_type_green,
+ heif_unci_component_type_Y,
}
},
@@ -107,25 +107,25 @@ static const PatternDefinition patterns[] = {
{
"qbc", 4, 4,
{
- heif_uncompressed_component_type_green,
- heif_uncompressed_component_type_green,
- heif_uncompressed_component_type_red,
- heif_uncompressed_component_type_red,
-
- heif_uncompressed_component_type_green,
- heif_uncompressed_component_type_green,
- heif_uncompressed_component_type_red,
- heif_uncompressed_component_type_red,
-
- heif_uncompressed_component_type_blue,
- heif_uncompressed_component_type_blue,
- heif_uncompressed_component_type_green,
- heif_uncompressed_component_type_green,
-
- heif_uncompressed_component_type_blue,
- heif_uncompressed_component_type_blue,
- heif_uncompressed_component_type_green,
- heif_uncompressed_component_type_green,
+ heif_unci_component_type_green,
+ heif_unci_component_type_green,
+ heif_unci_component_type_red,
+ heif_unci_component_type_red,
+
+ heif_unci_component_type_green,
+ heif_unci_component_type_green,
+ heif_unci_component_type_red,
+ heif_unci_component_type_red,
+
+ heif_unci_component_type_blue,
+ heif_unci_component_type_blue,
+ heif_unci_component_type_green,
+ heif_unci_component_type_green,
+
+ heif_unci_component_type_blue,
+ heif_unci_component_type_blue,
+ heif_unci_component_type_green,
+ heif_unci_component_type_green,
}
},
};
@@ -153,14 +153,14 @@ static std::optional<PatternDefinition> parse_pattern_string(const char* str)
}
uint16_t dim = (len == 4) ? 2 : 4;
- std::vector<heif_uncompressed_component_type> cpat;
+ std::vector<heif_unci_component_type> cpat;
cpat.reserve(len);
for (char c : s) {
switch (std::tolower(c)) {
- case 'r': cpat.push_back(heif_uncompressed_component_type_red); break;
- case 'g': cpat.push_back(heif_uncompressed_component_type_green); break;
- case 'b': cpat.push_back(heif_uncompressed_component_type_blue); break;
+ case 'r': cpat.push_back(heif_unci_component_type_red); break;
+ case 'g': cpat.push_back(heif_unci_component_type_green); break;
+ case 'b': cpat.push_back(heif_unci_component_type_blue); break;
default: return {};
}
}
@@ -309,7 +309,9 @@ static heif_image* create_bayer_image_from_png(const char* png_filename,
return nullptr;
}
- err = heif_image_add_plane(bayer_img, heif_channel_filter_array, width, height, output_bit_depth);
+ uint32_t filter_array_component_id;
+
+ err = heif_image_add_component(bayer_img, width, height, heif_unci_component_type_filter_array, heif_component_datatype_unsigned_integer, output_bit_depth, &filter_array_component_id);
if (err.code != heif_error_Ok) {
std::cerr << "Cannot add plane: " << err.message << "\n";
heif_image_release(bayer_img);
@@ -335,10 +337,10 @@ static heif_image* create_bayer_image_from_png(const char* png_filename,
auto comp_type = pat->cpat[py * pat->width + px];
switch (comp_type) {
- case heif_uncompressed_component_type_red: dst_row[x] = r; break;
- case heif_uncompressed_component_type_green: dst_row[x] = g; break;
- case heif_uncompressed_component_type_blue: dst_row[x] = b; break;
- case heif_uncompressed_component_type_Y: dst_row[x] = static_cast<uint8_t>((r + g + b) / 3); break;
+ case heif_unci_component_type_red: dst_row[x] = r; break;
+ case heif_unci_component_type_green: dst_row[x] = g; break;
+ case heif_unci_component_type_blue: dst_row[x] = b; break;
+ case heif_unci_component_type_Y: dst_row[x] = static_cast<uint8_t>((r + g + b) / 3); break;
default:
assert(false);
}
@@ -366,10 +368,10 @@ static heif_image* create_bayer_image_from_png(const char* png_filename,
auto comp_type = pat->cpat[py * pat->width + px];
switch (comp_type) {
- case heif_uncompressed_component_type_red: dst_row[x] = r; break;
- case heif_uncompressed_component_type_green: dst_row[x] = g; break;
- case heif_uncompressed_component_type_blue: dst_row[x] = b; break;
- case heif_uncompressed_component_type_Y: dst_row[x] = static_cast<uint16_t>((r + g + b) / 3); break;
+ case heif_unci_component_type_red: dst_row[x] = r; break;
+ case heif_unci_component_type_green: dst_row[x] = g; break;
+ case heif_unci_component_type_blue: dst_row[x] = b; break;
+ case heif_unci_component_type_Y: dst_row[x] = static_cast<uint16_t>((r + g + b) / 3); break;
default:
assert(false);
}
@@ -377,17 +379,30 @@ static heif_image* create_bayer_image_from_png(const char* png_filename,
}
}
+ // map component type to component id
+
+ std::map<uint16_t, uint32_t> map_type_to_id;
+ for (const auto& type : pat->cpat) {
+ if (map_type_to_id.find(type) == map_type_to_id.end()) {
+ uint32_t component_id;
+ heif_image_add_bayer_component(bayer_img, type, &component_id);
+
+ map_type_to_id[type] = component_id;
+ }
+ }
+
// Build heif_bayer_pattern_pixel array from component types.
// The component_index values here are the component types themselves — the encoder
// will resolve them to proper cmpd indices when writing the cpat box.
std::vector<heif_bayer_pattern_pixel> bayer_pixels(pat->cpat.size());
for (size_t i = 0; i < pat->cpat.size(); i++) {
- bayer_pixels[i].component_index = static_cast<uint16_t>(pat->cpat[i]);
+ bayer_pixels[i].component_id = map_type_to_id[pat->cpat[i]];
bayer_pixels[i].component_gain = 1.0f;
}
// Set Bayer pattern metadata
err = heif_image_set_bayer_pattern(bayer_img,
+ filter_array_component_id,
pat->width, pat->height,
bayer_pixels.data());
if (err.code != heif_error_Ok) {
diff --git a/heifio/decoder_raw.cc b/heifio/decoder_raw.cc
index 4ee0cce4..a17ed8e0 100644
--- a/heifio/decoder_raw.cc
+++ b/heifio/decoder_raw.cc
@@ -38,39 +38,39 @@ static struct heif_error heif_error_ok = {heif_error_Ok, heif_suberror_Unspecifi
bool parse_raw_pixel_type(const std::string& type_string,
- heif_channel_datatype* out_datatype,
+ heif_component_datatype* out_datatype,
int* out_bit_depth)
{
if (type_string == "uint8") {
- *out_datatype = heif_channel_datatype_unsigned_integer;
+ *out_datatype = heif_component_datatype_unsigned_integer;
*out_bit_depth = 8;
}
else if (type_string == "sint8") {
- *out_datatype = heif_channel_datatype_signed_integer;
+ *out_datatype = heif_component_datatype_signed_integer;
*out_bit_depth = 8;
}
else if (type_string == "uint16") {
- *out_datatype = heif_channel_datatype_unsigned_integer;
+ *out_datatype = heif_component_datatype_unsigned_integer;
*out_bit_depth = 16;
}
else if (type_string == "sint16") {
- *out_datatype = heif_channel_datatype_signed_integer;
+ *out_datatype = heif_component_datatype_signed_integer;
*out_bit_depth = 16;
}
else if (type_string == "uint32") {
- *out_datatype = heif_channel_datatype_unsigned_integer;
+ *out_datatype = heif_component_datatype_unsigned_integer;
*out_bit_depth = 32;
}
else if (type_string == "sint32") {
- *out_datatype = heif_channel_datatype_signed_integer;
+ *out_datatype = heif_component_datatype_signed_integer;
*out_bit_depth = 32;
}
else if (type_string == "float32") {
- *out_datatype = heif_channel_datatype_floating_point;
+ *out_datatype = heif_component_datatype_floating_point;
*out_bit_depth = 32;
}
else if (type_string == "float64") {
- *out_datatype = heif_channel_datatype_floating_point;
+ *out_datatype = heif_component_datatype_floating_point;
*out_bit_depth = 64;
}
else {
@@ -103,7 +103,7 @@ heif_error loadRAW(const char* filename, const RawImageParameters& params, Input
"At least one of --raw-width or --raw-height must be specified"};
}
- if (params.datatype == heif_channel_datatype_undefined || params.bit_depth <= 0) {
+ if (params.datatype == heif_component_datatype_undefined || params.bit_depth <= 0) {
return {heif_error_Invalid_input, heif_suberror_Unspecified,
"Raw image pixel type must be specified (use --raw-type)"};
}
@@ -187,7 +187,7 @@ heif_error loadRAW(const char* filename, const RawImageParameters& params, Input
uint32_t component_idx = 0;
err = heif_image_add_component(image, width, height,
- heif_uncompressed_component_type_monochrome,
+ heif_unci_component_type_monochrome,
params.datatype, params.bit_depth,
&component_idx);
if (err.code != heif_error_Ok) {
diff --git a/heifio/decoder_raw.h b/heifio/decoder_raw.h
index b272e67d..1f856757 100644
--- a/heifio/decoder_raw.h
+++ b/heifio/decoder_raw.h
@@ -34,7 +34,7 @@
struct RawImageParameters {
int width = 0;
int height = 0;
- heif_channel_datatype datatype = heif_channel_datatype_undefined;
+ heif_component_datatype datatype = heif_component_datatype_undefined;
int bit_depth = 0;
bool big_endian = false;
};
@@ -42,7 +42,7 @@ struct RawImageParameters {
// Maps a CLI string like "uint16" or "float32" to datatype + bit_depth.
// Returns false if the string is not recognized.
bool parse_raw_pixel_type(const std::string& type_string,
- heif_channel_datatype* out_datatype,
+ heif_component_datatype* out_datatype,
int* out_bit_depth);
LIBHEIF_API
diff --git a/heifio/decoder_tiff.cc b/heifio/decoder_tiff.cc
index baea6103..980371e5 100644
--- a/heifio/decoder_tiff.cc
+++ b/heifio/decoder_tiff.cc
@@ -693,8 +693,8 @@ static heif_error readMonoFloat(TIFF* tif, heif_image** image)
uint32_t component_idx;
err = heif_image_add_component(*image, (int)width, (int)height,
- heif_uncompressed_component_type_monochrome,
- heif_channel_datatype_floating_point, 32, &component_idx);
+ heif_unci_component_type_monochrome,
+ heif_component_datatype_floating_point, 32, &component_idx);
if (err.code != heif_error_Ok) {
heif_image_release(*image);
*image = nullptr;
@@ -740,8 +740,8 @@ static heif_error readMonoSignedInt(TIFF* tif, uint16_t bps, heif_image** image)
uint32_t component_idx;
err = heif_image_add_component(*image, (int)width, (int)height,
- heif_uncompressed_component_type_monochrome,
- heif_channel_datatype_signed_integer, bps, &component_idx);
+ heif_unci_component_type_monochrome,
+ heif_component_datatype_signed_integer, bps, &component_idx);
if (err.code != heif_error_Ok) {
heif_image_release(*image);
*image = nullptr;
@@ -1031,8 +1031,8 @@ static heif_error readTiledContiguous(TIFF* tif, uint32_t width, uint32_t height
uint32_t component_idx;
err = heif_image_add_component(*out_image, (int)width, (int)height,
- heif_uncompressed_component_type_monochrome,
- heif_channel_datatype_floating_point, 32, &component_idx);
+ heif_unci_component_type_monochrome,
+ heif_component_datatype_floating_point, 32, &component_idx);
if (err.code != heif_error_Ok) {
heif_image_release(*out_image);
*out_image = nullptr;
@@ -1091,8 +1091,8 @@ static heif_error readTiledContiguous(TIFF* tif, uint32_t width, uint32_t height
uint32_t component_idx;
err = heif_image_add_component(*out_image, (int)width, (int)height,
- heif_uncompressed_component_type_monochrome,
- heif_channel_datatype_signed_integer, bps, &component_idx);
+ heif_unci_component_type_monochrome,
+ heif_component_datatype_signed_integer, bps, &component_idx);
if (err.code != heif_error_Ok) {
heif_image_release(*out_image);
*out_image = nullptr;
@@ -1637,8 +1637,8 @@ heif_error TiledTiffReader::readTile(uint32_t tx, uint32_t ty, int output_bit_de
uint32_t component_idx;
err = heif_image_add_component(*out_image, (int)actual_w, (int)actual_h,
- heif_uncompressed_component_type_monochrome,
- heif_channel_datatype_floating_point, 32, &component_idx);
+ heif_unci_component_type_monochrome,
+ heif_component_datatype_floating_point, 32, &component_idx);
if (err.code != heif_error_Ok) {
heif_image_release(*out_image);
*out_image = nullptr;
@@ -1684,8 +1684,8 @@ heif_error TiledTiffReader::readTile(uint32_t tx, uint32_t ty, int output_bit_de
uint32_t component_idx;
err = heif_image_add_component(*out_image, (int)actual_w, (int)actual_h,
- heif_uncompressed_component_type_monochrome,
- heif_channel_datatype_signed_integer, m_bits_per_sample, &component_idx);
+ heif_unci_component_type_monochrome,
+ heif_component_datatype_signed_integer, m_bits_per_sample, &component_idx);
if (err.code != heif_error_Ok) {
heif_image_release(*out_image);
*out_image = nullptr;
diff --git a/libheif/api/libheif/heif_uncompressed.cc b/libheif/api/libheif/heif_uncompressed.cc
index 22ea296b..152f5af8 100644
--- a/libheif/api/libheif/heif_uncompressed.cc
+++ b/libheif/api/libheif/heif_uncompressed.cc
@@ -31,6 +31,7 @@
heif_error heif_image_set_bayer_pattern(heif_image* image,
+ uint32_t bayer_component_id,
uint16_t pattern_width,
uint16_t pattern_height,
const struct heif_bayer_pattern_pixel* patternPixels)
@@ -58,11 +59,26 @@ heif_error heif_image_set_bayer_pattern(heif_image* image,
}
+heif_error heif_image_add_bayer_component(heif_image* image,
+ uint16_t component_type,
+ uint32_t* out_component_id)
+{
+ if (image == nullptr || out_component_id == nullptr) {
+ return heif_error_null_pointer_argument;
+ }
+
+ *out_component_id = image->image->add_component_without_data(component_type);
+
+ return heif_error_success;
+}
+
+
int heif_image_has_bayer_pattern(const heif_image* image,
+ uint32_t bayer_component_id,
uint16_t* out_pattern_width,
uint16_t* out_pattern_height)
{
- if (image == nullptr || !image->image->has_bayer_pattern()) {
+ if (image == nullptr || !image->image->has_bayer_pattern(bayer_component_id)) {
if (out_pattern_width) {
*out_pattern_width = 0;
}
@@ -72,7 +88,7 @@ int heif_image_has_bayer_pattern(const heif_image* image,
return 0;
}
- const BayerPattern& pattern = image->image->get_bayer_pattern();
+ const BayerPattern& pattern = image->image->get_bayer_pattern(bayer_component_id);
if (out_pattern_width) {
*out_pattern_width = pattern.pattern_width;
@@ -86,19 +102,20 @@ int heif_image_has_bayer_pattern(const heif_image* image,
heif_error heif_image_get_bayer_pattern(const heif_image* image,
+ uint32_t bayer_component_id,
struct heif_bayer_pattern_pixel* out_patternPixels)
{
if (image == nullptr || out_patternPixels == nullptr) {
return heif_error_null_pointer_argument;
}
- if (!image->image->has_bayer_pattern()) {
+ if (!image->image->has_bayer_pattern(bayer_component_id)) {
return {heif_error_Usage_error,
heif_suberror_Invalid_parameter_value,
"Image does not have a Bayer pattern."};
}
- const BayerPattern& pattern = image->image->get_bayer_pattern();
+ const BayerPattern& pattern = image->image->get_bayer_pattern(bayer_component_id);
size_t num_pixels = size_t{pattern.pattern_width} * pattern.pattern_height;
std::copy(pattern.pixels.begin(), pattern.pixels.begin() + num_pixels, out_patternPixels);
@@ -124,8 +141,8 @@ int heif_polarization_angle_is_no_filter(float angle)
heif_error heif_image_add_polarization_pattern(heif_image* image,
- uint32_t num_component_indices,
- const uint32_t* component_indices,
+ uint32_t num_component_ids,
+ const uint32_t* component_ids,
uint16_t pattern_width,
uint16_t pattern_height,
const float* polarization_angles)
@@ -134,7 +151,7 @@ heif_error heif_image_add_polarization_pattern(heif_image* image,
return heif_error_null_pointer_argument;
}
- if (num_component_indices > 0 && component_indices == nullptr) {
+ if (num_component_ids > 0 && component_ids == nullptr) {
return heif_error_null_pointer_argument;
}
@@ -145,7 +162,7 @@ heif_error heif_image_add_polarization_pattern(heif_image* image,
}
PolarizationPattern pattern;
- pattern.component_indices.assign(component_indices, component_indices + num_component_indices);
+ pattern.component_ids.assign(component_ids, component_ids + num_component_ids);
pattern.pattern_width = pattern_width;
pattern.pattern_height = pattern_height;
@@ -170,7 +187,7 @@ int heif_image_get_number_of_polarization_patterns(const heif_image* image)
heif_error heif_image_get_polarization_pattern_info(const heif_image* image,
int pattern_index,
- uint32_t* out_num_component_indices,
+ uint32_t* out_num_component_ids,
uint16_t* out_pattern_width,
uint16_t* out_pattern_height)
{
@@ -186,8 +203,8 @@ heif_error heif_image_get_polarization_pattern_info(const heif_image* image,
}
const auto& p = patterns[pattern_index];
- if (out_num_component_indices) {
- *out_num_component_indices = static_cast<uint32_t>(p.component_indices.size());
+ if (out_num_component_ids) {
+ *out_num_component_ids = static_cast<uint32_t>(p.component_ids.size());
}
if (out_pattern_width) {
*out_pattern_width = p.pattern_width;
@@ -202,7 +219,7 @@ heif_error heif_image_get_polarization_pattern_info(const heif_image* image,
heif_error heif_image_get_polarization_pattern_data(const heif_image* image,
int pattern_index,
- uint32_t* out_component_indices,
+ uint32_t* out_component_ids,
float* out_polarization_angles)
{
if (image == nullptr || out_polarization_angles == nullptr) {
@@ -218,8 +235,8 @@ heif_error heif_image_get_polarization_pattern_data(const heif_image* image,
const auto& p = patterns[pattern_index];
- if (out_component_indices && !p.component_indices.empty()) {
- std::copy(p.component_indices.begin(), p.component_indices.end(), out_component_indices);
+ if (out_component_ids && !p.component_ids.empty()) {
+ std::copy(p.component_ids.begin(), p.component_ids.end(), out_component_ids);
}
size_t num_pixels = size_t{p.pattern_width} * p.pattern_height;
@@ -230,7 +247,7 @@ heif_error heif_image_get_polarization_pattern_data(const heif_image* image,
int heif_image_get_polarization_pattern_index_for_component(const heif_image* image,
- uint32_t component_index)
+ uint32_t component_id)
{
if (image == nullptr) {
return -1;
@@ -239,12 +256,12 @@ int heif_image_get_polarization_pattern_index_for_component(const heif_image* im
const auto& patterns = image->image->get_polarization_patterns();
for (size_t i = 0; i < patterns.size(); i++) {
const auto& p = patterns[i];
- if (p.component_indices.empty()) {
+ if (p.component_ids.empty()) {
// Empty component list means pattern applies to all components.
return static_cast<int>(i);
}
- for (uint32_t idx : p.component_indices) {
- if (idx == component_index) {
+ for (uint32_t idx : p.component_ids) {
+ if (idx == component_id) {
return static_cast<int>(i);
}
}
@@ -255,8 +272,8 @@ int heif_image_get_polarization_pattern_index_for_component(const heif_image* im
heif_error heif_image_add_sensor_bad_pixels_map(heif_image* image,
- uint32_t num_component_indices,
- const uint32_t* component_indices,
+ uint32_t num_component_ids,
+ const uint32_t* component_ids,
int correction_applied,
uint32_t num_bad_rows,
const uint32_t* bad_rows,
@@ -269,7 +286,7 @@ heif_error heif_image_add_sensor_bad_pixels_map(heif_image* image,
return heif_error_null_pointer_argument;
}
- if (num_component_indices > 0 && component_indices == nullptr) {
+ if (num_component_ids > 0 && component_ids == nullptr) {
return heif_error_null_pointer_argument;
}
@@ -286,7 +303,7 @@ heif_error heif_image_add_sensor_bad_pixels_map(heif_image* image,
}
SensorBadPixelsMap map;
- map.component_indices.assign(component_indices, component_indices + num_component_indices);
+ map.component_ids.assign(component_ids, component_ids + num_component_ids);
map.correction_applied = (correction_applied != 0);
map.bad_rows.assign(bad_rows, bad_rows + num_bad_rows);
@@ -316,7 +333,7 @@ int heif_image_get_number_of_sensor_bad_pixels_maps(const heif_image* image)
heif_error heif_image_get_sensor_bad_pixels_map_info(const heif_image* image,
int map_index,
- uint32_t* out_num_component_indices,
+ uint32_t* out_num_component_ids,
int* out_correction_applied,
uint32_t* out_num_bad_rows,
uint32_t* out_num_bad_columns,
@@ -334,8 +351,8 @@ heif_error heif_image_get_sensor_bad_pixels_map_info(const heif_image* image,
}
const auto& m = maps[map_index];
- if (out_num_component_indices) {
- *out_num_component_indices = static_cast<uint32_t>(m.component_indices.size());
+ if (out_num_component_ids) {
+ *out_num_component_ids = static_cast<uint32_t>(m.component_ids.size());
}
if (out_correction_applied) {
*out_correction_applied = m.correction_applied ? 1 : 0;
@@ -356,7 +373,7 @@ heif_error heif_image_get_sensor_bad_pixels_map_info(const heif_image* image,
heif_error heif_image_get_sensor_bad_pixels_map_data(const heif_image* image,
int map_index,
- uint32_t* out_component_indices,
+ uint32_t* out_component_ids,
uint32_t* out_bad_rows,
uint32_t* out_bad_columns,
struct heif_bad_pixel* out_bad_pixels)
@@ -374,8 +391,8 @@ heif_error heif_image_get_sensor_bad_pixels_map_data(const heif_image* image,
const auto& m = maps[map_index];
- if (out_component_indices && !m.component_indices.empty()) {
- std::copy(m.component_indices.begin(), m.component_indices.end(), out_component_indices);
+ if (out_component_ids && !m.component_ids.empty()) {
+ std::copy(m.component_ids.begin(), m.component_ids.end(), out_component_ids);
}
if (out_bad_rows && !m.bad_rows.empty()) {
@@ -398,8 +415,8 @@ heif_error heif_image_get_sensor_bad_pixels_map_data(const heif_image* image,
heif_error heif_image_add_sensor_nuc(heif_image* image,
- uint32_t num_component_indices,
- const uint32_t* component_indices,
+ uint32_t num_component_ids,
+ const uint32_t* component_ids,
int nuc_is_applied,
uint32_t image_width,
uint32_t image_height,
@@ -410,7 +427,7 @@ heif_error heif_image_add_sensor_nuc(heif_image* image,
return heif_error_null_pointer_argument;
}
- if (num_component_indices > 0 && component_indices == nullptr) {
+ if (num_component_ids > 0 && component_ids == nullptr) {
return heif_error_null_pointer_argument;
}
@@ -421,7 +438,7 @@ heif_error heif_image_add_sensor_nuc(heif_image* image,
}
SensorNonUniformityCorrection nuc;
- nuc.component_indices.assign(component_indices, component_indices + num_component_indices);
+ nuc.component_ids.assign(component_ids, component_ids + num_component_ids);
nuc.nuc_is_applied = (nuc_is_applied != 0);
nuc.image_width = image_width;
nuc.image_height = image_height;
@@ -448,7 +465,7 @@ int heif_image_get_number_of_sensor_nucs(const heif_image* image)
heif_error heif_image_get_sensor_nuc_info(const heif_image* image,
int nuc_index,
- uint32_t* out_num_component_indices,
+ uint32_t* out_num_component_ids,
int* out_nuc_is_applied,
uint32_t* out_image_width,
uint32_t* out_image_height)
@@ -465,8 +482,8 @@ heif_error heif_image_get_sensor_nuc_info(const heif_image* image,
}
const auto& n = nucs[nuc_index];
- if (out_num_component_indices) {
- *out_num_component_indices = static_cast<uint32_t>(n.component_indices.size());
+ if (out_num_component_ids) {
+ *out_num_component_ids = static_cast<uint32_t>(n.component_ids.size());
}
if (out_nuc_is_applied) {
*out_nuc_is_applied = n.nuc_is_applied ? 1 : 0;
@@ -484,7 +501,7 @@ heif_error heif_image_get_sensor_nuc_info(const heif_image* image,
heif_error heif_image_get_sensor_nuc_data(const heif_image* image,
int nuc_index,
- uint32_t* out_component_indices,
+ uint32_t* out_component_ids,
float* out_nuc_gains,
float* out_nuc_offsets)
{
@@ -501,8 +518,8 @@ heif_error heif_image_get_sensor_nuc_data(const heif_image* image,
const auto& n = nucs[nuc_index];
- if (out_component_indices && !n.component_indices.empty()) {
- std::copy(n.component_indices.begin(), n.component_indices.end(), out_component_indices);
+ if (out_component_ids && !n.component_ids.empty()) {
+ std::copy(n.component_ids.begin(), n.component_ids.end(), out_component_ids);
}
size_t num_pixels = size_t{n.image_width} * n.image_height;
@@ -605,7 +622,7 @@ void heif_unci_image_parameters_release(heif_unci_image_parameters* params)
}
-// --- index-based component access
+// --- id-based component access
uint32_t heif_image_get_number_of_used_components(const heif_image* image)
{
@@ -616,24 +633,15 @@ uint32_t heif_image_get_number_of_used_components(const heif_image* image)
}
-uint32_t heif_image_get_total_number_of_cmpd_components(const heif_image* image)
-{
- if (!image || !image->image) {
- return 0;
- }
- return image->image->get_total_number_of_cmpd_components();
-}
-
-
-void heif_image_get_used_component_indices(const heif_image* image, uint32_t* out_component_indices)
+void heif_image_get_used_component_ids(const heif_image* image, uint32_t* out_component_ids)
{
- if (!image || !image->image || !out_component_indices) {
+ if (!image || !image->image || !out_component_ids) {
return;
}
- auto indices = image->image->get_used_component_indices();
+ auto indices = image->image->get_used_component_ids();
for (size_t i = 0; i < indices.size(); i++) {
- out_component_indices[i] = indices[i];
+ out_component_ids[i] = indices[i];
}
}
@@ -686,7 +694,7 @@ uint16_t heif_image_get_component_type(const heif_image* image, uint32_t compone
heif_error heif_image_add_component(heif_image* image,
int width, int height,
uint16_t component_type,
- heif_channel_datatype datatype,
+ heif_component_datatype datatype,
int bit_depth,
uint32_t* out_component_idx)
{
diff --git a/libheif/api/libheif/heif_uncompressed.h b/libheif/api/libheif/heif_uncompressed.h
index 966c5b59..a406ff26 100644
--- a/libheif/api/libheif/heif_uncompressed.h
+++ b/libheif/api/libheif/heif_uncompressed.h
@@ -46,24 +46,32 @@ extern "C" {
// On the decoder path, they come directly from the cpat box.
LIBHEIF_API
heif_error heif_image_set_bayer_pattern(heif_image*,
+ uint32_t bayer_component_id,
uint16_t pattern_width,
uint16_t pattern_height,
const heif_bayer_pattern_pixel* patternPixels);
+LIBHEIF_API
+heif_error heif_image_add_bayer_component(heif_image*,
+ uint16_t component_type,
+ uint32_t* out_component_id);
+
// Returns whether the image has a Bayer / filter array pattern.
// If the image has a pattern, out_pattern_width and out_pattern_height are set.
// Either output pointer may be NULL if the caller does not need that value.
LIBHEIF_API
-int heif_image_has_bayer_pattern(const heif_image*,
- uint16_t* out_pattern_width,
- uint16_t* out_pattern_height);
+int heif_image_get_bayer_pattern_size(const heif_image*,
+ uint32_t bayer_component_id,
+ uint16_t* out_pattern_width,
+ uint16_t* out_pattern_height);
// Get the Bayer / filter array pattern pixels.
// The caller must provide an array large enough for pattern_width * pattern_height entries
-// (use heif_image_has_bayer_pattern() to query the dimensions first).
+// (use heif_image_get_bayer_pattern_size() to query the dimensions first).
// Returns heif_error_Ok on success, or an error if no pattern is set.
LIBHEIF_API
heif_error heif_image_get_bayer_pattern(const heif_image*,
+ uint32_t bayer_component_id,
heif_bayer_pattern_pixel* out_patternPixels);
// --- Polarization pattern (ISO 23001-17, Section 6.1.5)
@@ -283,14 +291,10 @@ heif_error heif_context_add_empty_unci_image(heif_context* ctx,
LIBHEIF_API
uint32_t heif_image_get_number_of_used_components(const heif_image*);
-// Returns the total number of components declared in the cmpd box.
-LIBHEIF_API
-uint32_t heif_image_get_total_number_of_cmpd_components(const heif_image*);
-
// Fills `out_component_indices` with the valid component indices.
// The caller must allocate an array of at least heif_image_get_number_of_used_components() elements.
LIBHEIF_API
-void heif_image_get_used_component_indices(const heif_image*, uint32_t* out_component_indices);
+void heif_image_get_used_component_ids(const heif_image*, uint32_t* out_component_ids);
LIBHEIF_API
enum heif_channel heif_image_get_component_channel(const heif_image*, uint32_t component_idx);
@@ -315,7 +319,7 @@ LIBHEIF_API
heif_error heif_image_add_component(heif_image* image,
int width, int height,
uint16_t component_type,
- heif_channel_datatype datatype,
+ heif_component_datatype datatype,
int bit_depth,
uint32_t* out_component_idx);
diff --git a/libheif/api/libheif/heif_uncompressed_types.h b/libheif/api/libheif/heif_uncompressed_types.h
index 1a00dcc9..2366bf7d 100644
--- a/libheif/api/libheif/heif_uncompressed_types.h
+++ b/libheif/api/libheif/heif_uncompressed_types.h
@@ -29,33 +29,33 @@ extern "C" {
// --- ISO 23001-17 component types (Table 1)
-typedef enum heif_uncompressed_component_type
+typedef enum heif_unci_component_type
{
- heif_uncompressed_component_type_monochrome = 0,
- heif_uncompressed_component_type_Y = 1,
- heif_uncompressed_component_type_Cb = 2,
- heif_uncompressed_component_type_Cr = 3,
- heif_uncompressed_component_type_red = 4,
- heif_uncompressed_component_type_green = 5,
- heif_uncompressed_component_type_blue = 6,
- heif_uncompressed_component_type_alpha = 7,
- heif_uncompressed_component_type_depth = 8,
- heif_uncompressed_component_type_disparity = 9,
- heif_uncompressed_component_type_palette = 10,
- heif_uncompressed_component_type_filter_array = 11,
- heif_uncompressed_component_type_padded = 12,
- heif_uncompressed_component_type_cyan = 13,
- heif_uncompressed_component_type_magenta = 14,
- heif_uncompressed_component_type_yellow = 15,
- heif_uncompressed_component_type_key_black = 16
-} heif_uncompressed_component_type;
+ heif_unci_component_type_monochrome = 0,
+ heif_unci_component_type_Y = 1,
+ heif_unci_component_type_Cb = 2,
+ heif_unci_component_type_Cr = 3,
+ heif_unci_component_type_red = 4,
+ heif_unci_component_type_green = 5,
+ heif_unci_component_type_blue = 6,
+ heif_unci_component_type_alpha = 7,
+ heif_unci_component_type_depth = 8,
+ heif_unci_component_type_disparity = 9,
+ heif_unci_component_type_palette = 10,
+ heif_unci_component_type_filter_array = 11,
+ heif_unci_component_type_padded = 12,
+ heif_unci_component_type_cyan = 13,
+ heif_unci_component_type_magenta = 14,
+ heif_unci_component_type_yellow = 15,
+ heif_unci_component_type_key_black = 16
+} heif_unci_component_type;
// --- Bayer / filter array pattern
typedef struct heif_bayer_pattern_pixel
{
- uint16_t component_index; // index into the component definition (cmpd)
+ uint32_t component_id;
float component_gain;
} heif_bayer_pattern_pixel;
@@ -117,14 +117,14 @@ typedef struct heif_unci_image_parameters
// --- pixel datatype support
-typedef enum heif_channel_datatype
+typedef enum heif_component_datatype
{
- heif_channel_datatype_undefined = 0,
- heif_channel_datatype_unsigned_integer = 1,
- heif_channel_datatype_signed_integer = 2,
- heif_channel_datatype_floating_point = 3,
- heif_channel_datatype_complex_number = 4
-} heif_channel_datatype;
+ heif_component_datatype_undefined = 0,
+ heif_component_datatype_unsigned_integer = 1,
+ heif_component_datatype_signed_integer = 2,
+ heif_component_datatype_floating_point = 3,
+ heif_component_datatype_complex_number = 4
+} heif_component_datatype;
typedef struct heif_complex32
{
diff --git a/libheif/codecs/uncompressed/unc_boxes.cc b/libheif/codecs/uncompressed/unc_boxes.cc
index 075ff1a3..b89fde98 100644
--- a/libheif/codecs/uncompressed/unc_boxes.cc
+++ b/libheif/codecs/uncompressed/unc_boxes.cc
@@ -96,27 +96,27 @@ bool is_predefined_component_type(uint16_t type)
{
// check whether the component type can be mapped to heif_uncompressed_component_type and we have a name defined for
// it in sNames_uncompressed_component_type.
- return type <= heif_uncompressed_component_type_max_valid;
+ return type <= heif_unci_component_type_max_valid;
}
-static std::map<heif_uncompressed_component_type, const char*> sNames_uncompressed_component_type{
- {heif_uncompressed_component_type_monochrome, "monochrome"},
- {heif_uncompressed_component_type_Y, "Y"},
- {heif_uncompressed_component_type_Cb, "Cb"},
- {heif_uncompressed_component_type_Cr, "Cr"},
- {heif_uncompressed_component_type_red, "red"},
- {heif_uncompressed_component_type_green, "green"},
- {heif_uncompressed_component_type_blue, "blue"},
- {heif_uncompressed_component_type_alpha, "alpha"},
- {heif_uncompressed_component_type_depth, "depth"},
- {heif_uncompressed_component_type_disparity, "disparity"},
- {heif_uncompressed_component_type_palette, "palette"},
- {heif_uncompressed_component_type_filter_array, "filter-array"},
- {heif_uncompressed_component_type_padded, "padded"},
- {heif_uncompressed_component_type_cyan, "cyan"},
- {heif_uncompressed_component_type_magenta, "magenta"},
- {heif_uncompressed_component_type_yellow, "yellow"},
- {heif_uncompressed_component_type_key_black, "key (black)"}
+static std::map<heif_unci_component_type, const char*> sNames_uncompressed_component_type{
+ {heif_unci_component_type_monochrome, "monochrome"},
+ {heif_unci_component_type_Y, "Y"},
+ {heif_unci_component_type_Cb, "Cb"},
+ {heif_unci_component_type_Cr, "Cr"},
+ {heif_unci_component_type_red, "red"},
+ {heif_unci_component_type_green, "green"},
+ {heif_unci_component_type_blue, "blue"},
+ {heif_unci_component_type_alpha, "alpha"},
+ {heif_unci_component_type_depth, "depth"},
+ {heif_unci_component_type_disparity, "disparity"},
+ {heif_unci_component_type_palette, "palette"},
+ {heif_unci_component_type_filter_array, "filter-array"},
+ {heif_unci_component_type_padded, "padded"},
+ {heif_unci_component_type_cyan, "cyan"},
+ {heif_unci_component_type_magenta, "magenta"},
+ {heif_unci_component_type_yellow, "yellow"},
+ {heif_unci_component_type_key_black, "key (black)"}
};
template <typename T> const char* get_name(T val, const std::map<T, const char*>& table)
@@ -186,7 +186,7 @@ std::string Box_cmpd::Component::get_component_type_name(uint16_t component_type
std::stringstream sstr;
if (is_predefined_component_type(component_type)) {
- sstr << get_name(heif_uncompressed_component_type(component_type), sNames_uncompressed_component_type) << "\n";
+ sstr << get_name(heif_unci_component_type(component_type), sNames_uncompressed_component_type) << "\n";
}
else {
sstr << "0x" << std::hex << component_type << std::dec << "\n";
@@ -196,7 +196,7 @@ std::string Box_cmpd::Component::get_component_type_name(uint16_t component_type
}
-bool Box_cmpd::has_component(heif_uncompressed_component_type type) const
+bool Box_cmpd::has_component(heif_unci_component_type type) const
{
return std::any_of(m_components.begin(), m_components.end(),
[type](const auto& cmp) { return cmp.component_type == type; });
@@ -457,9 +457,9 @@ void fill_uncC_and_cmpd_from_profile(const std::shared_ptr<Box_uncC>& uncC,
uncC->add_component({0, 8, component_format_unsigned, 0});
uncC->add_component({1, 8, component_format_unsigned, 0});
uncC->add_component({2, 8, component_format_unsigned, 0});
- cmpd->add_component({heif_uncompressed_component_type_red});
- cmpd->add_component({heif_uncompressed_component_type_green});
- cmpd->add_component({heif_uncompressed_component_type_blue});
+ cmpd->add_component({heif_unci_component_type_red});
+ cmpd->add_component({heif_unci_component_type_green});
+ cmpd->add_component({heif_unci_component_type_blue});
uncC->set_sampling_type(sampling_mode_no_subsampling);
uncC->set_interleave_type(interleave_mode_pixel);
}
@@ -469,10 +469,10 @@ void fill_uncC_and_cmpd_from_profile(const std::shared_ptr<Box_uncC>& uncC,
uncC->add_component({1, 8, component_format_unsigned, 0});
uncC->add_component({2, 8, component_format_unsigned, 0});
uncC->add_component({3, 8, component_format_unsigned, 0});
- cmpd->add_component({heif_uncompressed_component_type_red});
- cmpd->add_component({heif_uncompressed_component_type_green});
- cmpd->add_component({heif_uncompressed_component_type_blue});
- cmpd->add_component({heif_uncompressed_component_type_alpha});
+ cmpd->add_component({heif_unci_component_type_red});
+ cmpd->add_component({heif_unci_component_type_green});
+ cmpd->add_component({heif_unci_component_type_blue});
+ cmpd->add_component({heif_unci_component_type_alpha});
uncC->set_sampling_type(sampling_mode_no_subsampling);
uncC->set_interleave_type(interleave_mode_pixel);
}
@@ -482,10 +482,10 @@ void fill_uncC_and_cmpd_from_profile(const std::shared_ptr<Box_uncC>& uncC,
uncC->add_component({1, 8, component_format_unsigned, 0});
uncC->add_component({2, 8, component_format_unsigned, 0});
uncC->add_component({3, 8, component_format_unsigned, 0});
- cmpd->add_component({heif_uncompressed_component_type_alpha});
- cmpd->add_component({heif_uncompressed_component_type_blue});
- cmpd->add_component({heif_uncompressed_component_type_green});
- cmpd->add_component({heif_uncompressed_component_type_red});
+ cmpd->add_component({heif_unci_component_type_alpha});
+ cmpd->add_component({heif_unci_component_type_blue});
+ cmpd->add_component({heif_unci_component_type_green});
+ cmpd->add_component({heif_unci_component_type_red});
uncC->set_sampling_type(sampling_mode_no_subsampling);
uncC->set_interleave_type(interleave_mode_pixel);
}
@@ -496,9 +496,9 @@ void fill_uncC_and_cmpd_from_profile(const std::shared_ptr<Box_uncC>& uncC,
uncC->add_component({1, 8, component_format_unsigned, 0});
uncC->add_component({2, 8, component_format_unsigned, 0});
uncC->add_component({1, 8, component_format_unsigned, 0});
- cmpd->add_component({heif_uncompressed_component_type_Cb});
- cmpd->add_component({heif_uncompressed_component_type_Y});
- cmpd->add_component({heif_uncompressed_component_type_Cr});
+ cmpd->add_component({heif_unci_component_type_Cb});
+ cmpd->add_component({heif_unci_component_type_Y});
+ cmpd->add_component({heif_unci_component_type_Cr});
uncC->set_sampling_type(sampling_mode_422);
uncC->set_interleave_type(interleave_mode_multi_y);
}
@@ -509,9 +509,9 @@ void fill_uncC_and_cmpd_from_profile(const std::shared_ptr<Box_uncC>& uncC,
uncC->add_component({1, 8, component_format_unsigned, 0});
uncC->add_component({0, 8, component_format_unsigned, 0});
uncC->add_component({2, 8, component_format_unsigned, 0});
- cmpd->add_component({heif_uncompressed_component_type_Y});
- cmpd->add_component({heif_uncompressed_component_type_Cb});
- cmpd->add_component({heif_uncompressed_component_type_Cr});
+ cmpd->add_component({heif_unci_component_type_Y});
+ cmpd->add_component({heif_unci_component_type_Cb});
+ cmpd->add_component({heif_unci_component_type_Cr});
uncC->set_sampling_type(sampling_mode_422);
uncC->set_interleave_type(interleave_mode_multi_y);
}
@@ -522,9 +522,9 @@ void fill_uncC_and_cmpd_from_profile(const std::shared_ptr<Box_uncC>& uncC,
uncC->add_component({1, 8, component_format_unsigned, 0});
uncC->add_component({0, 8, component_format_unsigned, 0});
uncC->add_component({2, 8, component_format_unsigned, 0});
- cmpd->add_component({heif_uncompressed_component_type_Y});
- cmpd->add_component({heif_uncompressed_component_type_Cr});
- cmpd->add_component({heif_uncompressed_component_type_Cb});
+ cmpd->add_component({heif_unci_component_type_Y});
+ cmpd->add_component({heif_unci_component_type_Cr});
+ cmpd->add_component({heif_unci_component_type_Cb});
uncC->set_sampling_type(sampling_mode_422);
uncC->set_interleave_type(interleave_mode_multi_y);
}
@@ -535,9 +535,9 @@ void fill_uncC_and_cmpd_from_profile(const std::shared_ptr<Box_uncC>& uncC,
uncC->add_component({1, 8, component_format_unsigned, 0});
uncC->add_component({2, 8, component_format_unsigned, 0});
uncC->add_component({1, 8, component_format_unsigned, 0});
- cmpd->add_component({heif_uncompressed_component_type_Cr});
- cmpd->add_component({heif_uncompressed_component_type_Y});
- cmpd->add_component({heif_uncompressed_component_type_Cb});
+ cmpd->add_component({heif_unci_component_type_Cr});
+ cmpd->add_component({heif_unci_component_type_Y});
+ cmpd->add_component({heif_unci_component_type_Cb});
uncC->set_sampling_type(sampling_mode_422);
uncC->set_interleave_type(interleave_mode_multi_y);
}
@@ -550,9 +550,9 @@ void fill_uncC_and_cmpd_from_profile(const std::shared_ptr<Box_uncC>& uncC,
uncC->add_component({0, 8, component_format_unsigned, 0});
uncC->add_component({0, 8, component_format_unsigned, 0});
uncC->add_component({2, 8, component_format_unsigned, 0});
- cmpd->add_component({heif_uncompressed_component_type_Y});
- cmpd->add_component({heif_uncompressed_component_type_Cb});
- cmpd->add_component({heif_uncompressed_component_type_Cr});
+ cmpd->add_component({heif_unci_component_type_Y});
+ cmpd->add_component({heif_unci_component_type_Cb});
+ cmpd->add_component({heif_unci_component_type_Cr});
uncC->set_sampling_type(sampling_mode_411);
uncC->set_interleave_type(interleave_mode_multi_y);
}
@@ -562,9 +562,9 @@ void fill_uncC_and_cmpd_from_profile(const std::shared_ptr<Box_uncC>& uncC,
uncC->add_component({0, 8, component_format_unsigned, 0});
uncC->add_component({1, 8, component_format_unsigned, 0});
uncC->add_component({2, 8, component_format_unsigned, 0});
- cmpd->add_component({heif_uncompressed_component_type_Cr});
- cmpd->add_component({heif_uncompressed_component_type_Y});
- cmpd->add_component({heif_uncompressed_component_type_Cb});
+ cmpd->add_component({heif_unci_component_type_Cr});
+ cmpd->add_component({heif_unci_component_type_Y});
+ cmpd->add_component({heif_unci_component_type_Cb});
uncC->set_sampling_type(sampling_mode_no_subsampling);
uncC->set_interleave_type(interleave_mode_pixel);
}
@@ -575,10 +575,10 @@ void fill_uncC_and_cmpd_from_profile(const std::shared_ptr<Box_uncC>& uncC,
uncC->add_component({1, 8, component_format_unsigned, 0});
uncC->add_component({2, 8, component_format_unsigned, 0});
uncC->add_component({3, 8, component_format_unsigned, 0});
- cmpd->add_component({heif_uncompressed_component_type_Cb});
- cmpd->add_component({heif_uncompressed_component_type_Y});
- cmpd->add_component({heif_uncompressed_component_type_Cr});
- cmpd->add_component({heif_uncompressed_component_type_alpha});
+ cmpd->add_component({heif_unci_component_type_Cb});
+ cmpd->add_component({heif_unci_component_type_Y});
+ cmpd->add_component({heif_unci_component_type_Cr});
+ cmpd->add_component({heif_unci_component_type_alpha});
uncC->set_sampling_type(sampling_mode_no_subsampling);
uncC->set_interleave_type(interleave_mode_pixel);
}
@@ -590,9 +590,9 @@ void fill_uncC_and_cmpd_from_profile(const std::shared_ptr<Box_uncC>& uncC,
uncC->add_component({1, 10, component_format_unsigned, 0});
uncC->add_component({0, 10, component_format_unsigned, 0});
uncC->add_component({2, 10, component_format_unsigned, 0});
- cmpd->add_component({heif_uncompressed_component_type_Y});
- cmpd->add_component({heif_uncompressed_component_type_Cb});
- cmpd->add_component({heif_uncompressed_component_type_Cr});
+ cmpd->add_component({heif_unci_component_type_Y});
+ cmpd->add_component({heif_unci_component_type_Cb});
+ cmpd->add_component({heif_unci_component_type_Cr});
uncC->set_sampling_type(sampling_mode_422);
uncC->set_interleave_type(interleave_mode_multi_y);
uncC->set_block_size(2);
@@ -606,9 +606,9 @@ void fill_uncC_and_cmpd_from_profile(const std::shared_ptr<Box_uncC>& uncC,
uncC->add_component({0, 10, component_format_unsigned, 0});
uncC->add_component({1, 10, component_format_unsigned, 0});
uncC->add_component({2, 10, component_format_unsigned, 0});
- cmpd->add_component({heif_uncompressed_component_type_Cb});
- cmpd->add_component({heif_uncompressed_component_type_Y});
- cmpd->add_component({heif_uncompressed_component_type_Cr});
+ cmpd->add_component({heif_unci_component_type_Cb});
+ cmpd->add_component({heif_unci_component_type_Y});
+ cmpd->add_component({heif_unci_component_type_Cr});
uncC->set_sampling_type(sampling_mode_no_subsampling);
uncC->set_interleave_type(interleave_mode_pixel);
uncC->set_block_size(4);
@@ -624,9 +624,9 @@ void fill_uncC_and_cmpd_from_profile(const std::shared_ptr<Box_uncC>& uncC,
uncC->add_component({1, 10, component_format_unsigned, 0});
uncC->add_component({2, 10, component_format_unsigned, 0});
uncC->add_component({1, 10, component_format_unsigned, 0});
- cmpd->add_component({heif_uncompressed_component_type_Cb});
- cmpd->add_component({heif_uncompressed_component_type_Y});
- cmpd->add_component({heif_uncompressed_component_type_Cr});
+ cmpd->add_component({heif_unci_component_type_Cb});
+ cmpd->add_component({heif_unci_component_type_Y});
+ cmpd->add_component({heif_unci_component_type_Cr});
uncC->set_sampling_type(sampling_mode_422);
uncC->set_interleave_type(interleave_mode_multi_y);
uncC->set_block_size(4);
@@ -639,9 +639,9 @@ void fill_uncC_and_cmpd_from_profile(const std::shared_ptr<Box_uncC>& uncC,
uncC->add_component({0, 8, component_format_unsigned, 0});
uncC->add_component({1, 8, component_format_unsigned, 0});
uncC->add_component({2, 8, component_format_unsigned, 0});
- cmpd->add_component({heif_uncompressed_component_type_Y});
- cmpd->add_component({heif_uncompressed_component_type_Cb});
- cmpd->add_component({heif_uncompressed_component_type_Cr});
+ cmpd->add_component({heif_unci_component_type_Y});
+ cmpd->add_component({heif_unci_component_type_Cb});
+ cmpd->add_component({heif_unci_component_type_Cr});
uncC->set_sampling_type(sampling_mode_420);
uncC->set_interleave_type(interleave_mode_component);
}
@@ -651,9 +651,9 @@ void fill_uncC_and_cmpd_from_profile(const std::shared_ptr<Box_uncC>& uncC,
uncC->add_component({0, 8, component_format_unsigned, 0});
uncC->add_component({1, 8, component_format_unsigned, 0});
uncC->add_component({2, 8, component_format_unsigned, 0});
- cmpd->add_component({heif_uncompressed_component_type_Y});
- cmpd->add_component({heif_uncompressed_component_type_Cb});
- cmpd->add_component({heif_uncompressed_component_type_Cr});
+ cmpd->add_component({heif_unci_component_type_Y});
+ cmpd->add_component({heif_unci_component_type_Cb});
+ cmpd->add_component({heif_unci_component_type_Cr});
uncC->set_sampling_type(sampling_mode_420);
uncC->set_interleave_type(interleave_mode_mixed);
}
@@ -663,9 +663,9 @@ void fill_uncC_and_cmpd_from_profile(const std::shared_ptr<Box_uncC>& uncC,
uncC->add_component({0, 8, component_format_unsigned, 0});
uncC->add_component({1, 8, component_format_unsigned, 0});
uncC->add_component({2, 8, component_format_unsigned, 0});
- cmpd->add_component({heif_uncompressed_component_type_Y});
- cmpd->add_component({heif_uncompressed_component_type_Cr});
- cmpd->add_component({heif_uncompressed_component_type_Cb});
+ cmpd->add_component({heif_unci_component_type_Y});
+ cmpd->add_component({heif_unci_component_type_Cr});
+ cmpd->add_component({heif_unci_component_type_Cb});
uncC->set_sampling_type(sampling_mode_420);
uncC->set_interleave_type(interleave_mode_mixed);
}
@@ -675,9 +675,9 @@ void fill_uncC_and_cmpd_from_profile(const std::shared_ptr<Box_uncC>& uncC,
uncC->add_component({0, 8, component_format_unsigned, 0});
uncC->add_component({1, 8, component_format_unsigned, 0});
uncC->add_component({2, 8, component_format_unsigned, 0});
- cmpd->add_component({heif_uncompressed_component_type_Y});
- cmpd->add_component({heif_uncompressed_component_type_Cb});
- cmpd->add_component({heif_uncompressed_component_type_Cr});
+ cmpd->add_component({heif_unci_component_type_Y});
+ cmpd->add_component({heif_unci_component_type_Cb});
+ cmpd->add_component({heif_unci_component_type_Cr});
uncC->set_sampling_type(sampling_mode_422);
uncC->set_interleave_type(interleave_mode_component);
}
@@ -687,9 +687,9 @@ void fill_uncC_and_cmpd_from_profile(const std::shared_ptr<Box_uncC>& uncC,
uncC->add_component({0, 8, component_format_unsigned, 0});
uncC->add_component({1, 8, component_format_unsigned, 0});
uncC->add_component({2, 8, component_format_unsigned, 0});
- cmpd->add_component({heif_uncompressed_component_type_Y});
- cmpd->add_component({heif_uncompressed_component_type_Cr});
- cmpd->add_component({heif_uncompressed_component_type_Cb});
+ cmpd->add_component({heif_unci_component_type_Y});
+ cmpd->add_component({heif_unci_component_type_Cr});
+ cmpd->add_component({heif_unci_component_type_Cb});
uncC->set_sampling_type(sampling_mode_422);
uncC->set_interleave_type(interleave_mode_component);
}
@@ -699,9 +699,9 @@ void fill_uncC_and_cmpd_from_profile(const std::shared_ptr<Box_uncC>& uncC,
uncC->add_component({0, 8, component_format_unsigned, 0});
uncC->add_component({1, 8, component_format_unsigned, 0});
uncC->add_component({2, 8, component_format_unsigned, 0});
- cmpd->add_component({heif_uncompressed_component_type_Y});
- cmpd->add_component({heif_uncompressed_component_type_Cr});
- cmpd->add_component({heif_uncompressed_component_type_Cb});
+ cmpd->add_component({heif_unci_component_type_Y});
+ cmpd->add_component({heif_unci_component_type_Cr});
+ cmpd->add_component({heif_unci_component_type_Cb});
uncC->set_sampling_type(sampling_mode_420);
uncC->set_interleave_type(interleave_mode_component);
}
@@ -989,8 +989,8 @@ Error Box_cpat::parse(BitstreamRange& range, const heif_security_limits* limits)
m_pattern.pixels.resize(num_pixels);
for (size_t i = 0; i < num_pixels; i++) {
- heif_bayer_pattern_pixel pixel{};
- pixel.component_index = static_cast<uint16_t>(range.read32());
+ bayer_pattern_pixel_cmpd pixel{};
+ pixel.cmpd_index = range.read32();
pixel.component_gain = range.read_float32();
m_pattern.pixels[i] = pixel;
}
@@ -1008,7 +1008,7 @@ std::string Box_cpat::dump(Indent& indent) const
sstr << indent << "pattern_height: " << get_pattern_height() << "\n";
for (const auto& pixel : m_pattern.pixels) {
- sstr << indent << "component index: " << pixel.component_index << ", gain: " << pixel.component_gain << "\n";
+ sstr << indent << "component index: " << pixel.cmpd_index << ", gain: " << pixel.component_gain << "\n";
}
return sstr.str();
}
@@ -1028,7 +1028,7 @@ Error Box_cpat::write(StreamWriter& writer) const
writer.write16(m_pattern.pattern_height);
for (const auto& pixel : m_pattern.pixels) {
- writer.write32(pixel.component_index);
+ writer.write32(pixel.cmpd_index);
writer.write_float32(pixel.component_gain);
}
@@ -1053,9 +1053,9 @@ Error Box_splz::parse(BitstreamRange& range, const heif_security_limits* limits)
"Number of components in splz box exceeds the security limits."};
}
- m_pattern.component_indices.resize(component_count);
+ m_pattern.component_ids.resize(component_count);
for (uint32_t i = 0; i < component_count; i++) {
- m_pattern.component_indices[i] = range.read32();
+ m_pattern.component_ids[i] = range.read32();
}
m_pattern.pattern_width = range.read16();
@@ -1091,9 +1091,9 @@ std::string Box_splz::dump(Indent& indent) const
sstr << FullBox::dump(indent);
- sstr << indent << "component_count: " << m_pattern.component_indices.size() << "\n";
- for (size_t i = 0; i < m_pattern.component_indices.size(); i++) {
- sstr << indent << " component_index[" << i << "]: " << m_pattern.component_indices[i] << "\n";
+ sstr << indent << "component_count: " << m_pattern.component_ids.size() << "\n";
+ for (size_t i = 0; i < m_pattern.component_ids.size(); i++) {
+ sstr << indent << " component_index[" << i << "]: " << m_pattern.component_ids[i] << "\n";
}
sstr << indent << "pattern_width: " << m_pattern.pattern_width << "\n";
@@ -1125,8 +1125,8 @@ Error Box_splz::write(StreamWriter& writer) const
"incorrect number of polarization pattern angles"};
}
- writer.write32(static_cast<uint32_t>(m_pattern.component_indices.size()));
- for (uint32_t idx : m_pattern.component_indices) {
+ writer.write32(static_cast<uint32_t>(m_pattern.component_ids.size()));
+ for (uint32_t idx : m_pattern.component_ids) {
writer.write32(idx);
}
@@ -1159,9 +1159,9 @@ Error Box_sbpm::parse(BitstreamRange& range, const heif_security_limits* limits)
"sbpm component_count exceeds security limit."};
}
- m_map.component_indices.resize(component_count);
+ m_map.component_ids.resize(component_count);
for (uint32_t i = 0; i < component_count; i++) {
- m_map.component_indices[i] = range.read32();
+ m_map.component_ids[i] = range.read32();
}
uint8_t flags = range.read8();
@@ -1205,9 +1205,9 @@ std::string Box_sbpm::dump(Indent& indent) const
sstr << FullBox::dump(indent);
- sstr << indent << "component_count: " << m_map.component_indices.size() << "\n";
- for (size_t i = 0; i < m_map.component_indices.size(); i++) {
- sstr << indent << " component_index[" << i << "]: " << m_map.component_indices[i] << "\n";
+ sstr << indent << "component_count: " << m_map.component_ids.size() << "\n";
+ for (size_t i = 0; i < m_map.component_ids.size(); i++) {
+ sstr << indent << " component_index[" << i << "]: " << m_map.component_ids[i] << "\n";
}
sstr << indent << "correction_applied: " << m_map.correction_applied << "\n";
@@ -1236,8 +1236,8 @@ Error Box_sbpm::write(StreamWriter& writer) const
{
size_t box_start = reserve_box_header_space(writer);
- writer.write32(static_cast<uint32_t>(m_map.component_indices.size()));
- for (uint32_t idx : m_map.component_indices) {
+ writer.write32(static_cast<uint32_t>(m_map.component_ids.size()));
+ for (uint32_t idx : m_map.component_ids) {
writer.write32(idx);
}
@@ -1283,9 +1283,9 @@ Error Box_snuc::parse(BitstreamRange& range, const heif_security_limits* limits)
"snuc component_count exceeds security limit."};
}
- m_nuc.component_indices.resize(component_count);
+ m_nuc.component_ids.resize(component_count);
for (uint32_t i = 0; i < component_count; i++) {
- m_nuc.component_indices[i] = range.read32();
+ m_nuc.component_ids[i] = range.read32();
}
uint8_t flags = range.read8();
@@ -1340,9 +1340,9 @@ std::string Box_snuc::dump(Indent& indent) const
sstr << FullBox::dump(indent);
- sstr << indent << "component_count: " << m_nuc.component_indices.size() << "\n";
- for (size_t i = 0; i < m_nuc.component_indices.size(); i++) {
- sstr << indent << " component_index[" << i << "]: " << m_nuc.component_indices[i] << "\n";
+ sstr << indent << "component_count: " << m_nuc.component_ids.size() << "\n";
+ for (size_t i = 0; i < m_nuc.component_ids.size(); i++) {
+ sstr << indent << " component_index[" << i << "]: " << m_nuc.component_ids[i] << "\n";
}
sstr << indent << "nuc_is_applied: " << m_nuc.nuc_is_applied << "\n";
@@ -1361,8 +1361,8 @@ Error Box_snuc::write(StreamWriter& writer) const
{
size_t box_start = reserve_box_header_space(writer);
- writer.write32(static_cast<uint32_t>(m_nuc.component_indices.size()));
- for (uint32_t idx : m_nuc.component_indices) {
+ writer.write32(static_cast<uint32_t>(m_nuc.component_ids.size()));
+ for (uint32_t idx : m_nuc.component_ids) {
writer.write32(idx);
}
diff --git a/libheif/codecs/uncompressed/unc_boxes.h b/libheif/codecs/uncompressed/unc_boxes.h
index 1ce7ef48..36685159 100644
--- a/libheif/codecs/uncompressed/unc_boxes.h
+++ b/libheif/codecs/uncompressed/unc_boxes.h
@@ -64,7 +64,7 @@ public:
const std::vector<Component>& get_components() const { return m_components; }
- bool has_component(heif_uncompressed_component_type) const;
+ bool has_component(heif_unci_component_type) const;
uint16_t add_component(const Component& component)
{
@@ -363,9 +363,9 @@ public:
uint16_t get_pattern_height() const { return m_pattern.pattern_height; }
- const BayerPattern& get_pattern() const { return m_pattern; }
+ const BayerPatternCmpd& get_pattern() const { return m_pattern; }
- void set_pattern(const BayerPattern& pattern) { m_pattern = pattern; }
+ void set_pattern(const BayerPatternCmpd& pattern) { m_pattern = pattern; }
std::string dump(Indent&) const override;
@@ -374,7 +374,7 @@ public:
protected:
Error parse(BitstreamRange& range, const heif_security_limits* limits) override;
- BayerPattern m_pattern;
+ BayerPatternCmpd m_pattern;
};
diff --git a/libheif/codecs/uncompressed/unc_codec.cc b/libheif/codecs/uncompressed/unc_codec.cc
index 741d78ad..cddb2681 100644
--- a/libheif/codecs/uncompressed/unc_codec.cc
+++ b/libheif/codecs/uncompressed/unc_codec.cc
@@ -88,27 +88,27 @@ Error UncompressedImageCodec::get_heif_chroma_uncompressed(const std::shared_ptr
uint32_t component_index = component.component_index;
uint16_t component_type = cmpd->get_components()[component_index].component_type;
- if (component_type > heif_uncompressed_component_type_max_valid) {
+ if (component_type > heif_unci_component_type_max_valid) {
std::stringstream sstr;
- sstr << "a component_type > " << heif_uncompressed_component_type_max_valid << " is not supported";
+ sstr << "a component_type > " << heif_unci_component_type_max_valid << " is not supported";
return {heif_error_Unsupported_feature, heif_suberror_Invalid_parameter_value, sstr.str()};
}
- if (component_type == heif_uncompressed_component_type_padded) {
+ if (component_type == heif_unci_component_type_padded) {
// not relevant for determining chroma
continue;
}
componentSet |= (1 << component_type);
}
- *out_has_alpha = (componentSet & (1 << heif_uncompressed_component_type_alpha)) != 0;
+ *out_has_alpha = (componentSet & (1 << heif_unci_component_type_alpha)) != 0;
- if (componentSet == ((1 << heif_uncompressed_component_type_red) | (1 << heif_uncompressed_component_type_green) | (1 << heif_uncompressed_component_type_blue)) ||
- componentSet == ((1 << heif_uncompressed_component_type_red) | (1 << heif_uncompressed_component_type_green) | (1 << heif_uncompressed_component_type_blue) | (1 << heif_uncompressed_component_type_alpha))) {
+ if (componentSet == ((1 << heif_unci_component_type_red) | (1 << heif_unci_component_type_green) | (1 << heif_unci_component_type_blue)) ||
+ componentSet == ((1 << heif_unci_component_type_red) | (1 << heif_unci_component_type_green) | (1 << heif_unci_component_type_blue) | (1 << heif_unci_component_type_alpha))) {
*out_chroma = heif_chroma_444;
*out_colourspace = heif_colorspace_RGB;
}
- if (componentSet == ((1 << heif_uncompressed_component_type_Y) | (1 << heif_uncompressed_component_type_Cb) | (1 << heif_uncompressed_component_type_Cr))) {
+ if (componentSet == ((1 << heif_unci_component_type_Y) | (1 << heif_unci_component_type_Cb) | (1 << heif_unci_component_type_Cr))) {
switch (uncC->get_sampling_type()) {
case sampling_mode_no_subsampling:
*out_chroma = heif_chroma_444;
@@ -123,14 +123,14 @@ Error UncompressedImageCodec::get_heif_chroma_uncompressed(const std::shared_ptr
*out_colourspace = heif_colorspace_YCbCr;
}
- if (componentSet == (1 << heif_uncompressed_component_type_monochrome) || componentSet == ((1 << heif_uncompressed_component_type_monochrome) | (1 << heif_uncompressed_component_type_alpha)) ||
- componentSet == (1 << heif_uncompressed_component_type_Y) || componentSet == ((1 << heif_uncompressed_component_type_Y) | (1 << heif_uncompressed_component_type_alpha))) {
+ if (componentSet == (1 << heif_unci_component_type_monochrome) || componentSet == ((1 << heif_unci_component_type_monochrome) | (1 << heif_unci_component_type_alpha)) ||
+ componentSet == (1 << heif_unci_component_type_Y) || componentSet == ((1 << heif_unci_component_type_Y) | (1 << heif_unci_component_type_alpha))) {
// mono or mono + alpha input, mono output.
*out_chroma = heif_chroma_monochrome;
*out_colourspace = heif_colorspace_monochrome;
}
- if (componentSet == (1 << heif_uncompressed_component_type_filter_array)) {
+ if (componentSet == (1 << heif_unci_component_type_filter_array)) {
// TODO - we should look up the components
*out_chroma = heif_chroma_monochrome;
*out_colourspace = heif_colorspace_filter_array;
@@ -165,33 +165,50 @@ bool map_uncompressed_component_to_channel(const std::shared_ptr<const Box_cmpd>
}
-heif_channel_datatype unc_component_format_to_datatype(uint8_t format)
+heif_component_datatype unc_component_format_to_datatype(uint8_t format)
{
switch (format) {
case component_format_unsigned:
- return heif_channel_datatype_unsigned_integer;
+ return heif_component_datatype_unsigned_integer;
case component_format_signed:
- return heif_channel_datatype_signed_integer;
+ return heif_component_datatype_signed_integer;
case component_format_float:
- return heif_channel_datatype_floating_point;
+ return heif_component_datatype_floating_point;
case component_format_complex:
- return heif_channel_datatype_complex_number;
+ return heif_component_datatype_complex_number;
default:
- return heif_channel_datatype_undefined;
+ return heif_component_datatype_undefined;
}
}
-Result<std::shared_ptr<HeifPixelImage>> UncompressedImageCodec::create_image(const std::shared_ptr<const Box_cmpd> cmpd,
- const std::shared_ptr<const Box_uncC> uncC,
+static Error validate_component_indices(const std::vector<uint32_t>& indices,
+ size_t cmpd_size,
+ const char* box_name)
+{
+ for (uint32_t idx : indices) {
+ if (idx >= cmpd_size) {
+ return {heif_error_Invalid_input,
+ heif_suberror_Invalid_parameter_value,
+ std::string(box_name) + " component index out of range of cmpd table"};
+ }
+ }
+ return Error::Ok;
+}
+
+
+Result<std::shared_ptr<HeifPixelImage>> UncompressedImageCodec::create_image(const unci_properties& properties,
uint32_t width,
uint32_t height,
const heif_security_limits* limits)
{
+ auto cmpd = properties.cmpd;
+ auto uncC = properties.uncC;
+
const auto& components = cmpd->get_components();
auto img = std::make_shared<HeifPixelImage>();
@@ -206,15 +223,10 @@ Result<std::shared_ptr<HeifPixelImage>> UncompressedImageCodec::create_image(con
colourspace,
chroma);
- // Populate the cmpd table on the image so add_component_for_index() can look up types.
- {
- std::vector<uint16_t> cmpd_types;
- cmpd_types.reserve(components.size());
- for (const auto& c : components) {
- cmpd_types.push_back(c.component_type);
- }
- img->set_cmpd_component_types(std::move(cmpd_types));
- }
+
+ // Remember which components reference which cmpd indices.
+ // There can be several component ids referencing the same cmpd index.
+ std::vector<std::vector<uint32_t>> cmpd_index_to_comp_ids(components.size());
for (Box_uncC::Component component : uncC->get_components()) {
if (component.component_index >= components.size()) {
@@ -227,31 +239,103 @@ Result<std::shared_ptr<HeifPixelImage>> UncompressedImageCodec::create_image(con
auto component_type = components[component.component_index].component_type;
- if ((component_type == heif_uncompressed_component_type_Cb) ||
- (component_type == heif_uncompressed_component_type_Cr)) {
- Result<uint32_t> result = img->add_component_for_index(component.component_index,
- (width / chroma_h_subsampling(chroma)),
- (height / chroma_v_subsampling(chroma)),
- unc_component_format_to_datatype(component.component_format),
- component.component_bit_depth,
- limits);
+ if ((component_type == heif_unci_component_type_Cb) ||
+ (component_type == heif_unci_component_type_Cr)) {
+ Result<uint32_t> result = img->add_component((width / chroma_h_subsampling(chroma)),
+ (height / chroma_v_subsampling(chroma)),
+ cmpd->get_components()[component.component_index].component_type,
+ unc_component_format_to_datatype(component.component_format),
+ component.component_bit_depth,
+ limits);
if (result.is_error()) {
return result.error();
}
+
+ cmpd_index_to_comp_ids[component.component_index].push_back(*result);
}
else {
- Result<uint32_t> result = img->add_component_for_index(component.component_index,
- width,
- height,
- unc_component_format_to_datatype(component.component_format),
- component.component_bit_depth,
- limits);
+ Result<uint32_t> result = img->add_component(width,
+ height,
+ cmpd->get_components()[component.component_index].component_type,
+ unc_component_format_to_datatype(component.component_format),
+ component.component_bit_depth,
+ limits);
if (result.is_error()) {
return result.error();
}
+
+ cmpd_index_to_comp_ids[component.component_index].push_back(*result);
}
}
+
+ // --- assign the metadata boxes
+
+ size_t cmpd_size = cmpd ? cmpd->get_components().size() : 0;
+
+ if (properties.cpat) {
+ const auto& pattern_cmpd = properties.cpat->get_pattern();
+ std::vector<uint32_t> cpat_indices;
+ for (const auto& pixel : pattern_cmpd.pixels) {
+ cpat_indices.push_back(pixel.cmpd_index);
+ }
+ Error err = validate_component_indices(cpat_indices, cmpd_size, "cpat");
+ if (err) {
+ return err;
+ }
+
+ // translate BayerPattern, adding new components to the HeifPixelImage
+
+ BayerPattern pattern;
+ pattern.pattern_width = pattern_cmpd.pattern_width;
+ pattern.pattern_height = pattern_cmpd.pattern_height;
+ for (auto p : pattern_cmpd.pixels) {
+ uint32_t comp_id = img->add_component_without_data(components[p.cmpd_index].component_type);
+ pattern.pixels.push_back({comp_id, p.component_gain});
+
+ cmpd_index_to_comp_ids[p.cmpd_index].push_back(comp_id);
+ }
+
+ img->set_bayer_pattern(pattern);
+ }
+
+ for (const auto& splz_box : properties.splz) {
+ const auto& pattern_cmpd = splz_box->get_pattern();
+ Error err = validate_component_indices(pattern_cmpd.component_ids, cmpd_size, "splz");
+ if (err) {
+ return err;
+ }
+ PolarizationPattern pattern = pattern_cmpd;
+ pattern.component_ids = map_cmpd_to_component_ids(pattern_cmpd.component_ids, cmpd_index_to_comp_ids);
+ img->add_polarization_pattern(pattern);
+ }
+
+ for (const auto& sbpm_box : properties.sbpm) {
+ const auto& bad_pixels_map_cmpd = sbpm_box->get_bad_pixels_map();
+ Error err = validate_component_indices(bad_pixels_map_cmpd.component_ids, cmpd_size, "sbpm");
+ if (err) {
+ return err;
+ }
+ SensorBadPixelsMap bad_pixels_map = bad_pixels_map_cmpd;
+ bad_pixels_map.component_ids = map_cmpd_to_component_ids(bad_pixels_map_cmpd.component_ids, cmpd_index_to_comp_ids);
+ img->add_sensor_bad_pixels_map(bad_pixels_map);
+ }
+
+ for (const auto& snuc_box : properties.snuc) {
+ const auto& nuc_cmpd = snuc_box->get_nuc();
+ Error err = validate_component_indices(nuc_cmpd.component_ids, cmpd_size, "snuc");
+ if (err) {
+ return err;
+ }
+ SensorNonUniformityCorrection nuc = nuc_cmpd;
+ nuc.component_ids = map_cmpd_to_component_ids(nuc_cmpd.component_ids, cmpd_index_to_comp_ids);
+ img->add_sensor_nuc(nuc);
+ }
+
+ if (properties.cloc) {
+ img->set_chroma_location(properties.cloc->get_chroma_location());
+ }
+
return img;
}
@@ -283,7 +367,12 @@ Error UncompressedImageCodec::decode_uncompressed_image_tile(const HeifContext*
uint32_t tile_width = ispe->get_width() / uncC->get_number_of_tile_columns();
uint32_t tile_height = ispe->get_height() / uncC->get_number_of_tile_rows();
- Result<std::shared_ptr<HeifPixelImage>> createImgResult = create_image(cmpd, uncC, tile_width, tile_height, context->get_security_limits());
+
+ // Remember which components reference which cmpd indices.
+ // There can be several component ids referencing the same cmpd index.
+ std::vector<std::vector<uint32_t>> cmpd_index_to_comp_ids;
+
+ Result<std::shared_ptr<HeifPixelImage>> createImgResult = create_image(properties, tile_width, tile_height, context->get_security_limits());
if (!createImgResult) {
return createImgResult.error();
}
@@ -339,7 +428,7 @@ Error UncompressedImageCodec::check_header_validity(std::optional<const std::sha
}
uint16_t component_type = cmpd->get_components()[comp.component_index].component_type;
- if (component_type > 7 && component_type != heif_uncompressed_component_type_padded && component_type != heif_uncompressed_component_type_filter_array) {
+ if (component_type > 7 && component_type != heif_unci_component_type_padded && component_type != heif_unci_component_type_filter_array) {
std::stringstream sstr;
sstr << "Uncompressed image with component_type " << ((int) component_type) << " is not implemented yet";
return {heif_error_Unsupported_feature,
diff --git a/libheif/codecs/uncompressed/unc_codec.h b/libheif/codecs/uncompressed/unc_codec.h
index eb08061a..28ca6c60 100644
--- a/libheif/codecs/uncompressed/unc_codec.h
+++ b/libheif/codecs/uncompressed/unc_codec.h
@@ -83,8 +83,7 @@ public:
heif_colorspace* out_colourspace,
bool* out_has_alpha);
- static Result<std::shared_ptr<HeifPixelImage>> create_image(std::shared_ptr<const Box_cmpd>,
- std::shared_ptr<const Box_uncC>,
+ static Result<std::shared_ptr<HeifPixelImage>> create_image(const unci_properties& properties,
uint32_t width,
uint32_t height,
const heif_security_limits* limits);
diff --git a/libheif/codecs/uncompressed/unc_dec.cc b/libheif/codecs/uncompressed/unc_dec.cc
index c831d0e3..23a60e15 100644
--- a/libheif/codecs/uncompressed/unc_dec.cc
+++ b/libheif/codecs/uncompressed/unc_dec.cc
@@ -65,14 +65,14 @@ int Decoder_uncompressed::get_luma_bits_per_pixel() const
}
auto component_type = m_cmpd->get_components()[component_index].component_type;
switch (component_type) {
- case heif_uncompressed_component_type_monochrome:
- case heif_uncompressed_component_type_red:
- case heif_uncompressed_component_type_green:
- case heif_uncompressed_component_type_blue:
- case heif_uncompressed_component_type_filter_array:
+ case heif_unci_component_type_monochrome:
+ case heif_unci_component_type_red:
+ case heif_unci_component_type_green:
+ case heif_unci_component_type_blue:
+ case heif_unci_component_type_filter_array:
alternate_channel_bits = std::max(alternate_channel_bits, (int) component.component_bit_depth);
break;
- case heif_uncompressed_component_type_Y:
+ case heif_unci_component_type_Y:
luma_bits = std::max(luma_bits, (int) component.component_bit_depth);
break;
// TODO: there are other things we'll need to handle eventually, like palette.
@@ -109,15 +109,15 @@ int Decoder_uncompressed::get_chroma_bits_per_pixel() const
}
auto component_type = m_cmpd->get_components()[component_index].component_type;
switch (component_type) {
- case heif_uncompressed_component_type_monochrome:
- case heif_uncompressed_component_type_red:
- case heif_uncompressed_component_type_green:
- case heif_uncompressed_component_type_blue:
- case heif_uncompressed_component_type_filter_array:
+ case heif_unci_component_type_monochrome:
+ case heif_unci_component_type_red:
+ case heif_unci_component_type_green:
+ case heif_unci_component_type_blue:
+ case heif_unci_component_type_filter_array:
alternate_channel_bits = std::max(alternate_channel_bits, (int) component.component_bit_depth);
break;
- case heif_uncompressed_component_type_Cb:
- case heif_uncompressed_component_type_Cr:
+ case heif_unci_component_type_Cb:
+ case heif_unci_component_type_Cr:
chroma_bits = std::max(chroma_bits, (int) component.component_bit_depth);
break;
// TODO: there are other things we'll need to handle eventually, like palette.
diff --git a/libheif/codecs/uncompressed/unc_decoder.cc b/libheif/codecs/uncompressed/unc_decoder.cc
index c5fa4ac8..1d15eaa9 100644
--- a/libheif/codecs/uncompressed/unc_decoder.cc
+++ b/libheif/codecs/uncompressed/unc_decoder.cc
@@ -39,21 +39,6 @@
#include <string>
-static Error validate_component_indices(const std::vector<uint32_t>& indices,
- size_t cmpd_size,
- const char* box_name)
-{
- for (uint32_t idx : indices) {
- if (idx >= cmpd_size) {
- return {heif_error_Invalid_input,
- heif_suberror_Invalid_parameter_value,
- std::string(box_name) + " component index out of range of cmpd table"};
- }
- }
- return Error::Ok;
-}
-
-
// --- unc_decoder ---
unc_decoder::unc_decoder(uint32_t width, uint32_t height,
@@ -471,58 +456,13 @@ Result<std::shared_ptr<HeifPixelImage> > unc_decoder::decode_full_image(
return {global_limit_error};
}
- Result<std::shared_ptr<HeifPixelImage> > createImgResult = UncompressedImageCodec::create_image(cmpd, uncC, width, height, limits);
+ Result<std::shared_ptr<HeifPixelImage> > createImgResult = UncompressedImageCodec::create_image(properties, width, height, limits);
if (!createImgResult) {
return createImgResult.error();
}
auto img = *createImgResult;
- size_t cmpd_size = cmpd ? cmpd->get_components().size() : 0;
-
- if (properties.cpat) {
- const auto& pattern = properties.cpat->get_pattern();
- std::vector<uint32_t> cpat_indices;
- for (const auto& pixel : pattern.pixels) {
- cpat_indices.push_back(pixel.component_index);
- }
- Error err = validate_component_indices(cpat_indices, cmpd_size, "cpat");
- if (err) {
- return err;
- }
- img->set_bayer_pattern(pattern);
- }
-
- for (const auto& splz_box : properties.splz) {
- const auto& pattern = splz_box->get_pattern();
- Error err = validate_component_indices(pattern.component_indices, cmpd_size, "splz");
- if (err) {
- return err;
- }
- img->add_polarization_pattern(pattern);
- }
-
- for (const auto& sbpm_box : properties.sbpm) {
- const auto& bad_pixels_map = sbpm_box->get_bad_pixels_map();
- Error err = validate_component_indices(bad_pixels_map.component_indices, cmpd_size, "sbpm");
- if (err) {
- return err;
- }
- img->add_sensor_bad_pixels_map(bad_pixels_map);
- }
-
- for (const auto& snuc_box : properties.snuc) {
- const auto& nuc = snuc_box->get_nuc();
- Error err = validate_component_indices(nuc.component_indices, cmpd_size, "snuc");
- if (err) {
- return err;
- }
- img->add_sensor_nuc(nuc);
- }
-
- if (properties.cloc) {
- img->set_chroma_location(properties.cloc->get_chroma_location());
- }
auto decoderResult = unc_decoder_factory::get_unc_decoder(width, height, cmpd, uncC);
if (!decoderResult) {
diff --git a/libheif/codecs/uncompressed/unc_decoder_bytealign_component_interleave.cc b/libheif/codecs/uncompressed/unc_decoder_bytealign_component_interleave.cc
index 1ba6e1c4..77f67ba2 100644
--- a/libheif/codecs/uncompressed/unc_decoder_bytealign_component_interleave.cc
+++ b/libheif/codecs/uncompressed/unc_decoder_bytealign_component_interleave.cc
@@ -87,6 +87,7 @@ Error unc_decoder_bytealign_component_interleave::decode_tile(const std::vector<
comp[i].use = true; // map_uncompressed_component_to_channel(m_cmpd, c, &channel);
if (comp[i].use) {
comp[i].dst_plane = img->get_component(c.component_index, &comp[i].dst_plane_stride);
+ assert(comp[i].dst_plane != nullptr);
}
else {
comp[i].dst_plane = nullptr;
diff --git a/libheif/codecs/uncompressed/unc_encoder.cc b/libheif/codecs/uncompressed/unc_encoder.cc
index c07fcc41..ca277b9c 100644
--- a/libheif/codecs/uncompressed/unc_encoder.cc
+++ b/libheif/codecs/uncompressed/unc_encoder.cc
@@ -36,42 +36,42 @@
#include <utility>
-heif_uncompressed_component_type heif_channel_to_component_type(heif_channel channel)
+heif_unci_component_type heif_channel_to_component_type(heif_channel channel)
{
switch (channel) {
- case heif_channel_Y: return heif_uncompressed_component_type_Y;
- case heif_channel_Cb: return heif_uncompressed_component_type_Cb;
- case heif_channel_Cr: return heif_uncompressed_component_type_Cr;
- case heif_channel_R: return heif_uncompressed_component_type_red;
- case heif_channel_G: return heif_uncompressed_component_type_green;
- case heif_channel_B: return heif_uncompressed_component_type_blue;
- case heif_channel_Alpha: return heif_uncompressed_component_type_alpha;
+ case heif_channel_Y: return heif_unci_component_type_Y;
+ case heif_channel_Cb: return heif_unci_component_type_Cb;
+ case heif_channel_Cr: return heif_unci_component_type_Cr;
+ case heif_channel_R: return heif_unci_component_type_red;
+ case heif_channel_G: return heif_unci_component_type_green;
+ case heif_channel_B: return heif_unci_component_type_blue;
+ case heif_channel_Alpha: return heif_unci_component_type_alpha;
case heif_channel_interleaved: assert(false);
break;
- case heif_channel_filter_array: return heif_uncompressed_component_type_filter_array;
- case heif_channel_depth: return heif_uncompressed_component_type_depth;
- case heif_channel_disparity: return heif_uncompressed_component_type_disparity;
- case heif_channel_unknown: return heif_uncompressed_component_type_padded;
+ case heif_channel_filter_array: return heif_unci_component_type_filter_array;
+ case heif_channel_depth: return heif_unci_component_type_depth;
+ case heif_channel_disparity: return heif_unci_component_type_disparity;
+ case heif_channel_unknown: return heif_unci_component_type_padded;
}
- return heif_uncompressed_component_type_padded;
+ return heif_unci_component_type_padded;
}
-heif_uncompressed_component_format to_unc_component_format(heif_channel_datatype channel_datatype)
+heif_uncompressed_component_format to_unc_component_format(heif_component_datatype channel_datatype)
{
switch (channel_datatype) {
- case heif_channel_datatype_signed_integer:
+ case heif_component_datatype_signed_integer:
return component_format_signed;
- case heif_channel_datatype_floating_point:
+ case heif_component_datatype_floating_point:
return component_format_float;
- case heif_channel_datatype_complex_number:
+ case heif_component_datatype_complex_number:
return component_format_complex;
- case heif_channel_datatype_unsigned_integer:
- case heif_channel_datatype_undefined:
+ case heif_component_datatype_unsigned_integer:
+ case heif_component_datatype_undefined:
default:
return component_format_unsigned;
}
@@ -83,68 +83,69 @@ unc_encoder::unc_encoder(const std::shared_ptr<const HeifPixelImage>& image)
m_cmpd = std::make_shared<Box_cmpd>();
m_uncC = std::make_shared<Box_uncC>();
- m_cmpd->set_components(image->get_cmpd_component_types());
+ // --- fill component-id to cmpd-index map
- // --- Bayer pattern: add reference components to cmpd and generate cpat box
+ std::vector<uint32_t> ids = image->get_used_component_ids();
- if (image->has_bayer_pattern()) {
- const BayerPattern& bayer = image->get_bayer_pattern();
-
- // The bayer pattern stores component_index values. When the image has a cmpd
- // table (add_component path), we look up the component type from it. When it
- // doesn't (legacy add_plane path), the component_index IS the component type.
-
- // Collect unique component types from the pattern (in order of first appearance)
- std::vector<uint16_t> unique_types;
- std::set<uint16_t> seen;
- for (const auto& pixel : bayer.pixels) {
- uint16_t comp_type = pixel.component_index; // legacy: index IS the type
- if (seen.insert(comp_type).second) {
- unique_types.push_back(comp_type);
- }
- }
+ for (size_t i = 0; i < ids.size(); i++) {
+ m_map_id_to_cmpd_index[ids[i]] = static_cast<uint32_t>(i);
+ }
- // Add reference components to cmpd (these have no uncC entries).
- std::map<uint16_t, uint16_t> type_to_cmpd_index;
- for (uint16_t type : unique_types) {
- type_to_cmpd_index[type] = m_cmpd->add_component({type});
- }
+ // TODO: we could combine component_ids with similar types if they are also used in the same way in the metadata boxes
+
+ // --- create cmpd component types
+
+ uint32_t max_cmpd_index=0;
+ for (auto iter : m_map_id_to_cmpd_index) {
+ max_cmpd_index = std::max(max_cmpd_index, iter.second);
+ }
+
+ std::vector<uint16_t> cmpd_types(static_cast<size_t>(max_cmpd_index) + 1);
+
+ for (auto iter : m_map_id_to_cmpd_index) {
+ uint16_t comp_type = image->get_component_type(iter.first);
+ cmpd_types[iter.second] = comp_type;
+ }
+
+ m_cmpd->set_components(cmpd_types);
+
+ // --- Bayer pattern: add reference components to cmpd and generate cpat box
+
+ if (image->has_any_bayer_pattern()) {
+ const BayerPattern& bayer = image->get_any_bayer_pattern();
// Build cpat box with resolved cmpd indices
- BayerPattern cpat_pattern;
- cpat_pattern.pattern_width = bayer.pattern_width;
- cpat_pattern.pattern_height = bayer.pattern_height;
- cpat_pattern.pixels.resize(bayer.pixels.size());
- for (size_t i = 0; i < bayer.pixels.size(); i++) {
- uint16_t comp_type = bayer.pixels[i].component_index; // legacy: index IS the type
- cpat_pattern.pixels[i].component_index = type_to_cmpd_index[comp_type];
- cpat_pattern.pixels[i].component_gain = bayer.pixels[i].component_gain;
- }
m_cpat = std::make_shared<Box_cpat>();
- m_cpat->set_pattern(cpat_pattern);
+ m_cpat->set_pattern(bayer.resolve_to_cmpd(m_map_id_to_cmpd_index));
}
if (image->has_polarization_patterns()) {
for (const auto& pol : image->get_polarization_patterns()) {
+ PolarizationPattern polCmpd = pol;
+ polCmpd.component_ids = map_component_ids_to_cmpd(pol.component_ids, m_map_id_to_cmpd_index);
auto splz = std::make_shared<Box_splz>();
- splz->set_pattern(pol);
+ splz->set_pattern(polCmpd);
m_splz.push_back(splz);
}
}
if (image->has_sensor_bad_pixels_maps()) {
for (const auto& bpm : image->get_sensor_bad_pixels_maps()) {
+ SensorBadPixelsMap bpmCmpd = bpm;
+ bpmCmpd.component_ids = map_component_ids_to_cmpd(bpm.component_ids, m_map_id_to_cmpd_index);
auto sbpm = std::make_shared<Box_sbpm>();
- sbpm->set_bad_pixels_map(bpm);
+ sbpm->set_bad_pixels_map(bpmCmpd);
m_sbpm.push_back(sbpm);
}
}
if (image->has_sensor_nuc()) {
for (const auto& nuc : image->get_sensor_nuc()) {
+ SensorNonUniformityCorrection nucCmpd = nuc;
+ nucCmpd.component_ids = map_component_ids_to_cmpd(nuc.component_ids, m_map_id_to_cmpd_index);
auto snuc = std::make_shared<Box_snuc>();
- snuc->set_nuc(nuc);
+ snuc->set_nuc(nucCmpd);
m_snuc.push_back(snuc);
}
}
@@ -187,7 +188,7 @@ Result<std::unique_ptr<const unc_encoder> > unc_encoder_factory::get_unc_encoder
heif_uncompressed_component_format to_unc_component_format(const std::shared_ptr<const HeifPixelImage>& image, heif_channel channel)
{
- heif_channel_datatype datatype = image->get_datatype(channel);
+ heif_component_datatype datatype = image->get_datatype(channel);
heif_uncompressed_component_format component_format = to_unc_component_format(datatype);
return component_format;
}
diff --git a/libheif/codecs/uncompressed/unc_encoder.h b/libheif/codecs/uncompressed/unc_encoder.h
index 40d2a8d9..c613926f 100644
--- a/libheif/codecs/uncompressed/unc_encoder.h
+++ b/libheif/codecs/uncompressed/unc_encoder.h
@@ -23,6 +23,7 @@
#include <memory>
#include <vector>
+#include <map>
#include "error.h"
#include "codecs/encoder.h"
@@ -38,9 +39,9 @@ class Box_snuc;
class Box_cloc;
class HeifPixelImage;
-heif_uncompressed_component_type heif_channel_to_component_type(heif_channel channel);
+heif_unci_component_type heif_channel_to_component_type(heif_channel channel);
-heif_uncompressed_component_format to_unc_component_format(heif_channel_datatype channel_datatype);
+heif_uncompressed_component_format to_unc_component_format(heif_component_datatype channel_datatype);
class unc_encoder
@@ -58,6 +59,8 @@ public:
std::vector<std::shared_ptr<Box_snuc>> get_snuc() const { return m_snuc; }
std::shared_ptr<Box_cloc> get_cloc() const { return m_cloc; }
+ // const std::map<uint32_t, uint32_t>& map_id_to_cmpd_index() { return m_map_id_to_cmpd_index; } // do we need this ?
+
virtual uint64_t compute_tile_data_size_bytes(uint32_t tile_width, uint32_t tile_height) const = 0;
@@ -74,6 +77,8 @@ protected:
std::vector<std::shared_ptr<Box_sbpm>> m_sbpm;
std::vector<std::shared_ptr<Box_snuc>> m_snuc;
std::shared_ptr<Box_cloc> m_cloc;
+
+ std::map<uint32_t, uint32_t> m_map_id_to_cmpd_index;
};
diff --git a/libheif/codecs/uncompressed/unc_encoder_component_interleave.cc b/libheif/codecs/uncompressed/unc_encoder_component_interleave.cc
index d2cc3143..a161492b 100644
--- a/libheif/codecs/uncompressed/unc_encoder_component_interleave.cc
+++ b/libheif/codecs/uncompressed/unc_encoder_component_interleave.cc
@@ -90,16 +90,16 @@ unc_encoder_component_interleave::unc_encoder_component_interleave(const std::sh
uint32_t num_components = image->get_number_of_used_components();
for (uint32_t idx = 0; idx < num_components; idx++) {
- heif_uncompressed_component_type comp_type;
+ heif_unci_component_type comp_type;
heif_channel ch = heif_channel_Y; // default for nonvisual
if (is_nonvisual) {
- comp_type = static_cast<heif_uncompressed_component_type>(image->get_component_type(idx));
+ comp_type = static_cast<heif_unci_component_type>(image->get_component_type(idx));
}
else {
ch = image->get_component_channel(idx);
if (ch == heif_channel_Y && !image->has_channel(heif_channel_Cb)) {
- comp_type = heif_uncompressed_component_type_monochrome;
+ comp_type = heif_unci_component_type_monochrome;
}
else {
comp_type = heif_channel_to_component_type(ch);
diff --git a/libheif/codecs/uncompressed/unc_encoder_component_interleave.h b/libheif/codecs/uncompressed/unc_encoder_component_interleave.h
index db84e99b..834a093f 100644
--- a/libheif/codecs/uncompressed/unc_encoder_component_interleave.h
+++ b/libheif/codecs/uncompressed/unc_encoder_component_interleave.h
@@ -42,7 +42,7 @@ private:
{
uint32_t component_idx;
heif_channel channel;
- heif_uncompressed_component_type component_type;
+ heif_unci_component_type component_type;
heif_uncompressed_component_format component_format;
uint16_t bpp;
bool byte_aligned;
diff --git a/libheif/codecs/uncompressed/unc_encoder_rgb_block_pixel_interleave.cc b/libheif/codecs/uncompressed/unc_encoder_rgb_block_pixel_interleave.cc
index 59ec4eaf..4e5062a7 100644
--- a/libheif/codecs/uncompressed/unc_encoder_rgb_block_pixel_interleave.cc
+++ b/libheif/codecs/uncompressed/unc_encoder_rgb_block_pixel_interleave.cc
@@ -49,18 +49,18 @@ bool unc_encoder_factory_rgb_block_pixel_interleave::can_encode(const std::share
std::unique_ptr<const unc_encoder> unc_encoder_factory_rgb_block_pixel_interleave::create(const std::shared_ptr<const HeifPixelImage>& image,
- const heif_encoding_options& options) const
+ const heif_encoding_options& options) const
{
return std::make_unique<unc_encoder_rgb_block_pixel_interleave>(image, options);
}
unc_encoder_rgb_block_pixel_interleave::unc_encoder_rgb_block_pixel_interleave(const std::shared_ptr<const HeifPixelImage>& image,
- const heif_encoding_options& options)
+ const heif_encoding_options& options)
: unc_encoder(image)
{
- auto cmpd_idx = image->get_component_cmpd_indices_interleaved();
- assert(cmpd_idx.size() == 3);
+ auto ids = image->get_component_ids_interleaved();
+ assert(ids.size() == 3);
uint16_t bpp = image->get_bits_per_pixel(heif_channel_interleaved);
@@ -74,9 +74,9 @@ unc_encoder_rgb_block_pixel_interleave::unc_encoder_rgb_block_pixel_interleave(c
m_uncC->set_sampling_type(sampling_mode_no_subsampling);
m_uncC->set_block_little_endian(false);
- m_uncC->add_component({cmpd_idx[0], bpp, component_format_unsigned, 0});
- m_uncC->add_component({cmpd_idx[1], bpp, component_format_unsigned, 0});
- m_uncC->add_component({cmpd_idx[2], bpp, component_format_unsigned, 0});
+ m_uncC->add_component({m_map_id_to_cmpd_index.find(ids[0])->second, bpp, component_format_unsigned, 0});
+ m_uncC->add_component({m_map_id_to_cmpd_index.find(ids[1])->second, bpp, component_format_unsigned, 0});
+ m_uncC->add_component({m_map_id_to_cmpd_index.find(ids[2])->second, bpp, component_format_unsigned, 0});
}
diff --git a/libheif/codecs/uncompressed/unc_encoder_rgb_block_pixel_interleave.h b/libheif/codecs/uncompressed/unc_encoder_rgb_block_pixel_interleave.h
index 085c9f3d..170a5554 100644
--- a/libheif/codecs/uncompressed/unc_encoder_rgb_block_pixel_interleave.h
+++ b/libheif/codecs/uncompressed/unc_encoder_rgb_block_pixel_interleave.h
@@ -25,12 +25,14 @@
#include <memory>
#include <vector>
+#include <map>
+
class unc_encoder_rgb_block_pixel_interleave : public unc_encoder
{
public:
unc_encoder_rgb_block_pixel_interleave(const std::shared_ptr<const HeifPixelImage>& image,
- const heif_encoding_options& options);
+ const heif_encoding_options& options);
uint64_t compute_tile_data_size_bytes(uint32_t tile_width, uint32_t tile_height) const override;
diff --git a/libheif/codecs/uncompressed/unc_encoder_rgb_bytealign_pixel_interleave.cc b/libheif/codecs/uncompressed/unc_encoder_rgb_bytealign_pixel_interleave.cc
index c337f643..c46cd7b8 100644
--- a/libheif/codecs/uncompressed/unc_encoder_rgb_bytealign_pixel_interleave.cc
+++ b/libheif/codecs/uncompressed/unc_encoder_rgb_bytealign_pixel_interleave.cc
@@ -59,12 +59,12 @@ unc_encoder_rgb_bytealign_pixel_interleave::unc_encoder_rgb_bytealign_pixel_inte
const heif_encoding_options& options)
: unc_encoder(image)
{
- auto cmpd_idx = image->get_component_cmpd_indices_interleaved();
+ auto cmpd_ids = image->get_component_ids_interleaved();
bool save_alpha = image->has_alpha();
m_bytes_per_pixel = save_alpha ? 8 : 6;
- assert(cmpd_idx.size() == m_bytes_per_pixel/2);
+ assert(cmpd_ids.size() == m_bytes_per_pixel/2);
bool little_endian = (image->get_chroma_format() == heif_chroma_interleaved_RRGGBB_LE ||
image->get_chroma_format() == heif_chroma_interleaved_RRGGBBAA_LE);
@@ -84,11 +84,11 @@ unc_encoder_rgb_bytealign_pixel_interleave::unc_encoder_rgb_bytealign_pixel_inte
m_uncC->set_components_little_endian(false); // little_endian);
m_uncC->set_pixel_size(m_bytes_per_pixel);
- m_uncC->add_component({cmpd_idx[0], bpp, component_format_unsigned, component_align_size});
- m_uncC->add_component({cmpd_idx[1], bpp, component_format_unsigned, component_align_size});
- m_uncC->add_component({cmpd_idx[2], bpp, component_format_unsigned, component_align_size});
+ m_uncC->add_component({m_map_id_to_cmpd_index[cmpd_ids[0]], bpp, component_format_unsigned, component_align_size});
+ m_uncC->add_component({m_map_id_to_cmpd_index[cmpd_ids[1]], bpp, component_format_unsigned, component_align_size});
+ m_uncC->add_component({m_map_id_to_cmpd_index[cmpd_ids[2]], bpp, component_format_unsigned, component_align_size});
if (save_alpha) {
- m_uncC->add_component({cmpd_idx[3], bpp, component_format_unsigned, component_align_size});
+ m_uncC->add_component({m_map_id_to_cmpd_index[cmpd_ids[3]], bpp, component_format_unsigned, component_align_size});
}
}
diff --git a/libheif/codecs/uncompressed/unc_encoder_rgb_pixel_interleave.cc b/libheif/codecs/uncompressed/unc_encoder_rgb_pixel_interleave.cc
index 484ac5ef..eb4e6a3b 100644
--- a/libheif/codecs/uncompressed/unc_encoder_rgb_pixel_interleave.cc
+++ b/libheif/codecs/uncompressed/unc_encoder_rgb_pixel_interleave.cc
@@ -55,11 +55,11 @@ unc_encoder_rgb_pixel_interleave::unc_encoder_rgb_pixel_interleave(const std::sh
const heif_encoding_options& options)
: unc_encoder(image)
{
- auto cmpd_idx = image->get_component_cmpd_indices_interleaved();
+ auto cmpd_ids = image->get_component_ids_interleaved();
bool save_alpha = image->has_alpha();
m_bytes_per_pixel = save_alpha ? 4 : 3;
- assert(cmpd_idx.size() == m_bytes_per_pixel);
+ assert(cmpd_ids.size() == m_bytes_per_pixel);
uint16_t bpp = image->get_bits_per_pixel(heif_channel_interleaved);
@@ -79,11 +79,11 @@ unc_encoder_rgb_pixel_interleave::unc_encoder_rgb_pixel_interleave(const std::sh
m_uncC->set_interleave_type(interleave_mode_pixel);
m_uncC->set_sampling_type(sampling_mode_no_subsampling);
- m_uncC->add_component({cmpd_idx[0], bpp, component_format_unsigned, component_align_size});
- m_uncC->add_component({cmpd_idx[1], bpp, component_format_unsigned, component_align_size});
- m_uncC->add_component({cmpd_idx[2], bpp, component_format_unsigned, component_align_size});
+ m_uncC->add_component({m_map_id_to_cmpd_index[cmpd_ids[0]], bpp, component_format_unsigned, component_align_size});
+ m_uncC->add_component({m_map_id_to_cmpd_index[cmpd_ids[1]], bpp, component_format_unsigned, component_align_size});
+ m_uncC->add_component({m_map_id_to_cmpd_index[cmpd_ids[2]], bpp, component_format_unsigned, component_align_size});
if (save_alpha) {
- m_uncC->add_component({cmpd_idx[3], bpp, component_format_unsigned, component_align_size});
+ m_uncC->add_component({m_map_id_to_cmpd_index[cmpd_ids[3]], bpp, component_format_unsigned, component_align_size});
}
}
diff --git a/libheif/codecs/uncompressed/unc_types.h b/libheif/codecs/uncompressed/unc_types.h
index 7dfb16c0..f5de9fef 100644
--- a/libheif/codecs/uncompressed/unc_types.h
+++ b/libheif/codecs/uncompressed/unc_types.h
@@ -26,7 +26,7 @@
#include <libheif/heif_uncompressed.h>
// Update this when adding new values to heif_uncompressed_component_type.
-#define heif_uncompressed_component_type_max_valid heif_uncompressed_component_type_key_black
+#define heif_unci_component_type_max_valid heif_unci_component_type_key_black
/**
* HEIF uncompressed component format.
diff --git a/libheif/color-conversion/bayer_bilinear.cc b/libheif/color-conversion/bayer_bilinear.cc
index 9e0ef309..210e1be2 100644
--- a/libheif/color-conversion/bayer_bilinear.cc
+++ b/libheif/color-conversion/bayer_bilinear.cc
@@ -65,11 +65,11 @@ Op_bayer_bilinear_to_RGB24_32::state_after_conversion(const ColorState& input_st
static int component_type_to_rgb_index(uint16_t component_type)
{
switch (component_type) {
- case heif_uncompressed_component_type_red:
+ case heif_unci_component_type_red:
return 0;
- case heif_uncompressed_component_type_green:
+ case heif_unci_component_type_green:
return 1;
- case heif_uncompressed_component_type_blue:
+ case heif_unci_component_type_blue:
return 2;
default:
return -1;
@@ -88,11 +88,11 @@ Op_bayer_bilinear_to_RGB24_32::convert_colorspace(const std::shared_ptr<const He
uint32_t width = input->get_width();
uint32_t height = input->get_height();
- if (!input->has_bayer_pattern()) {
+ if (!input->has_any_bayer_pattern()) {
return Error::InternalError;
}
- const BayerPattern& pattern = input->get_bayer_pattern();
+ const BayerPattern& pattern = input->get_any_bayer_pattern();
uint16_t pw = pattern.pattern_width;
uint16_t ph = pattern.pattern_height;
@@ -122,7 +122,7 @@ Op_bayer_bilinear_to_RGB24_32::convert_colorspace(const std::shared_ptr<const He
// Build a lookup table: for each pattern position, which RGB channel (0=R,1=G,2=B) does it provide?
std::vector<int> pattern_channel(pw * ph);
for (int i = 0; i < pw * ph; i++) {
- uint16_t comp_type = input->get_component_type(pattern.pixels[i].component_index);
+ uint16_t comp_type = input->get_component_type(pattern.pixels[i].component_id);
pattern_channel[i] = component_type_to_rgb_index(comp_type);
if (pattern_channel[i] < 0) {
return Error(heif_error_Unsupported_feature,
diff --git a/libheif/pixelimage.cc b/libheif/pixelimage.cc
index aec45672..55c5e4f5 100644
--- a/libheif/pixelimage.cc
+++ b/libheif/pixelimage.cc
@@ -100,29 +100,29 @@ uint32_t channel_height(uint32_t h, heif_chroma chroma, heif_channel channel)
heif_channel map_uncompressed_component_to_channel(uint16_t component_type)
{
switch (component_type) {
- case heif_uncompressed_component_type_monochrome:
- case heif_uncompressed_component_type_Y:
+ case heif_unci_component_type_monochrome:
+ case heif_unci_component_type_Y:
return heif_channel_Y;
- case heif_uncompressed_component_type_Cb:
+ case heif_unci_component_type_Cb:
return heif_channel_Cb;
- case heif_uncompressed_component_type_Cr:
+ case heif_unci_component_type_Cr:
return heif_channel_Cr;
- case heif_uncompressed_component_type_red:
+ case heif_unci_component_type_red:
return heif_channel_R;
- case heif_uncompressed_component_type_green:
+ case heif_unci_component_type_green:
return heif_channel_G;
- case heif_uncompressed_component_type_blue:
+ case heif_unci_component_type_blue:
return heif_channel_B;
- case heif_uncompressed_component_type_alpha:
+ case heif_unci_component_type_alpha:
return heif_channel_Alpha;
- case heif_uncompressed_component_type_filter_array:
+ case heif_unci_component_type_filter_array:
return heif_channel_filter_array;
- case heif_uncompressed_component_type_depth:
+ case heif_unci_component_type_depth:
return heif_channel_depth;
- case heif_uncompressed_component_type_disparity:
+ case heif_unci_component_type_disparity:
return heif_channel_disparity;
- case heif_uncompressed_component_type_padded:
+ case heif_unci_component_type_padded:
default:
return heif_channel_unknown;
}
@@ -133,43 +133,43 @@ static std::vector<uint16_t> map_channel_to_component_type(heif_channel channel,
{
switch (channel) {
case heif_channel_Y:
- return {heif_uncompressed_component_type_Y};
+ return {heif_unci_component_type_Y};
case heif_channel_Cb:
- return {heif_uncompressed_component_type_Cb};
+ return {heif_unci_component_type_Cb};
case heif_channel_Cr:
- return {heif_uncompressed_component_type_Cr};
+ return {heif_unci_component_type_Cr};
case heif_channel_R:
- return {heif_uncompressed_component_type_red};
+ return {heif_unci_component_type_red};
case heif_channel_G:
- return {heif_uncompressed_component_type_green};
+ return {heif_unci_component_type_green};
case heif_channel_B:
- return {heif_uncompressed_component_type_blue};
+ return {heif_unci_component_type_blue};
case heif_channel_Alpha:
- return {heif_uncompressed_component_type_alpha};
+ return {heif_unci_component_type_alpha};
case heif_channel_filter_array:
- return {heif_uncompressed_component_type_filter_array};
+ return {heif_unci_component_type_filter_array};
case heif_channel_depth:
- return {heif_uncompressed_component_type_depth};
+ return {heif_unci_component_type_depth};
case heif_channel_disparity:
- return {heif_uncompressed_component_type_disparity};
+ return {heif_unci_component_type_disparity};
case heif_channel_interleaved:
switch (chroma) {
case heif_chroma_interleaved_RGB:
case heif_chroma_interleaved_RRGGBB_BE:
case heif_chroma_interleaved_RRGGBB_LE:
return {
- heif_uncompressed_component_type_red,
- heif_uncompressed_component_type_green,
- heif_uncompressed_component_type_blue
+ heif_unci_component_type_red,
+ heif_unci_component_type_green,
+ heif_unci_component_type_blue
};
case heif_chroma_interleaved_RGBA:
case heif_chroma_interleaved_RRGGBBAA_BE:
case heif_chroma_interleaved_RRGGBBAA_LE:
return {
- heif_uncompressed_component_type_red,
- heif_uncompressed_component_type_green,
- heif_uncompressed_component_type_blue,
- heif_uncompressed_component_type_alpha
+ heif_unci_component_type_red,
+ heif_unci_component_type_green,
+ heif_unci_component_type_blue,
+ heif_unci_component_type_alpha
};
default:
assert(false);
@@ -184,6 +184,51 @@ static std::vector<uint16_t> map_channel_to_component_type(heif_channel channel,
}
+BayerPatternCmpd BayerPattern::resolve_to_cmpd(std::map<uint32_t, uint32_t> comp_id_to_cmap) const
+{
+ BayerPatternCmpd cpat;
+ cpat.pattern_width = pattern_width;
+ cpat.pattern_height = pattern_height;
+
+ for (auto p : pixels) {
+ cpat.pixels.push_back({comp_id_to_cmap[p.component_id], p.component_gain});
+ }
+
+ return cpat;
+}
+
+
+static void remove_duplicates(std::vector<uint32_t>& v)
+{
+ std::sort(v.begin(), v.end());
+ v.erase(std::unique(v.begin(), v.end()), v.end());
+}
+
+
+std::vector<uint32_t> map_component_ids_to_cmpd(const std::vector<uint32_t>& component_ids, const std::map<uint32_t, uint32_t>& comp_id_to_cmpd)
+{
+ std::vector<uint32_t> cmpd_indices;
+
+ for (uint32_t comp_id : component_ids) {
+ cmpd_indices.push_back(comp_id_to_cmpd.find(comp_id)->second);
+ }
+
+ remove_duplicates(cmpd_indices);
+
+ return cmpd_indices;
+}
+
+std::vector<uint32_t> map_cmpd_to_component_ids(const std::vector<uint32_t>& cmpd_indices, const std::vector<std::vector<uint32_t>>& cmpd_to_comp_ids)
+{
+ std::vector<uint32_t> component_ids;
+
+ for (uint32_t idx : cmpd_indices) {
+ component_ids.insert(component_ids.end(), cmpd_to_comp_ids[idx].begin(), cmpd_to_comp_ids[idx].end());
+ }
+
+ return component_ids;
+}
+
ImageExtraData::~ImageExtraData()
{
@@ -504,10 +549,11 @@ HeifPixelImage::ImageComponent HeifPixelImage::new_image_plane_for_channel(heif_
// ISO 23001-17 component types
// For interleaved planes, several component types are added to cmpd
- auto cmpd = map_channel_to_component_type(channel, m_chroma);
- for (size_t i = 0; i < cmpd.size(); i++) {
- plane.m_component_index.push_back(static_cast<uint32_t>(m_cmpd_component_types.size()));
- m_cmpd_component_types.push_back(cmpd[i]);
+ auto component_types = map_channel_to_component_type(channel, m_chroma);
+ for (auto type : component_types) {
+ plane.m_component_ids.push_back(m_next_component_id);
+ m_component_types[m_next_component_id] = type;
+ m_next_component_id++;
}
return plane;
@@ -531,7 +577,7 @@ Error HeifPixelImage::add_plane(heif_channel channel, uint32_t width, uint32_t h
bit_depth = 8;
}
- if (auto err = plane.alloc(width, height, heif_channel_datatype_unsigned_integer, bit_depth, num_interleaved_pixels, limits, m_memory_handle)) {
+ if (auto err = plane.alloc(width, height, heif_component_datatype_unsigned_integer, bit_depth, num_interleaved_pixels, limits, m_memory_handle)) {
return err;
}
else {
@@ -541,7 +587,7 @@ Error HeifPixelImage::add_plane(heif_channel channel, uint32_t width, uint32_t h
}
-Error HeifPixelImage::add_channel(heif_channel channel, uint32_t width, uint32_t height, heif_channel_datatype datatype, int bit_depth,
+Error HeifPixelImage::add_channel(heif_channel channel, uint32_t width, uint32_t height, heif_component_datatype datatype, int bit_depth,
const heif_security_limits* limits)
{
ImageComponent plane = new_image_plane_for_channel(channel);
@@ -556,7 +602,7 @@ Error HeifPixelImage::add_channel(heif_channel channel, uint32_t width, uint32_t
}
-Error HeifPixelImage::ImageComponent::alloc(uint32_t width, uint32_t height, heif_channel_datatype datatype, int bit_depth,
+Error HeifPixelImage::ImageComponent::alloc(uint32_t width, uint32_t height, heif_component_datatype datatype, int bit_depth,
int num_interleaved_components,
const heif_security_limits* limits,
MemoryHandle& memory_handle)
@@ -840,7 +886,7 @@ uint32_t HeifPixelImage::get_height(enum heif_channel channel) const
uint32_t HeifPixelImage::get_width(uint32_t component_idx) const
{
- auto* comp = find_component_by_index(component_idx);
+ auto* comp = find_component_by_id(component_idx);
if (!comp) {
return 0;
}
@@ -851,7 +897,7 @@ uint32_t HeifPixelImage::get_width(uint32_t component_idx) const
uint32_t HeifPixelImage::get_height(uint32_t component_idx) const
{
- auto* comp = find_component_by_index(component_idx);
+ auto* comp = find_component_by_id(component_idx);
if (!comp) {
return 0;
}
@@ -872,7 +918,7 @@ uint32_t HeifPixelImage::get_primary_component() const
case heif_channel_G:
case heif_channel_B:
case heif_channel_filter_array:
- return m_planes[idx].m_component_index[0];
+ return m_planes[idx].m_component_ids[0];
default:
; // NOP
}
@@ -880,35 +926,34 @@ uint32_t HeifPixelImage::get_primary_component() const
// second pass: if we have a cmpd table, use component types
- if (!m_cmpd_component_types.empty()) {
- for (uint32_t idx=0; idx<m_planes.size(); idx++) {
- uint16_t comp_type = get_component_type(m_planes[idx].m_component_index[0]);
- switch (comp_type) {
- case heif_uncompressed_component_type_Y:
- case heif_uncompressed_component_type_monochrome:
- case heif_uncompressed_component_type_red:
- case heif_uncompressed_component_type_green:
- case heif_uncompressed_component_type_blue:
- case heif_uncompressed_component_type_cyan:
- case heif_uncompressed_component_type_magenta:
- case heif_uncompressed_component_type_yellow:
- case heif_uncompressed_component_type_key_black:
- case heif_uncompressed_component_type_filter_array:
- case heif_uncompressed_component_type_palette:
- return m_planes[idx].m_component_index[0];
+ for (uint32_t idx = 0; idx < m_planes.size(); idx++) {
+ uint16_t comp_type = get_component_type(m_planes[idx].m_component_ids[0]);
+ switch (comp_type) {
+ case heif_unci_component_type_Y:
+ case heif_unci_component_type_monochrome:
+ case heif_unci_component_type_red:
+ case heif_unci_component_type_green:
+ case heif_unci_component_type_blue:
+ case heif_unci_component_type_cyan:
+ case heif_unci_component_type_magenta:
+ case heif_unci_component_type_yellow:
+ case heif_unci_component_type_key_black:
+ case heif_unci_component_type_filter_array:
+ case heif_unci_component_type_palette:
+ return m_planes[idx].m_component_ids[0];
- default:
- ; // NOP
- }
+ default:
+ ; // NOP
}
}
// third pass: allow anything
if (!m_planes.empty()) {
- return m_planes[0].m_component_index[0];
+ return m_planes[0].m_component_ids[0];
}
- return 0;
+
+ return heif_unci_component_type_UNDEFINED;
}
#if 0
uint32_t HeifPixelImage::get_primary_width() const
@@ -1015,11 +1060,11 @@ uint16_t HeifPixelImage::get_visual_image_bits_per_pixel() const
}
-heif_channel_datatype HeifPixelImage::get_datatype(enum heif_channel channel) const
+heif_component_datatype HeifPixelImage::get_datatype(enum heif_channel channel) const
{
auto* comp = find_component_for_channel(channel);
if (!comp) {
- return heif_channel_datatype_undefined;
+ return heif_component_datatype_undefined;
}
return comp->m_datatype;
@@ -2104,9 +2149,6 @@ Error HeifPixelImage::create_clone_image_at_new_size(const std::shared_ptr<const
create(w, h, colorspace, chroma);
- // Copy the cmpd component type table (needed for nonvisual/component images)
- m_cmpd_component_types = source->m_cmpd_component_types;
-
for (const auto& src_plane : source->m_planes) {
// TODO: do we also support images where some planes (e.g. the alpha-plane) have a different size than the main image?
// We could do this by scaling all planes proportionally. This would also handle chroma channels implicitly.
@@ -2115,7 +2157,8 @@ Error HeifPixelImage::create_clone_image_at_new_size(const std::shared_ptr<const
ImageComponent plane;
plane.m_channel = src_plane.m_channel;
- plane.m_component_index = src_plane.m_component_index;
+ plane.m_component_ids = src_plane.m_component_ids;
+
if (auto err = plane.alloc(plane_w, plane_h, src_plane.m_datatype, src_plane.m_bit_depth,
src_plane.m_num_interleaved_components, limits, m_memory_handle)) {
return err;
@@ -2124,6 +2167,8 @@ Error HeifPixelImage::create_clone_image_at_new_size(const std::shared_ptr<const
m_planes.push_back(plane);
}
+ m_component_types = source->m_component_types;
+
return Error::Ok;
}
@@ -2189,13 +2234,13 @@ HeifPixelImage::extract_image_area(uint32_t x0, uint32_t y0, uint32_t w, uint32_
// --- index-based component access methods
-HeifPixelImage::ImageComponent* HeifPixelImage::find_component_by_index(uint32_t component_index)
+HeifPixelImage::ImageComponent* HeifPixelImage::find_component_by_id(uint32_t component_index)
{
for (auto& plane : m_planes) {
// we search through all indices in case we have an interleaved plane
- if (std::find(plane.m_component_index.begin(),
- plane.m_component_index.end(),
- component_index) != plane.m_component_index.end()) {
+ if (std::find(plane.m_component_ids.begin(),
+ plane.m_component_ids.end(),
+ component_index) != plane.m_component_ids.end()) {
return &plane;
}
}
@@ -2203,15 +2248,15 @@ HeifPixelImage::ImageComponent* HeifPixelImage::find_component_by_index(uint32_t
}
-const HeifPixelImage::ImageComponent* HeifPixelImage::find_component_by_index(uint32_t component_index) const
+const HeifPixelImage::ImageComponent* HeifPixelImage::find_component_by_id(uint32_t component_index) const
{
- return const_cast<HeifPixelImage*>(this)->find_component_by_index(component_index);
+ return const_cast<HeifPixelImage*>(this)->find_component_by_id(component_index);
}
heif_channel HeifPixelImage::get_component_channel(uint32_t component_idx) const
{
- auto* comp = find_component_by_index(component_idx);
+ auto* comp = find_component_by_id(component_idx);
assert(comp);
return comp->m_channel;
}
@@ -2219,7 +2264,7 @@ heif_channel HeifPixelImage::get_component_channel(uint32_t component_idx) const
uint32_t HeifPixelImage::get_component_width(uint32_t component_idx) const
{
- auto* comp = find_component_by_index(component_idx);
+ auto* comp = find_component_by_id(component_idx);
assert(comp);
return comp->m_width;
}
@@ -2227,7 +2272,7 @@ uint32_t HeifPixelImage::get_component_width(uint32_t component_idx) const
uint32_t HeifPixelImage::get_component_height(uint32_t component_idx) const
{
- auto* comp = find_component_by_index(component_idx);
+ auto* comp = find_component_by_id(component_idx);
assert(comp);
return comp->m_height;
}
@@ -2235,7 +2280,7 @@ uint32_t HeifPixelImage::get_component_height(uint32_t component_idx) const
uint16_t HeifPixelImage::get_component_bits_per_pixel(uint32_t component_idx) const
{
- auto* comp = find_component_by_index(component_idx);
+ auto* comp = find_component_by_id(component_idx);
assert(comp);
return comp->m_bit_depth;
}
@@ -2243,7 +2288,7 @@ uint16_t HeifPixelImage::get_component_bits_per_pixel(uint32_t component_idx) co
uint16_t HeifPixelImage::get_component_storage_bits_per_pixel(uint32_t component_idx) const
{
- auto* comp = find_component_by_index(component_idx);
+ auto* comp = find_component_by_id(component_idx);
assert(comp);
uint32_t bpp = comp->get_bytes_per_pixel() * 8;
assert(bpp);
@@ -2251,55 +2296,58 @@ uint16_t HeifPixelImage::get_component_storage_bits_per_pixel(uint32_t component
}
-heif_channel_datatype HeifPixelImage::get_component_datatype(uint32_t component_idx) const
+heif_component_datatype HeifPixelImage::get_component_datatype(uint32_t component_idx) const
{
- auto* comp = find_component_by_index(component_idx);
+ auto* comp = find_component_by_id(component_idx);
assert(comp);
return comp->m_datatype;
}
-uint16_t HeifPixelImage::get_component_type(uint32_t component_idx) const
+uint16_t HeifPixelImage::get_component_type(uint32_t component_id) const
{
- if (component_idx >= m_cmpd_component_types.size()) {
- return 0;
+ auto iter = m_component_types.find(component_id);
+ if (iter == m_component_types.end()) {
+ return heif_unci_component_type_UNDEFINED;
}
- return m_cmpd_component_types[component_idx];
+
+ return iter->second;
}
-std::vector<uint32_t> HeifPixelImage::get_component_cmpd_indices_interleaved() const
+std::vector<uint32_t> HeifPixelImage::get_component_ids_interleaved() const
{
const ImageComponent* comp = find_component_for_channel(heif_channel_interleaved);
assert(comp);
- return comp->m_component_index;
+ return comp->m_component_ids;
}
Result<uint32_t> HeifPixelImage::add_component(uint32_t width, uint32_t height,
uint16_t component_type,
- heif_channel_datatype datatype, int bit_depth,
+ heif_component_datatype datatype, int bit_depth,
const heif_security_limits* limits)
{
// Auto-generate component_index by appending to cmpd table
- uint32_t component_index = static_cast<uint32_t>(m_cmpd_component_types.size());
- m_cmpd_component_types.push_back(component_type);
+ uint32_t component_id = m_next_component_id++;
+ m_component_types[component_id] = component_type;
ImageComponent plane;
plane.m_channel = map_uncompressed_component_to_channel(component_type);
- plane.m_component_index = std::vector{component_index};
+ plane.m_component_ids = std::vector{component_id};
if (Error err = plane.alloc(width, height, datatype, bit_depth, 1, limits, m_memory_handle)) {
return {err};
}
m_planes.push_back(plane);
- return component_index;
+ return component_id;
}
+#if 0
Result<uint32_t> HeifPixelImage::add_component_for_index(uint32_t component_index,
uint32_t width, uint32_t height,
- heif_channel_datatype datatype, int bit_depth,
+ heif_component_datatype datatype, int bit_depth,
const heif_security_limits* limits)
{
if (component_index >= m_cmpd_component_types.size()) {
@@ -2319,15 +2367,18 @@ Result<uint32_t> HeifPixelImage::add_component_for_index(uint32_t component_inde
m_planes.push_back(plane);
return component_index;
}
+#endif
-std::vector<uint32_t> HeifPixelImage::get_used_component_indices() const
+std::vector<uint32_t> HeifPixelImage::get_used_component_ids() const
{
std::vector<uint32_t> indices;
- indices.reserve(m_planes.size());
- for (const auto& plane : m_planes) {
- indices.insert(indices.end(), plane.m_component_index.begin(), plane.m_component_index.end());
+ indices.reserve(m_component_types.size());
+
+ for (const auto& iter : m_component_types) {
+ indices.push_back(iter.first);
}
+
return indices;
}
diff --git a/libheif/pixelimage.h b/libheif/pixelimage.h
index 40c7b92a..c19dd8af 100644
--- a/libheif/pixelimage.h
+++ b/libheif/pixelimage.h
@@ -41,16 +41,37 @@
#include <cassert>
#include <string>
+constexpr uint16_t heif_unci_component_type_UNDEFINED = 0xFFFF;
+
+
+struct bayer_pattern_pixel_cmpd
+{
+ uint32_t cmpd_index;
+ float component_gain;
+};
+
+struct BayerPatternCmpd
+{
+ uint16_t pattern_width = 0;
+ uint16_t pattern_height = 0;
+ std::vector<bayer_pattern_pixel_cmpd> pixels;
+};
+
struct BayerPattern
{
uint16_t pattern_width = 0;
uint16_t pattern_height = 0;
std::vector<heif_bayer_pattern_pixel> pixels;
+
+ BayerPatternCmpd resolve_to_cmpd(std::map<uint32_t, uint32_t> comp_id_to_cmap) const;
};
+std::vector<uint32_t> map_component_ids_to_cmpd(const std::vector<uint32_t>& component_ids, const std::map<uint32_t, uint32_t>& comp_id_to_cmpd);
+std::vector<uint32_t> map_cmpd_to_component_ids(const std::vector<uint32_t>& cmpd_indices, const std::vector<std::vector<uint32_t>>& cmpd_to_comp_ids);
+
struct PolarizationPattern
{
- std::vector<uint32_t> component_indices; // empty = applies to all components
+ std::vector<uint32_t> component_ids; // empty = applies to all components. Either cmpd-index or component-id, depending on context.
uint16_t pattern_width = 0;
uint16_t pattern_height = 0;
std::vector<float> polarization_angles; // pattern_width * pattern_height entries
@@ -59,17 +80,21 @@ struct PolarizationPattern
struct SensorBadPixelsMap
{
- std::vector<uint32_t> component_indices; // empty = applies to all components
+ struct BadPixelCoordinate
+ {
+ uint32_t row, column;
+ };
+
+ std::vector<uint32_t> component_ids; // empty = applies to all components. Either cmpd-index or component-id, depending on context.
bool correction_applied = false;
std::vector<uint32_t> bad_rows;
std::vector<uint32_t> bad_columns;
- struct BadPixel { uint32_t row; uint32_t column; };
- std::vector<BadPixel> bad_pixels;
+ std::vector<BadPixelCoordinate> bad_pixels;
};
struct SensorNonUniformityCorrection
{
- std::vector<uint32_t> component_indices; // empty = applies to all components
+ std::vector<uint32_t> component_ids; // empty = applies to all components. Either cmpd-index or component-id, depending on context.
bool nuc_is_applied = false;
uint32_t image_width = 0;
uint32_t image_height = 0;
@@ -213,12 +238,19 @@ public:
// --- bayer pattern
- bool has_bayer_pattern() const { return m_bayer_pattern.has_value(); }
+ bool has_bayer_pattern(uint32_t component_id) const { return m_bayer_pattern.has_value(); }
+
+ bool has_any_bayer_pattern() const { return m_bayer_pattern.has_value(); }
- const BayerPattern& get_bayer_pattern() const { assert(has_bayer_pattern()); return *m_bayer_pattern; }
+ const BayerPattern& get_bayer_pattern(uint32_t component_id) const { assert(has_bayer_pattern(component_id)); return *m_bayer_pattern; }
+
+ const BayerPattern& get_any_bayer_pattern() const { assert(has_any_bayer_pattern()); return *m_bayer_pattern; }
virtual void set_bayer_pattern(const BayerPattern& pattern) { m_bayer_pattern = pattern; }
+ // TODO: replace uint16_t component_type with class that also handled the std::string type
+ uint32_t add_component_without_data(uint16_t component_type) { assert(false); /*TODO*/ }
+
// --- polarization pattern
@@ -342,7 +374,7 @@ public:
Error add_plane(heif_channel channel, uint32_t width, uint32_t height, int bit_depth, const heif_security_limits* limits);
- Error add_channel(heif_channel channel, uint32_t width, uint32_t height, heif_channel_datatype datatype, int bit_depth,
+ Error add_channel(heif_channel channel, uint32_t width, uint32_t height, heif_component_datatype datatype, int bit_depth,
const heif_security_limits* limits);
bool has_channel(heif_channel channel) const;
@@ -387,7 +419,7 @@ public:
// Get the maximum bit depth of a visual channel (YCbCr or RGB).
uint16_t get_visual_image_bits_per_pixel() const;
- heif_channel_datatype get_datatype(heif_channel channel) const;
+ heif_component_datatype get_datatype(heif_channel channel) const;
int get_number_of_interleaved_components(heif_channel channel) const;
@@ -423,11 +455,11 @@ public:
}
- // --- index-based component access (for ISO 23001-17 multi-component images)
+ // --- id-based component access (for ISO 23001-17 multi-component images)
- uint32_t get_number_of_used_components() const { return static_cast<uint32_t>(m_planes.size()); }
+ uint32_t get_number_of_used_components() const { return static_cast<uint32_t>(m_component_types.size()); }
- uint32_t get_total_number_of_cmpd_components() const { return static_cast<uint32_t>(m_cmpd_component_types.size()); }
+ //uint32_t get_total_number_of_cmpd_components() const { return static_cast<uint32_t>(m_cmpd_component_types.size()); }
heif_channel get_component_channel(uint32_t component_idx) const;
@@ -435,37 +467,39 @@ public:
uint32_t get_component_height(uint32_t component_idx) const;
uint16_t get_component_bits_per_pixel(uint32_t component_idx) const;
uint16_t get_component_storage_bits_per_pixel(uint32_t component_idx) const;
- heif_channel_datatype get_component_datatype(uint32_t component_idx) const;
+ heif_component_datatype get_component_datatype(uint32_t component_idx) const;
// Look up the component type from the cmpd table. Works for any cmpd index,
// even those that have no image plane (e.g. bayer reference components).
uint16_t get_component_type(uint32_t component_idx) const;
- std::vector<uint16_t> get_cmpd_component_types() const { return m_cmpd_component_types; }
+ //std::vector<uint16_t> get_cmpd_component_types() const { return m_cmpd_component_types; }
- std::vector<uint32_t> get_component_cmpd_indices_interleaved() const;
+ std::vector<uint32_t> get_component_ids_interleaved() const;
- uint32_t get_component_cmpd_index() const { assert(m_cmpd_component_types.size()==1); return m_cmpd_component_types[0]; }
+ //uint32_t get_component_cmpd_index() const { assert(m_cmpd_component_types.size()==1); return m_cmpd_component_types[0]; }
// Encoder path: auto-generates component_index by appending to cmpd table.
Result<uint32_t> add_component(uint32_t width, uint32_t height,
uint16_t component_type,
- heif_channel_datatype datatype, int bit_depth,
+ heif_component_datatype datatype, int bit_depth,
const heif_security_limits* limits);
// Decoder path: uses a pre-populated cmpd table to look up the component type.
+#if 0
Result<uint32_t> add_component_for_index(uint32_t component_index,
uint32_t width, uint32_t height,
- heif_channel_datatype datatype, int bit_depth,
+ heif_component_datatype datatype, int bit_depth,
const heif_security_limits* limits);
+#endif
// Populate the cmpd component types table (decoder path).
- void set_cmpd_component_types(std::vector<uint16_t> types) { m_cmpd_component_types = std::move(types); }
+ //void set_cmpd_component_types(std::vector<uint16_t> types) { m_cmpd_component_types = std::move(types); }
- const std::vector<uint16_t>& get_cmpd_component_types() { return m_cmpd_component_types; }
+ //const std::vector<uint16_t>& get_cmpd_component_types() { return m_cmpd_component_types; }
// Returns the sorted list of component_indices of all planes that have pixel data.
- std::vector<uint32_t> get_used_component_indices() const;
+ std::vector<uint32_t> get_used_component_ids() const;
uint8_t* get_component(uint32_t component_idx, size_t* out_stride);
const uint8_t* get_component(uint32_t component_idx, size_t* out_stride) const;
@@ -473,7 +507,7 @@ public:
template <typename T>
T* get_component_data(uint32_t component_idx, size_t* out_stride)
{
- auto* comp = find_component_by_index(component_idx);
+ auto* comp = find_component_by_id(component_idx);
if (!comp) {
if (out_stride) *out_stride = 0;
return nullptr;
@@ -558,15 +592,15 @@ private:
// index into the cmpd component definition table
// Interleaved channels will have a list of indices in the order R,G,B,A
- std::vector<uint32_t> m_component_index;
+ std::vector<uint32_t> m_component_ids;
// limits=nullptr disables the limits
- Error alloc(uint32_t width, uint32_t height, heif_channel_datatype datatype, int bit_depth,
+ Error alloc(uint32_t width, uint32_t height, heif_component_datatype datatype, int bit_depth,
int num_interleaved_components,
const heif_security_limits* limits,
MemoryHandle& memory_handle);
- heif_channel_datatype m_datatype = heif_channel_datatype_unsigned_integer;
+ heif_component_datatype m_datatype = heif_component_datatype_unsigned_integer;
// logical bit depth per component
// For interleaved formats, it is the number of bits for one component.
@@ -600,8 +634,8 @@ private:
ImageComponent* find_component_for_channel(heif_channel channel);
const ImageComponent* find_component_for_channel(heif_channel channel) const;
- ImageComponent* find_component_by_index(uint32_t component_index);
- const ImageComponent* find_component_by_index(uint32_t component_index) const;
+ ImageComponent* find_component_by_id(uint32_t component_index);
+ const ImageComponent* find_component_by_id(uint32_t component_index) const;
ImageComponent new_image_plane_for_channel(heif_channel channel);
@@ -611,11 +645,16 @@ private:
heif_chroma m_chroma = heif_chroma_undefined;
std::vector<ImageComponent> m_planes;
- std::vector<uint16_t> m_cmpd_component_types; // indexed by cmpd index
+ //std::vector<uint16_t> m_cmpd_component_types; // indexed by cmpd index
MemoryHandle m_memory_handle;
+ // maps component_id to component_type (for all components, including cpat and all components in an interleaved plane)
+ std::map<uint32_t, uint16_t> m_component_types;
+
uint32_t m_sample_duration = 0; // duration of a sequence frame
+ uint32_t m_next_component_id = 1;
+
std::vector<Error> m_warnings;
};
diff --git a/libheif/sequences/track_visual.cc b/libheif/sequences/track_visual.cc
index ee982a26..3c3f11ad 100644
--- a/libheif/sequences/track_visual.cc
+++ b/libheif/sequences/track_visual.cc
@@ -158,7 +158,7 @@ bool Track_Visual::has_alpha_channel() const
if (sampleEntry) {
if (auto box_uncv = std::dynamic_pointer_cast<const Box_uncv>(sampleEntry)) {
if (auto cmpd = box_uncv->get_child_box<const Box_cmpd>()) {
- if (cmpd->has_component(heif_uncompressed_component_type_alpha)) {
+ if (cmpd->has_component(heif_unci_component_type_alpha)) {
return true;
}
}
diff --git a/tests/pixel_data_types.cc b/tests/pixel_data_types.cc
index e57ce733..244295c2 100644
--- a/tests/pixel_data_types.cc
+++ b/tests/pixel_data_types.cc
@@ -33,7 +33,7 @@ TEST_CASE( "uint32_t" )
auto* limits = heif_get_global_security_limits();
image.create(3,2, heif_colorspace_nonvisual, heif_chroma_undefined);
- image.add_channel(heif_channel_Y, 3,2, heif_channel_datatype_unsigned_integer, 32, limits);
+ image.add_channel(heif_channel_Y, 3,2, heif_component_datatype_unsigned_integer, 32, limits);
size_t stride;
uint32_t* data = image.get_channel<uint32_t>(heif_channel_Y, &stride);
@@ -43,7 +43,7 @@ TEST_CASE( "uint32_t" )
REQUIRE(image.get_height(heif_channel_Y) == 2);
REQUIRE(image.get_bits_per_pixel(heif_channel_Y) == 32);
REQUIRE(image.get_storage_bits_per_pixel(heif_channel_Y) == 32);
- REQUIRE(image.get_datatype(heif_channel_Y) == heif_channel_datatype_unsigned_integer);
+ REQUIRE(image.get_datatype(heif_channel_Y) == heif_component_datatype_unsigned_integer);
REQUIRE(image.get_number_of_interleaved_components(heif_channel_Y) == 1);
data[0*stride + 0] = 0;
@@ -128,7 +128,7 @@ TEST_CASE( "complex64_t" )
auto* limits = heif_get_global_security_limits();
image.create(3,2, heif_colorspace_nonvisual, heif_chroma_undefined);
- image.add_channel(heif_channel_Y, 3,2, heif_channel_datatype_complex_number, 128, limits);
+ image.add_channel(heif_channel_Y, 3,2, heif_component_datatype_complex_number, 128, limits);
size_t stride;
heif_complex64* data = image.get_channel<heif_complex64>(heif_channel_Y, &stride);
@@ -138,7 +138,7 @@ TEST_CASE( "complex64_t" )
REQUIRE(image.get_height(heif_channel_Y) == 2);
REQUIRE(image.get_bits_per_pixel(heif_channel_Y) == 128);
REQUIRE(image.get_storage_bits_per_pixel(heif_channel_Y) == 128);
- REQUIRE(image.get_datatype(heif_channel_Y) == heif_channel_datatype_complex_number);
+ REQUIRE(image.get_datatype(heif_channel_Y) == heif_component_datatype_complex_number);
REQUIRE(image.get_number_of_interleaved_components(heif_channel_Y) == 1);
data[0*stride + 0] = {0.0, -1.0};
@@ -160,7 +160,7 @@ TEST_CASE( "image datatype through public API" )
REQUIRE(!error.code);
uint32_t comp_idx;
- error = heif_image_add_component(image, 3, 2, 0, heif_channel_datatype_unsigned_integer, 32, &comp_idx);
+ error = heif_image_add_component(image, 3, 2, 0, heif_component_datatype_unsigned_integer, 32, &comp_idx);
REQUIRE(!error.code);
size_t stride;
diff --git a/tests/uncompressed_box.cc b/tests/uncompressed_box.cc
index 6f6d3a75..c65e1783 100644
--- a/tests/uncompressed_box.cc
+++ b/tests/uncompressed_box.cc
@@ -728,7 +728,7 @@ TEST_CASE("splz")
// Construct: 2 component indices, 2x1 pattern, angles 45.0 and 90.0
auto splz = std::make_shared<Box_splz>();
PolarizationPattern pattern;
- pattern.component_indices = {0, 1};
+ pattern.component_ids = {0, 1};
pattern.pattern_width = 2;
pattern.pattern_height = 1;
pattern.polarization_angles = {45.0f, 90.0f};
@@ -767,9 +767,9 @@ TEST_CASE("splz")
REQUIRE(parsed != nullptr);
const auto& p = parsed->get_pattern();
- REQUIRE(p.component_indices.size() == 2);
- REQUIRE(p.component_indices[0] == 0);
- REQUIRE(p.component_indices[1] == 1);
+ REQUIRE(p.component_ids.size() == 2);
+ REQUIRE(p.component_ids[0] == 0);
+ REQUIRE(p.component_ids[1] == 1);
REQUIRE(p.pattern_width == 2);
REQUIRE(p.pattern_height == 1);
REQUIRE(p.polarization_angles.size() == 2);
@@ -822,7 +822,7 @@ TEST_CASE("snuc")
// Construct: 1 component index, nuc_is_applied=true, 2x1 image, 2 gains + 2 offsets
auto snuc = std::make_shared<Box_snuc>();
SensorNonUniformityCorrection nuc;
- nuc.component_indices = {0};
+ nuc.component_ids = {0};
nuc.nuc_is_applied = true;
nuc.image_width = 2;
nuc.image_height = 1;
@@ -866,8 +866,8 @@ TEST_CASE("snuc")
REQUIRE(parsed != nullptr);
const auto& n = parsed->get_nuc();
- REQUIRE(n.component_indices.size() == 1);
- REQUIRE(n.component_indices[0] == 0);
+ REQUIRE(n.component_ids.size() == 1);
+ REQUIRE(n.component_ids[0] == 0);
REQUIRE(n.nuc_is_applied == true);
REQUIRE(n.image_width == 2);
REQUIRE(n.image_height == 1);
diff --git a/tests/uncompressed_encode_multicomponent.cc b/tests/uncompressed_encode_multicomponent.cc
index 3f8ce3ba..05e5c8af 100644
--- a/tests/uncompressed_encode_multicomponent.cc
+++ b/tests/uncompressed_encode_multicomponent.cc
@@ -241,7 +241,7 @@ const int8_t* get_component_ptr_readonly<int8_t>(const heif_image* image, uint32
template <typename T>
-static heif_image* create_and_fill_image(heif_channel_datatype datatype, int bit_depth)
+static heif_image* create_and_fill_image(heif_component_datatype datatype, int bit_depth)
{
heif_image* image = nullptr;
heif_error err;
@@ -332,7 +332,7 @@ static void verify_image_data(const heif_image* image)
template <typename T>
-static void test_multi_mono(heif_channel_datatype datatype, int bit_depth, const char* output_filename)
+static void test_multi_mono(heif_component_datatype datatype, int bit_depth, const char* output_filename)
{
heif_image* image = create_and_fill_image<T>(datatype, bit_depth);
@@ -380,57 +380,57 @@ static void test_multi_mono(heif_channel_datatype datatype, int bit_depth, const
TEST_CASE("Multi-mono uint8")
{
- test_multi_mono<uint8_t>(heif_channel_datatype_unsigned_integer, 8, "multi_mono_uint8.heif");
+ test_multi_mono<uint8_t>(heif_component_datatype_unsigned_integer, 8, "multi_mono_uint8.heif");
}
TEST_CASE("Multi-mono uint16")
{
- test_multi_mono<uint16_t>(heif_channel_datatype_unsigned_integer, 16, "multi_mono_uint16.heif");
+ test_multi_mono<uint16_t>(heif_component_datatype_unsigned_integer, 16, "multi_mono_uint16.heif");
}
TEST_CASE("Multi-mono uint12")
{
- test_multi_mono<uint16_t>(heif_channel_datatype_unsigned_integer, 12, "multi_mono_uint12.heif");
+ test_multi_mono<uint16_t>(heif_component_datatype_unsigned_integer, 12, "multi_mono_uint12.heif");
}
TEST_CASE("Multi-mono uint32")
{
- test_multi_mono<uint32_t>(heif_channel_datatype_unsigned_integer, 32, "multi_mono_uint32.heif");
+ test_multi_mono<uint32_t>(heif_component_datatype_unsigned_integer, 32, "multi_mono_uint32.heif");
}
TEST_CASE("Multi-mono int8")
{
- test_multi_mono<int8_t>(heif_channel_datatype_signed_integer, 8, "multi_mono_int8.heif");
+ test_multi_mono<int8_t>(heif_component_datatype_signed_integer, 8, "multi_mono_int8.heif");
}
TEST_CASE("Multi-mono int16")
{
- test_multi_mono<int16_t>(heif_channel_datatype_signed_integer, 16, "multi_mono_int16.heif");
+ test_multi_mono<int16_t>(heif_component_datatype_signed_integer, 16, "multi_mono_int16.heif");
}
TEST_CASE("Multi-mono int32")
{
- test_multi_mono<int32_t>(heif_channel_datatype_signed_integer, 32, "multi_mono_int32.heif");
+ test_multi_mono<int32_t>(heif_component_datatype_signed_integer, 32, "multi_mono_int32.heif");
}
TEST_CASE("Multi-mono float32")
{
- test_multi_mono<float>(heif_channel_datatype_floating_point, 32, "multi_mono_float32.heif");
+ test_multi_mono<float>(heif_component_datatype_floating_point, 32, "multi_mono_float32.heif");
}
TEST_CASE("Multi-mono float64")
{
- test_multi_mono<double>(heif_channel_datatype_floating_point, 64, "multi_mono_float64.heif");
+ test_multi_mono<double>(heif_component_datatype_floating_point, 64, "multi_mono_float64.heif");
}
TEST_CASE("Multi-mono complex32")
{
- test_multi_mono<heif_complex32>(heif_channel_datatype_complex_number, 64, "multi_mono_complex32.heif");
+ test_multi_mono<heif_complex32>(heif_component_datatype_complex_number, 64, "multi_mono_complex32.heif");
}
TEST_CASE("Multi-mono complex64")
{
- test_multi_mono<heif_complex64>(heif_channel_datatype_complex_number, 128, "multi_mono_complex64.heif");
+ test_multi_mono<heif_complex64>(heif_component_datatype_complex_number, 128, "multi_mono_complex64.heif");
}
@@ -455,13 +455,13 @@ TEST_CASE("Mixed bpp: 16-bit and 14-bit components")
// Add 16-bit component (byte-aligned)
uint32_t idx0 = 0;
err = heif_image_add_component(image, kW, kH, kMonoComponentType,
- heif_channel_datatype_unsigned_integer, kBpp16, &idx0);
+ heif_component_datatype_unsigned_integer, kBpp16, &idx0);
REQUIRE(err.code == heif_error_Ok);
// Add 14-bit component (non-byte-aligned)
uint32_t idx1 = 0;
err = heif_image_add_component(image, kW, kH, kMonoComponentType,
- heif_channel_datatype_unsigned_integer, kBpp14, &idx1);
+ heif_component_datatype_unsigned_integer, kBpp14, &idx1);
REQUIRE(err.code == heif_error_Ok);
// Fill 16-bit component