|
1 |
| -use crate::ReadUtils; |
2 |
| -use crate::reader::read_iptc_data; |
3 |
| -use crate::tags::IPTCTag; |
| 1 | +use crate::{ReadUtils, tags}; |
4 | 2 | use std::collections::HashMap;
|
5 | 3 | use std::error::Error;
|
6 | 4 | use std::io::Cursor;
|
7 |
| -use tiff::decoder::Decoder; |
| 5 | +use tags::IPTCTag; |
| 6 | +use tiff::decoder::{Decoder, DecodingResult}; |
| 7 | +use xml::reader::{EventReader, XmlEvent}; |
8 | 8 |
|
9 | 9 | pub(crate) struct TIFFReader;
|
10 | 10 |
|
11 | 11 | impl TIFFReader {
|
12 | 12 | pub fn read_iptc(buffer: &Vec<u8>) -> Result<HashMap<IPTCTag, String>, Box<dyn Error>> {
|
13 | 13 | let cursor = Cursor::new(buffer);
|
14 |
| - let decoder = Decoder::new(cursor); |
| 14 | + let mut decoder = Decoder::new(cursor)?; |
| 15 | + |
| 16 | + while let Ok(Some(field)) = decoder.next_field() { |
| 17 | + if field.tag == 700 { |
| 18 | + if let DecodingResult::U8(data) = field.data { |
| 19 | + return read_xmp_data(&data); |
| 20 | + } |
| 21 | + } |
| 22 | + } |
15 | 23 |
|
16 | 24 | Ok(HashMap::new())
|
17 | 25 | }
|
18 | 26 | }
|
| 27 | + |
| 28 | +fn read_xmp_data(data: &[u8]) -> Result<HashMap<IPTCTag, String>, Box<dyn Error>> { |
| 29 | + let parser = EventReader::new(Cursor::new(data)); |
| 30 | + let mut iptc_data = HashMap::new(); |
| 31 | + let mut current_tag: Option<IPTCTag> = None; |
| 32 | + |
| 33 | + for event in parser { |
| 34 | + match event? { |
| 35 | + XmlEvent::StartElement { name, .. } => { |
| 36 | + current_tag = match name.local_name.as_str() { |
| 37 | + "creator" => Some(IPTCTag::ByLine), |
| 38 | + "title" => Some(IPTCTag::ByLineTitle), |
| 39 | + _ => None, |
| 40 | + }; |
| 41 | + } |
| 42 | + XmlEvent::Characters(data) => { |
| 43 | + if let Some(tag) = ¤t_tag { |
| 44 | + iptc_data.insert(tag.clone(), data); |
| 45 | + } |
| 46 | + } |
| 47 | + XmlEvent::EndElement { .. } => { |
| 48 | + current_tag = None; |
| 49 | + } |
| 50 | + _ => {} |
| 51 | + } |
| 52 | + } |
| 53 | + |
| 54 | + Ok(iptc_data) |
| 55 | +} |
0 commit comments