Update exif module

This commit is contained in:
2022-05-13 15:25:27 +08:00
parent 3868d69d23
commit cbbec08db6
8 changed files with 149 additions and 31 deletions

View File

@@ -1,7 +1,12 @@
use crate::_exif;
use crate::_exif::ExifDataRef;
use crate::ext::rawhandle::FromRawHandle;
use crate::ext::rawhandle::ToRawHandle;
use c_fixed_string::CFixedStr;
use int_enum::IntEnum;
use std::borrow::Borrow;
use std::borrow::ToOwned;
use std::clone::Clone;
use std::convert::TryFrom;
use std::ffi::CStr;
use std::ffi::CString;
@@ -10,6 +15,7 @@ use std::ffi::OsStr;
use std::fs::copy;
#[cfg(test)]
use std::fs::create_dir;
use std::ops::Deref;
use std::ops::Drop;
use std::os::raw::c_long;
use std::path::Path;
@@ -500,6 +506,10 @@ impl ExifData {
Ok(Self { data: d })
}
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<(), ()> {
@@ -529,32 +539,18 @@ impl ExifData {
Ok(())
}
}
}
/// Get the number of metadata entries.
pub fn count(&self) -> Option<usize> {
if self.data.is_null() {
return None;
}
let r = unsafe { _exif::exif_data_get_count(self.data) };
if r == -1 {
return None;
}
Some(r as usize)
impl Borrow<ExifDataRef> for ExifData {
fn borrow(&self) -> &ExifDataRef {
self.deref()
}
}
/// Return true if there is no Exif metadata.
pub fn empty(&self) -> Option<bool> {
if self.data.is_null() {
return None;
}
let r = unsafe { _exif::exif_data_is_empty(self.data) };
if r == -1 {
None
} else if r == 0 {
Some(false)
} else {
Some(true)
}
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())) }
}
}
@@ -572,6 +568,61 @@ impl ToRawHandle<_exif::ExifData> for ExifData {
}
}
#[allow(dead_code)]
impl ExifDataRef {
/// Get the number of metadata entries.
pub fn count(&self) -> Option<usize> {
let data = unsafe { self.to_raw_handle() };
if data.is_null() {
return None;
}
let r = unsafe { _exif::exif_data_ref_get_count(data) };
if r == -1 {
return None;
}
Some(r as usize)
}
/// Return true if there is no Exif metadata.
pub fn empty(&self) -> Option<bool> {
let data = unsafe { self.to_raw_handle() };
if data.is_null() {
return None;
}
let r = unsafe { _exif::exif_data_ref_is_empty(data) };
if r == -1 {
None
} else if r == 0 {
Some(false)
} else {
Some(true)
}
}
}
impl ToOwned for ExifDataRef {
type Owned = ExifData;
fn to_owned(&self) -> Self::Owned {
let o = unsafe { self.to_raw_handle() };
if o.is_null() {
return ExifData::new().unwrap();
}
let r = unsafe { _exif::exif_data_ref_clone(o) };
if r.is_null() {
panic!("Failed to convert ExifDataRef to ExifData.");
}
unsafe { ExifData::from_raw_pointer(r) }
}
}
impl ToRawHandle<ExifDataRef> for ExifDataRef {
unsafe fn to_raw_handle(&self) -> *mut ExifDataRef {
self.to_const_handle() as *mut ExifDataRef
}
unsafe fn to_const_handle(&self) -> *const ExifDataRef {
self
}
}
pub struct ExifImage {
img: *mut _exif::ExifImage,
}
@@ -600,6 +651,17 @@ impl ExifImage {
Ok(Self { img: f })
}
pub fn exif_data(&self) -> Option<&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_const_handle(d)) }
}
pub fn set_exif_data(&mut self, data: &ExifData) -> Result<(), ()> {
if self.img.is_null() {
return Err(());
@@ -715,6 +777,7 @@ 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));
img.write_metadata().unwrap();
}
}

View File

@@ -8,3 +8,17 @@ pub trait ToRawHandle<T> {
self.to_raw_handle() as *const T
}
}
pub trait FromRawHandle<T> {
unsafe fn from_raw_handle<'a>(ptr: *mut T) -> &'a mut Self;
unsafe fn from_const_handle<'a>(ptr: *const T) -> &'a Self;
}
impl<T> FromRawHandle<Self> for T {
unsafe fn from_raw_handle<'a>(ptr: *mut T) -> &'a mut Self {
&mut *(ptr)
}
unsafe fn from_const_handle<'a>(ptr: *const Self) -> &'a Self {
&*(ptr)
}
}