mirror of
https://github.com/lifegpc/pixiv_downloader.git
synced 2026-06-15 18:34:34 +08:00
Update exif module
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
217
src/exif.rs
217
src/exif.rs
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user