ExifImage support to modify current buffered ExifData

This commit is contained in:
2022-05-14 07:45:43 +08:00
parent 8e5b24bef2
commit 886f05aa12
4 changed files with 79 additions and 45 deletions

View File

@@ -28,7 +28,7 @@ typedef struct ExifDataRef ExifDataRef;
#endif
EXIF_API ExifImage* create_exif_image(const char* path);
EXIF_API const ExifDataRef* exif_image_get_exif_data(ExifImage* image);
EXIF_API ExifDataRef* exif_image_get_exif_data(ExifImage* image);
EXIF_API int exif_image_set_exif_data(ExifImage* image, ExifData* data);
EXIF_API int exif_image_write_metadata(ExifImage* image);
EXIF_API void free_exif_image(ExifImage* img);
@@ -55,9 +55,9 @@ EXIF_API char* exif_value_to_string(ExifValue* value, size_t* len);
EXIF_API char* exif_value_to_string2(ExifValue* value, size_t* len, long i);
EXIF_API int64_t exif_value_to_int64(ExifValue* value, long i);
EXIF_API ExifData* exif_data_new();
EXIF_API int exif_data_add(ExifData* d, ExifKey* key, ExifValue* value);
EXIF_API int exif_data_clear(ExifData* d);
EXIF_API const ExifDataRef* exif_data_get_ref(ExifData* d);
EXIF_API int exif_data_ref_add(ExifDataRef* d, ExifKey* key, ExifValue* value);
EXIF_API int exif_data_ref_clear(ExifDataRef* d);
EXIF_API ExifDataRef* exif_data_get_ref(ExifData* d);
EXIF_API ExifData* exif_data_ref_clone(ExifDataRef* d);
EXIF_API int exif_data_ref_is_empty(ExifDataRef* d);
EXIF_API long exif_data_ref_get_count(ExifDataRef* d);

View File

@@ -24,7 +24,7 @@ end:
return nullptr;
}
const ExifDataRef* exif_image_get_exif_data(ExifImage* image) {
ExifDataRef* exif_image_get_exif_data(ExifImage* image) {
if (!image || !image->image) return nullptr;
image->exif_data_ref.data = &image->image->exifData();
return &image->exif_data_ref;
@@ -224,19 +224,19 @@ ExifData* exif_data_new() {
return new ExifData;
}
int exif_data_add(ExifData* d, ExifKey* key, ExifValue* value) {
if (!d || !key || !value || !key->key) return 0;
d->data.add(*key->key, value->value.get());
int exif_data_ref_add(ExifDataRef* d, ExifKey* key, ExifValue* value) {
if (!d || !d->data || !key || !value || !key->key) return 0;
d->data->add(*key->key, value->value.get());
return 1;
}
int exif_data_clear(ExifData* d) {
if (!d) return 0;
d->data.clear();
int exif_data_ref_clear(ExifDataRef* d) {
if (!d || !d->data) return 0;
d->data->clear();
return 1;
}
const ExifDataRef* exif_data_get_ref(ExifData* d) {
ExifDataRef* exif_data_get_ref(ExifData* d) {
if (!d) return nullptr;
d->ref.data = &d->data;
return &d->ref;

View File

@@ -2,7 +2,7 @@
#define _EXIF_EXIF_PRIV_H
#include "exiv2/exiv2.hpp"
typedef struct ExifDataRef {
const Exiv2::ExifData* data = nullptr;
Exiv2::ExifData* data = nullptr;
} ExifDataRef;
typedef struct ExifImage {
Exiv2::Image::UniquePtr image;

View File

@@ -5,6 +5,7 @@ use crate::ext::rawhandle::ToRawHandle;
use c_fixed_string::CFixedStr;
use int_enum::IntEnum;
use std::borrow::Borrow;
use std::borrow::BorrowMut;
use std::borrow::ToOwned;
use std::clone::Clone;
use std::convert::TryFrom;
@@ -16,6 +17,7 @@ use std::fs::copy;
#[cfg(test)]
use std::fs::create_dir;
use std::ops::Deref;
use std::ops::DerefMut;
use std::ops::Drop;
use std::os::raw::c_long;
use std::path::Path;
@@ -509,36 +511,6 @@ impl ExifData {
pub unsafe fn from_raw_pointer(data: *mut _exif::ExifData) -> Self {
Self { data }
}
/// Add a data from the supplied key and value pair.
/// No duplicate checks are performed, i.e., it is possible to add multiple metadata with the same key.
pub fn add(&mut self, key: &ExifKey, value: &ExifValue) -> Result<(), ()> {
let k = unsafe { key.to_raw_handle() };
let v = unsafe { value.to_raw_handle() };
if k.is_null() || v.is_null() {
return Err(());
}
let r = unsafe { _exif::exif_data_add(self.data, k, v) };
if r == 0 {
Err(())
} else {
Ok(())
}
}
/// Delete all Exifdatum instances resulting in an empty container.
/// Note that this also removes thumbnails.
pub fn clear(&mut self) -> Result<(), ()> {
if self.data.is_null() {
return Err(());
}
let r = unsafe { _exif::exif_data_clear(self.data) };
if r == 0 {
Err(())
} else {
Ok(())
}
}
}
impl Borrow<ExifDataRef> for ExifData {
@@ -547,10 +519,22 @@ impl Borrow<ExifDataRef> for ExifData {
}
}
impl BorrowMut<ExifDataRef> for ExifData {
fn borrow_mut(&mut self) -> &mut ExifDataRef {
self.deref_mut()
}
}
impl Deref for ExifData {
type Target = ExifDataRef;
fn deref(&self) -> &Self::Target {
unsafe { ExifDataRef::from_const_handle(_exif::exif_data_get_ref(self.to_raw_handle())) }
unsafe { ExifDataRef::from_const_handle(_exif::exif_data_get_ref(self.to_raw_handle()) as *const ExifDataRef) }
}
}
impl DerefMut for ExifData {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { ExifDataRef::from_raw_handle(_exif::exif_data_get_ref(self.to_raw_handle())) }
}
}
@@ -570,6 +554,38 @@ impl ToRawHandle<_exif::ExifData> for ExifData {
#[allow(dead_code)]
impl ExifDataRef {
/// Add a data from the supplied key and value pair.
/// No duplicate checks are performed, i.e., it is possible to add multiple metadata with the same key.
pub fn add(&mut self, key: &ExifKey, value: &ExifValue) -> Result<(), ()> {
let data = unsafe { self.to_raw_handle() };
let k = unsafe { key.to_raw_handle() };
let v = unsafe { value.to_raw_handle() };
if k.is_null() || v.is_null() || data.is_null() {
return Err(());
}
let r = unsafe { _exif::exif_data_ref_add(data, k, v) };
if r == 0 {
Err(())
} else {
Ok(())
}
}
/// Delete all Exifdatum instances resulting in an empty container.
/// Note that this also removes thumbnails.
pub fn clear(&mut self) -> Result<(), ()> {
let data = unsafe { self.to_raw_handle() };
if data.is_null() {
return Err(());
}
let r = unsafe { _exif::exif_data_ref_clear(data) };
if r == 0 {
Err(())
} else {
Ok(())
}
}
/// Get the number of metadata entries.
pub fn count(&self) -> Option<usize> {
let data = unsafe { self.to_raw_handle() };
@@ -665,7 +681,20 @@ impl ExifImage {
if d.is_null() {
return None;
}
unsafe { Some(ExifDataRef::from_const_handle(d)) }
unsafe { Some(ExifDataRef::from_const_handle(d as *const ExifDataRef)) }
}
/// Returns an ExifData instance containing currently buffered Exif data.
/// The Exif data in the returned instance will be written to the image when [Self::write_metadata()] is called.
pub fn exif_data_as_mut(&mut self) -> Option<&mut ExifDataRef> {
if self.img.is_null() {
return None;
}
let d = unsafe { _exif::exif_image_get_exif_data(self.img) };
if d.is_null() {
return None;
}
unsafe { Some(ExifDataRef::from_raw_handle(d)) }
}
/// Assign new Exif data.
@@ -793,6 +822,11 @@ fn test_exif_image() {
let mut img = ExifImage::new(target).unwrap();
img.set_exif_data(&d).unwrap();
assert_eq!(img.exif_data().unwrap().count(), Some(1));
let k = ExifKey::try_from("Exif.Image.Artist").unwrap();
let mut v = ExifValue::try_from(ExifTypeID::AsciiString).unwrap();
v.read("L.H.B".as_bytes(), None).unwrap();
img.exif_data_as_mut().unwrap().add(&k, &v).unwrap();
assert_eq!(img.exif_data().unwrap().count(), Some(2));
img.write_metadata().unwrap();
}
}