Commit 77ed03de for libheif
commit 77ed03dea8562ac6ace1ef487d9149741212d47d
Author: Dirk Farin <dirk.farin@gmail.com>
Date: Sun Dec 21 23:51:48 2025 +0100
item language 'elng' can be get/set using either plain items or text-items (#1559)
diff --git a/libheif/api/libheif/heif_items.cc b/libheif/api/libheif/heif_items.cc
index 09e9a1e2..2abdcf87 100644
--- a/libheif/api/libheif/heif_items.cc
+++ b/libheif/api/libheif/heif_items.cc
@@ -182,6 +182,50 @@ void heif_release_item_data(const heif_context* ctx, uint8_t** item_data)
}
+heif_error heif_item_get_property_extended_language(const heif_context* context,
+ heif_item_id itemId,
+ char** out_language)
+{
+ if (!out_language || !context) {
+ return {heif_error_Usage_error, heif_suberror_Invalid_parameter_value, "NULL passed"};
+ }
+
+ auto elng = context->context->find_property<Box_elng>(itemId);
+ if (!elng) {
+ return elng.error_struct(context->context.get());
+ }
+
+ std::string lang = (*elng)->get_extended_language();
+ *out_language = new char[lang.length() + 1];
+ strcpy(*out_language, lang.c_str());
+
+ return heif_error_success;
+}
+
+
+heif_error heif_item_set_extended_language(heif_context* context,
+ heif_item_id item_id,
+ const char* language, heif_property_id* out_optional_propertyId)
+{
+ if (!context || !language) {
+ return {heif_error_Usage_error, heif_suberror_Null_pointer_argument, "NULL passed"};
+ }
+
+ Result<heif_property_id> property_id_result = context->context->add_text_property(item_id,
+ language);
+
+ if (auto err = property_id_result.error()) {
+ return err.error_struct(context->context.get());
+ }
+
+ if (out_optional_propertyId) {
+ *out_optional_propertyId = *property_id_result;
+ }
+
+ return heif_error_success;
+}
+
+
size_t heif_context_get_item_references(const heif_context* ctx,
heif_item_id from_item_id,
int index,
diff --git a/libheif/api/libheif/heif_items.h b/libheif/api/libheif/heif_items.h
index 5448375b..1e179f0e 100644
--- a/libheif/api/libheif/heif_items.h
+++ b/libheif/api/libheif/heif_items.h
@@ -167,6 +167,27 @@ LIBHEIF_API
void heif_release_item_data(const heif_context* ctx, uint8_t** item_data);
+// ------------------------- item language -------------------------
+
+/**
+ * Get the extended language associated with the item.
+ * The item is usually a text item.
+ *
+ * @param context the heif file context containg the item.
+ * @param itemId the identifier for the item
+ * @param out_language output parameter with the item's language. Free with heif_string_release().
+ * @return heif_error_ok on success, or an error value indicating the problem
+ */
+LIBHEIF_API
+heif_error heif_item_get_property_extended_language(const heif_context* context,
+ heif_item_id itemId,
+ char** out_language);
+
+LIBHEIF_API
+heif_error heif_item_set_extended_language(heif_context* context,
+ heif_item_id item_id,
+ const char* language, heif_property_id* out_optional_propertyId);
+
// ------------------------- item references -------------------------
/**
diff --git a/libheif/api/libheif/heif_text.cc b/libheif/api/libheif/heif_text.cc
index 0b44d692..f4f3e204 100644
--- a/libheif/api/libheif/heif_text.cc
+++ b/libheif/api/libheif/heif_text.cc
@@ -117,17 +117,16 @@ const char* heif_text_item_get_content(heif_text_item* text_item)
return text_c;
}
-struct heif_error heif_item_get_property_extended_language(const heif_context* context,
- heif_item_id itemId,
- char** out_language)
+
+heif_error heif_text_item_get_property_extended_language(const heif_text_item* text_item, char** out_language)
{
- if (!out_language || !context) {
+ if (!out_language || !text_item) {
return {heif_error_Usage_error, heif_suberror_Invalid_parameter_value, "NULL passed"};
}
- auto elng = context->context->find_property<Box_elng>(itemId);
+ auto elng = text_item->context->find_property<Box_elng>(text_item->text_item->get_item_id());
if (!elng) {
- return elng.error_struct(context->context.get());
+ return elng.error_struct(text_item->context.get());
}
std::string lang = (*elng)->get_extended_language();
@@ -137,27 +136,22 @@ struct heif_error heif_item_get_property_extended_language(const heif_context* c
return heif_error_success;
}
-struct heif_error heif_text_item_set_extended_language(heif_text_item* text_item, const char *language, heif_property_id* out_optional_propertyId)
+
+heif_error heif_text_item_set_extended_language(heif_text_item* text_item, const char *language, heif_property_id* out_optional_propertyId)
{
if (!text_item || !language) {
return {heif_error_Usage_error, heif_suberror_Null_pointer_argument, "NULL passed"};
}
- if (auto img = text_item->context->get_image(text_item->text_item->get_item_id(), false)) {
- auto existing_elng = img->get_property<Box_elng>();
- if (existing_elng) {
- existing_elng->set_lang(std::string(language));
- return heif_error_success;
- }
- }
+ Result<heif_property_id> property_id_result = text_item->context->add_text_property(text_item->text_item->get_item_id(),
+ language);
- auto elng = std::make_shared<Box_elng>();
- elng->set_lang(std::string(language));
-
- heif_property_id id = text_item->context->add_property(text_item->text_item->get_item_id(), elng, false);
+ if (auto err = property_id_result.error()) {
+ return err.error_struct(text_item->context.get());
+ }
if (out_optional_propertyId) {
- *out_optional_propertyId = id;
+ *out_optional_propertyId = *property_id_result;
}
return heif_error_success;
diff --git a/libheif/api/libheif/heif_text.h b/libheif/api/libheif/heif_text.h
index e46e1487..943f4d1a 100644
--- a/libheif/api/libheif/heif_text.h
+++ b/libheif/api/libheif/heif_text.h
@@ -104,17 +104,16 @@ LIBHEIF_API
const char* heif_text_item_get_content(heif_text_item* text_item);
/**
- * Get the extended language associated with the text item.
+ * This function is similar to heif_item_get_property_extended_language(), but
+ * takes a `heif_text_item` as parameter.
*
- * @param context the context to get the text item from, usually from a file operation
- * @param itemId the identifier for the text item
- * @param out_language pointer to pointer to the resulting language
- * @return heif_error_ok on success, or an error value indicating the problem
+ * @param text_item The text item for which we are requesting the language.
+ * @param out_language Output parameter for the text language. Free with heif_string_release().
+ * @return
*/
LIBHEIF_API
-heif_error heif_item_get_property_extended_language(const heif_context* context,
- heif_item_id itemId,
- char** out_language);
+heif_error heif_text_item_get_property_extended_language(const heif_text_item* text_item,
+ char** out_language);
// --- adding text items
diff --git a/libheif/context.cc b/libheif/context.cc
index e5f3d2fa..a9b3143b 100644
--- a/libheif/context.cc
+++ b/libheif/context.cc
@@ -1844,6 +1844,24 @@ Result<heif_item_id> HeifContext::add_pyramid_group(const std::vector<heif_item_
}
+Result<heif_property_id> HeifContext::add_text_property(heif_item_id itemId, const std::string& language)
+{
+ if (find_property<Box_elng>(itemId)) {
+ return Error{
+ heif_error_Usage_error,
+ heif_suberror_Unspecified,
+ "Item already has an 'elng' language property."
+ };
+ }
+
+ auto elng = std::make_shared<Box_elng>();
+ elng->set_lang(std::string(language));
+
+ heif_property_id id = add_property(itemId, elng, false);
+ return id;
+}
+
+
Error HeifContext::interpret_heif_file_sequences()
{
m_tracks.clear();
diff --git a/libheif/context.h b/libheif/context.h
index ae3c8148..af1359cc 100644
--- a/libheif/context.h
+++ b/libheif/context.h
@@ -165,6 +165,9 @@ public:
Result<heif_item_id> add_pyramid_group(const std::vector<heif_item_id>& layers);
+ Result<heif_property_id> add_text_property(heif_item_id, const std::string& language);
+
+
// --- region items
void add_region_item(std::shared_ptr<RegionItem> region_item)
@@ -271,6 +274,14 @@ public:
return result;
}
+ template<typename T>
+ bool has_property(heif_item_id itemId) const
+ {
+ auto file = this->get_heif_file();
+ auto result = file->get_property_for_item<T>(itemId);
+ return result != nullptr;
+ }
+
private:
std::map<heif_item_id, std::shared_ptr<ImageItem>> m_all_images;