Update exif module

This commit is contained in:
2023-03-27 07:19:55 +00:00
committed by GitHub
parent b8a8b5fa6f
commit f80fd2efae
4 changed files with 234 additions and 39 deletions

View File

@@ -23,6 +23,8 @@ typedef struct ExifDataItor ExifDataItor;
typedef struct ExifDatumRef ExifDatumRef;
/// <div rustbindgen opaque></div>
typedef struct ExifValueRef ExifValueRef;
/// <div rustbindgen opaque></div>
typedef struct ExifDataMutItor ExifDataMutItor;
#if defined _WIN32 && defined WIN32_DLL
#if BUILD_DLL
#define EXIF_API __declspec(dllexport)
@@ -65,7 +67,7 @@ EXIF_API char* exif_value_to_string2(ExifValueRef* value, size_t* len, long i);
EXIF_API int64_t exif_value_to_int64(ExifValueRef* value, long i);
EXIF_API ExifValue* exif_value_ref_clone(ExifValueRef* value);
EXIF_API ExifData* exif_data_new();
EXIF_API int exif_data_ref_add(ExifDataRef* d, ExifKey* key, ExifValue* value);
EXIF_API int exif_data_ref_add(ExifDataRef* d, ExifKey* key, ExifValueRef* 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);
@@ -74,13 +76,18 @@ EXIF_API long exif_data_ref_get_count(ExifDataRef* d);
EXIF_API void exif_data_ref_sort_by_key(ExifDataRef* d);
EXIF_API void exif_data_ref_sort_by_tag(ExifDataRef* d);
EXIF_API ExifDataItor* exif_data_ref_iter(ExifDataRef* d);
EXIF_API ExifDataMutItor* exif_data_ref_iter_mut(ExifDataRef* d);
EXIF_API ExifDatumRef* exif_data_itor_next(ExifDataItor* itor);
EXIF_API ExifDatumRef* exif_data_itor_next_back(ExifDataItor* itor);
EXIF_API ExifDatumRef* exif_data_mutitor_next(ExifDataMutItor* itor);
EXIF_API ExifDatumRef* exif_data_mutitor_next_back(ExifDataMutItor* itor);
EXIF_API char* exif_datum_key(ExifDatumRef* d);
EXIF_API ExifValueRef* exif_datum_value(ExifDatumRef *d);
EXIF_API void exif_datum_set_value(ExifDatumRef* d, ExifValueRef* v);
EXIF_API void exif_free_value(ExifValue* value);
EXIF_API void exif_free_data(ExifData* d);
EXIF_API void exif_free_data_itor(ExifDataItor* itor);
EXIF_API void exif_free_data_mutitor(ExifDataMutItor* itor);
#ifdef __cplusplus
}
#endif

View File

@@ -283,10 +283,11 @@ ExifData* exif_data_new() {
return new ExifData;
}
int exif_data_ref_add(ExifDataRef* d, ExifKey* key, ExifValue* value) {
int exif_data_ref_add(ExifDataRef* d, ExifKey* key, ExifValueRef* value) {
if (!d || !key || !value || !key->key) return 0;
auto data = (Exiv2::ExifData*)d;
data->add(*key->key, value->value.get());
auto v = (Exiv2::Value*)value;
data->add(*key->key, v);
return 1;
}
@@ -362,6 +363,15 @@ ExifDataItor* exif_data_ref_iter(ExifDataRef* d) {
return re;
}
ExifDataMutItor* exif_data_ref_iter_mut(ExifDataRef* d) {
if (!d) return nullptr;
auto re = new ExifDataMutItor;
re->ref = (Exiv2::ExifData*)d;
re->itor = re->ref->begin();
re->end = re->ref->end();
return re;
}
void exif_free_data_itor(ExifDataItor* itor) {
if (!itor) return;
delete itor;
@@ -383,6 +393,22 @@ ExifDatumRef* exif_data_itor_next_back(ExifDataItor* itor) {
return (ExifDatumRef*)&data;
}
ExifDatumRef* exif_data_mutitor_next(ExifDataMutItor* itor) {
if (!itor->ref) return nullptr;
if (itor->itor == itor->end) return nullptr;
auto& data = (*itor->itor);
itor->itor++;
return (ExifDatumRef*)&data;
}
ExifDatumRef* exif_data_mutitor_next_back(ExifDataMutItor* itor) {
if (!itor->ref) return nullptr;
if (itor->itor == itor->end) return nullptr;
itor->end--;
auto& data = (*itor->end);
return (ExifDatumRef*)&data;
}
char* exif_datum_key(ExifDatumRef* d) {
if (!d) return nullptr;
auto data = (Exiv2::Exifdatum*)d;
@@ -401,3 +427,15 @@ ExifValueRef* exif_datum_value(ExifDatumRef *d) {
return nullptr;
}
}
void exif_free_data_mutitor(ExifDataMutItor* itor) {
if (!itor) return;
delete itor;
}
void exif_datum_set_value(ExifDatumRef* d, ExifValueRef* v) {
if (!d || !v) return;
auto da = (Exiv2::Exifdatum*)d;
auto va = (Exiv2::Value*)v;
da->setValue(va);
}

View File

@@ -22,4 +22,9 @@ typedef struct ExifDataItor {
Exiv2::ExifMetadata::const_iterator itor;
Exiv2::ExifMetadata::const_iterator end;
} ExifDataItor;
typedef struct ExifDataMutItor {
Exiv2::ExifData* ref;
Exiv2::ExifMetadata::iterator itor;
Exiv2::ExifMetadata::iterator end;
} ExifDataMutItor;
#endif

View File

@@ -1,5 +1,5 @@
use crate::_exif;
use crate::_exif::{ExifDataRef, ExifDatumRef, ExifValueRef};
pub use crate::_exif::{ExifDataRef, ExifDatumRef, ExifValueRef};
use crate::ext::rawhandle::FromRawHandle;
use crate::ext::rawhandle::ToRawHandle;
use c_fixed_string::CFixedStr;
@@ -16,7 +16,7 @@ use std::ffi::OsStr;
use std::fs::copy;
#[cfg(test)]
use std::fs::create_dir;
use std::iter::{DoubleEndedIterator, Iterator};
use std::iter::{DoubleEndedIterator, ExactSizeIterator, Iterator};
use std::marker::PhantomData;
use std::ops::Deref;
use std::ops::DerefMut;
@@ -595,6 +595,16 @@ impl ExifDatumRef {
Some(s.to_owned())
}
/// Set the value.
pub fn set_value<'a>(&'a mut self, value: &ExifValueRef) {
let data = unsafe { self.to_raw_handle() };
let v = unsafe { value.to_raw_handle() };
if data.is_null() || v.is_null() {
return;
}
unsafe { _exif::exif_datum_set_value(data, v) }
}
/// Return a constant reference to the value.
///
/// This method is provided mostly for convenient and versatile output of the value which can (to some extent) be formatted through standard stream manipulators.
@@ -689,7 +699,7 @@ impl ToRawHandle<_exif::ExifData> for ExifData {
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<(), ()> {
pub fn add(&mut self, key: &ExifKey, value: &ExifValueRef) -> Result<(), ()> {
let data = unsafe { self.to_raw_handle() };
let k = unsafe { key.to_raw_handle() };
let v = unsafe { value.to_raw_handle() };
@@ -750,12 +760,44 @@ impl ExifDataRef {
pub fn iter<'a>(&'a self) -> Option<ExifDataItor<'a>> {
let data = unsafe { self.to_raw_handle() };
let count = match self.count() {
Some(count) => count,
None => {
return None;
}
};
if data.is_null() {
return None;
}
let r = unsafe { _exif::exif_data_ref_iter(data) };
if r.is_null() {
return None;
}
Some(ExifDataItor {
itor: r,
count,
phantom: PhantomData,
})
}
pub fn iter_mut<'a>(&'a mut self) -> Option<ExifDataMutItor<'a>> {
let data = unsafe { self.to_raw_handle() };
let count = match self.count() {
Some(count) => count,
None => {
return None;
}
};
if data.is_null() {
return None;
}
let r = unsafe { _exif::exif_data_ref_iter_mut(data) };
if r.is_null() {
return None;
}
Some(ExifDataMutItor {
itor: r,
count,
phantom: PhantomData,
})
}
@@ -803,6 +845,7 @@ impl ToRawHandle<ExifDataRef> for ExifDataRef {
pub struct ExifDataItor<'a> {
itor: *mut _exif::ExifDataItor,
count: usize,
phantom: PhantomData<&'a _exif::ExifDataItor>,
}
@@ -842,6 +885,60 @@ impl<'a> DoubleEndedIterator for ExifDataItor<'a> {
}
}
impl<'a> ExactSizeIterator for ExifDataItor<'a> {
fn len(&self) -> usize {
self.count
}
}
pub struct ExifDataMutItor<'a> {
itor: *mut _exif::ExifDataMutItor,
count: usize,
phantom: PhantomData<&'a mut _exif::ExifDataMutItor>,
}
impl<'a> Drop for ExifDataMutItor<'a> {
fn drop(&mut self) {
if !self.itor.is_null() {
unsafe { _exif::exif_free_data_mutitor(self.itor) };
self.itor = std::ptr::null_mut();
}
}
}
impl<'a> Iterator for ExifDataMutItor<'a> {
type Item = &'a mut ExifDatumRef;
fn next(&mut self) -> Option<Self::Item> {
if self.itor.is_null() {
return None;
}
let r = unsafe { _exif::exif_data_mutitor_next(self.itor) };
if r.is_null() {
return None;
}
Some(unsafe { ExifDatumRef::from_raw_handle(r) })
}
}
impl<'a> DoubleEndedIterator for ExifDataMutItor<'a> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.itor.is_null() {
return None;
}
let r = unsafe { _exif::exif_data_mutitor_next_back(self.itor) };
if r.is_null() {
return None;
}
Some(unsafe { ExifDatumRef::from_raw_handle(r) })
}
}
impl<'a> ExactSizeIterator for ExifDataMutItor<'a> {
fn len(&self) -> usize {
self.count
}
}
/// An image
pub struct ExifImage {
img: *mut _exif::ExifImage,
@@ -1043,43 +1140,91 @@ fn test_exif_data() {
v2.read("p1".as_bytes(), None).unwrap();
d.add(&k2, &v2).unwrap();
assert_eq!(Some(2), d.count());
let mut i = d.iter().unwrap();
let f = i.next().unwrap();
assert_eq!(f.key(), Some(String::from("Exif.Image.XPTitle")));
assert_eq!(
i.next().unwrap().key(),
Some(String::from("Exif.Image.PageName"))
);
assert!(i.next().is_none());
let mut i = 0;
for data in d.iter().unwrap() {
i += 1;
match data.key().unwrap().as_str() {
"Exif.Image.PageName" => {
assert_eq!(i, 2);
let v = data.value().unwrap();
assert_eq!(v.to_string(None), Some(CString::new("p1").unwrap()));
{
let mut i = d.iter().unwrap();
let f = i.next().unwrap();
assert_eq!(f.key(), Some(String::from("Exif.Image.XPTitle")));
assert_eq!(
i.next().unwrap().key(),
Some(String::from("Exif.Image.PageName"))
);
assert!(i.next().is_none());
let mut i = 0;
for data in d.iter().unwrap() {
i += 1;
match data.key().unwrap().as_str() {
"Exif.Image.PageName" => {
assert_eq!(i, 2);
let v = data.value().unwrap();
assert_eq!(v.to_string(None), Some(CString::new("p1").unwrap()));
}
"Exif.Image.XPTitle" => assert_eq!(i, 1),
_ => {}
}
"Exif.Image.XPTitle" => assert_eq!(i, 1),
}
assert_eq!(i, 2);
let mut i = d.iter().unwrap();
let f = i.next().unwrap();
let f2 = i.next().unwrap();
assert_eq!(f.key(), Some(String::from("Exif.Image.XPTitle")));
assert_eq!(f2.key(), Some(String::from("Exif.Image.PageName")));
let mut i = d.iter().unwrap();
assert_eq!(
i.next_back().unwrap().key(),
Some(String::from("Exif.Image.PageName"))
);
assert_eq!(
i.next().unwrap().key(),
Some(String::from("Exif.Image.XPTitle"))
);
assert!(i.next().is_none());
assert_eq!(
d.iter().unwrap().position(|d| match d.key() {
Some(key) => {
match key.as_str() {
"Exif.Image.PageName" => true,
_ => false,
}
}
None => false,
}),
Some(1)
);
assert_eq!(
d.iter().unwrap().rposition(|d| match d.key() {
Some(key) => {
match key.as_str() {
"Exif.Image.XPTitle" => true,
_ => false,
}
}
None => false,
}),
Some(0)
);
}
for i in d.iter_mut().unwrap() {
match i.key() {
Some(key) => match key.as_str() {
"Exif.Image.PageName" => {
let mut v = ExifValue::try_from(ExifTypeID::AsciiString).unwrap();
v.read("p2".as_bytes(), None).unwrap();
i.set_value(&v);
}
_ => {}
},
_ => {}
}
}
assert_eq!(i, 2);
let mut i = d.iter().unwrap();
let f = i.next().unwrap();
let f2 = i.next().unwrap();
assert_eq!(f.key(), Some(String::from("Exif.Image.XPTitle")));
assert_eq!(f2.key(), Some(String::from("Exif.Image.PageName")));
let mut i = d.iter().unwrap();
assert_eq!(
i.next_back().unwrap().key(),
Some(String::from("Exif.Image.PageName"))
);
assert_eq!(
i.next().unwrap().key(),
Some(String::from("Exif.Image.XPTitle"))
);
assert!(i.next().is_none());
let p = d
.iter()
.unwrap()
.nth(1)
.unwrap()
.value()
.unwrap()
.to_string(None);
assert_eq!(p, Some(CString::new("p2").unwrap()));
}
#[test]