mod jpeg;
use jpeg::JPEGReader;
mod tiff;
use tiff::TIFFReader;
mod reader;
mod tags;
use image::ImageFormat;
use std::collections::HashMap;
use std::error::Error;
use std::path::Path;
pub use tags::IPTCTag;
#[derive(Default)]
pub struct IPTC {
pub data: HashMap<IPTCTag, Vec<String>>,
}
impl IPTC {
pub fn new() -> Self {
Self::default()
}
pub fn get_all(&self) -> HashMap<IPTCTag, Vec<String>> {
self.data.clone()
}
pub fn get(&self, tag: IPTCTag) -> String {
let returned_tag = self.data.get(&tag);
if returned_tag == None {
return String::new();
}
returned_tag.unwrap().join(", ")
}
pub fn set_tag(&mut self, tag: IPTCTag, value: &str) {
if let Some(values) = self.data.get_mut(&tag) {
if !values.contains(&value.to_string()) {
values.push(value.to_string());
}
} else {
self.data.insert(tag, vec![value.to_string()]);
}
}
pub fn write_to_buffer(&self, image_buffer: &[u8]) -> Result<Vec<u8>, Box<dyn Error>> {
let format = image::guess_format(image_buffer)?;
if format != ImageFormat::Jpeg {
return Err("Writing IPTC data is only supported for JPEG files".into());
}
JPEGReader::write_iptc(image_buffer, &self.data)
}
pub fn write_to_file(&self, image_path: &Path) -> Result<(), Box<dyn Error>> {
let buffer = std::fs::read(image_path)?;
let new_buffer = self.write_to_buffer(&buffer)?;
std::fs::write(image_path, new_buffer)?;
Ok(())
}
pub fn read_from_buffer(image_buffer: &[u8]) -> Result<Self, Box<dyn Error>> {
let format = image::guess_format(image_buffer)?;
let mut string_data = HashMap::new();
if format == ImageFormat::Jpeg {
string_data = JPEGReader::read_iptc(image_buffer)?;
} else if format == ImageFormat::Tiff {
println!("TIFF file detected, not all tags are supported");
string_data = TIFFReader::read_iptc(image_buffer)?;
} else {
println!("Unsupported file, only JPEG & Tiff files are supported");
}
let data = string_data.into_iter().map(|(k, v)| (k, vec![v])).collect();
Ok(IPTC { data })
}
pub fn read_from_path(image_path: &Path) -> Result<Self, Box<dyn Error>> {
let buffer = std::fs::read(image_path)?;
Self::read_from_buffer(&buffer)
}
}