feat: Enhance XMP writing capabilities with face region and tag support
This commit is contained in:
@@ -1,9 +1,15 @@
|
||||
use std::{io::Cursor, path::{Path, PathBuf}};
|
||||
use std::{
|
||||
io::Cursor,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use chrono::{DateTime, Datelike, NaiveDateTime, Utc};
|
||||
use nom_exif::{AsyncMediaParser, AsyncMediaSource, ExifIter, MediaParser, MediaSource, TrackInfo};
|
||||
|
||||
use crate::{error::{CoreError, CoreResult}, models::MediaMetadataSource};
|
||||
use crate::{
|
||||
error::{CoreError, CoreResult},
|
||||
models::MediaMetadataSource,
|
||||
};
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct ExtractedExif {
|
||||
@@ -26,9 +32,7 @@ pub fn parse_exif_datetime(s: &str) -> Option<DateTime<Utc>> {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn extract_exif_data_from_bytes(
|
||||
bytes: &[u8],
|
||||
) -> CoreResult<ExtractedExif> {
|
||||
pub fn extract_exif_data_from_bytes(bytes: &[u8]) -> CoreResult<ExtractedExif> {
|
||||
let ms = MediaSource::seekable(Cursor::new(bytes))
|
||||
.map_err(|e| CoreError::Unknown(format!("Failed to open bytes for EXIF: {}", e)))?;
|
||||
|
||||
@@ -54,7 +58,11 @@ pub fn extract_exif_data_from_bytes(
|
||||
v.to_string(),
|
||||
)),
|
||||
Err(e) => {
|
||||
println!("!! EXIF parsing error for tag 0x{:04x}: {}", x.tag_code(), e);
|
||||
println!(
|
||||
"!! EXIF parsing error for tag 0x{:04x}: {}",
|
||||
x.tag_code(),
|
||||
e
|
||||
);
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -83,7 +91,7 @@ pub fn extract_exif_data_from_bytes(
|
||||
}
|
||||
|
||||
pub async fn extract_exif_data(file_path: &Path) -> CoreResult<ExtractedExif> {
|
||||
let ms = AsyncMediaSource::file_path(file_path)
|
||||
let ms = AsyncMediaSource::file_path(file_path)
|
||||
.await
|
||||
.map_err(|e| CoreError::Unknown(format!("Failed to open file for EXIF: {}", e)))?;
|
||||
|
||||
@@ -146,10 +154,12 @@ pub fn get_storage_path_and_date(
|
||||
extracted_data: &ExtractedExif,
|
||||
filename: &str,
|
||||
) -> (PathBuf, Option<DateTime<Utc>>) {
|
||||
let date_taken_str = extracted_data.all_tags.iter()
|
||||
let date_taken_str = extracted_data
|
||||
.all_tags
|
||||
.iter()
|
||||
.find(|(source, tag_name, _)| {
|
||||
*source == MediaMetadataSource::Exif &&
|
||||
(tag_name == "DateTimeOriginal" || tag_name == "ModifyDate")
|
||||
*source == MediaMetadataSource::Exif
|
||||
&& (tag_name == "DateTimeOriginal" || tag_name == "ModifyDate")
|
||||
})
|
||||
.map(|(_, _, tag_value)| tag_value);
|
||||
|
||||
@@ -158,8 +168,25 @@ pub fn get_storage_path_and_date(
|
||||
|
||||
let year = file_date.year().to_string();
|
||||
let month = format!("{:02}", file_date.month());
|
||||
|
||||
|
||||
let storage_path = PathBuf::from(&year).join(&month).join(filename);
|
||||
|
||||
|
||||
(storage_path, date_taken)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_invalid_exif_tag(tag_name: &str, tag_value: &str) -> bool {
|
||||
if tag_name.starts_with("Unknown(") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if tag_value.starts_with("U16Array")
|
||||
|| tag_value.starts_with("U32Array")
|
||||
|| tag_value.starts_with("U8Array")
|
||||
|| tag_value.starts_with("URationalArray")
|
||||
|| tag_value.starts_with("Undefined")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
@@ -3,7 +3,13 @@ use std::sync::Arc;
|
||||
use async_trait::async_trait;
|
||||
|
||||
use crate::{
|
||||
config::AppConfig, error::CoreResult, models::Media, repositories::{AlbumRepository, MediaMetadataRepository, MediaRepository, UserRepository}
|
||||
config::AppConfig,
|
||||
error::CoreResult,
|
||||
models::Media,
|
||||
repositories::{
|
||||
AlbumRepository, FaceRegionRepository, MediaMetadataRepository, MediaRepository,
|
||||
PersonRepository, TagRepository, UserRepository,
|
||||
},
|
||||
};
|
||||
|
||||
pub struct PluginData {
|
||||
@@ -15,6 +21,9 @@ pub struct PluginContext {
|
||||
pub album_repo: Arc<dyn AlbumRepository>,
|
||||
pub user_repo: Arc<dyn UserRepository>,
|
||||
pub metadata_repo: Arc<dyn MediaMetadataRepository>,
|
||||
pub tag_repo: Arc<dyn TagRepository>,
|
||||
pub person_repo: Arc<dyn PersonRepository>,
|
||||
pub face_region_repo: Arc<dyn FaceRegionRepository>,
|
||||
pub media_library_path: String,
|
||||
pub config: Arc<AppConfig>,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user