Skip to content

Commit b419e58

Browse files
committed
Basic format detection and factory
1 parent 26c81dc commit b419e58

File tree

13 files changed

+416
-16
lines changed

13 files changed

+416
-16
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ edition = "2021"
77

88
[dependencies]
99
# mp4 = { path = "lib/mp4", version = "0.1.0" }
10-
10+
lazy_static = "1.4.0"
1111

1212
[workspace]
1313
members = [

src/cr3.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
1+
use super::rawfile::ReadAndSeek;
12
use super::{Error, RawFile, RawFileImpl, Result, Type, TypeId};
23
use crate::thumbnail::Thumbnail;
34

45
/// Canon CR3 File
5-
pub struct Cr3File {}
6+
pub struct Cr3File {
7+
reader: Box<dyn ReadAndSeek>,
8+
}
9+
10+
impl Cr3File {
11+
pub fn factory(reader: Box<dyn ReadAndSeek>) -> Box<dyn RawFile> {
12+
Box::new(Cr3File { reader })
13+
}
14+
}
615

716
impl RawFileImpl for Cr3File {
817
fn identify_id(&self) -> TypeId {
918
0
1019
}
1120

12-
fn thumbnail_for_size(&self, size: u32) -> Result<Thumbnail> {
21+
fn thumbnail_for_size(&self, _size: u32) -> Result<Thumbnail> {
1322
Err(Error::NotSupported)
1423
}
1524

src/factory.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* libopenraw - factory.rs
3+
*
4+
* Copyright (C) 2022 Hubert Figuière
5+
*
6+
* This library is free software: you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public License
8+
* as published by the Free Software Foundation, either version 3 of
9+
* the License, or (at your option) any later version.
10+
*
11+
* This library is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public
17+
* License along with this library. If not, see
18+
* <http://www.gnu.org/licenses/>.
19+
*/
20+
21+
use std::collections::HashMap;
22+
23+
use super::cr3::Cr3File;
24+
use super::rawfile::RawFileFactory;
25+
use super::Type;
26+
27+
lazy_static::lazy_static! {
28+
static ref FACTORY_MAP: HashMap<Type, RawFileFactory> = {
29+
let mut m = HashMap::new();
30+
31+
m.insert(Type::Cr3, Cr3File::factory as RawFileFactory);
32+
33+
m
34+
};
35+
}
36+
37+
pub fn get_raw_file_factory(t: Type) -> Option<&'static RawFileFactory> {
38+
FACTORY_MAP.get(&t)
39+
}

src/identify.rs

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*
2+
* libopenraw - identify.rs
3+
*
4+
* Copyright (C) 2022 Hubert Figuière
5+
*
6+
* This library is free software: you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public License
8+
* as published by the Free Software Foundation, either version 3 of
9+
* the License, or (at your option) any later version.
10+
*
11+
* This library is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public
17+
* License along with this library. If not, see
18+
* <http://www.gnu.org/licenses/>.
19+
*/
20+
21+
use std::collections::HashMap;
22+
use std::ffi::{OsStr, OsString};
23+
24+
use super::{Error, Result, Type};
25+
use crate::raf;
26+
use crate::rawfile::ReadAndSeek;
27+
28+
lazy_static::lazy_static! {
29+
static ref EXT_TO_TYPE: HashMap<OsString, Type> = {
30+
let mut m = HashMap::new();
31+
// The extension MUST be lowercase
32+
m.insert(OsString::from("cr3"), Type::Cr3);
33+
34+
m
35+
};
36+
}
37+
38+
/// Get the type associated to the extension.
39+
/// `ext` must be lowercase ASCII.
40+
pub(crate) fn type_for_extension(ext: &OsStr) -> Option<Type> {
41+
EXT_TO_TYPE.get(ext).cloned()
42+
}
43+
44+
/// Return the `Type` based on the content of the file.
45+
pub(crate) fn type_for_content(content: &mut dyn ReadAndSeek) -> Result<Option<Type>> {
46+
use crate::Type::*;
47+
48+
// Buffer to read the content to identify
49+
// Size is max of (14, RAF_MAGIC.len())
50+
// Change as needed
51+
let mut buf = [0_u8; 16];
52+
53+
let len = content.read(&mut buf)?;
54+
if len <= 4 {
55+
return Err(Error::BufferTooSmall);
56+
}
57+
58+
if &buf[0..4] == b"\0MRM" {
59+
return Ok(Some(Mrw));
60+
}
61+
if len >= 12 && &buf[4..12] == b"ftypcrx " {
62+
return Ok(Some(Cr3));
63+
}
64+
if len >= 14 && &buf[0..14] == b"II\x1a\0\0\0HEAPCCDR" {
65+
return Ok(Some(Crw));
66+
}
67+
if &buf[0..4] == b"IIRO" {
68+
return Ok(Some(Orf));
69+
}
70+
if &buf[0..4] == b"IIU\0" {
71+
return Ok(Some(Rw2));
72+
}
73+
if len >= raf::RAF_MAGIC.len() && &buf[0..raf::RAF_MAGIC.len()] == raf::RAF_MAGIC {
74+
return Ok(Some(Raf));
75+
}
76+
if &buf[0..4] == b"II\x2a\0" || &buf[0..4] == b"MM\0\x2a" {
77+
// TIFF based format
78+
if len >= 12 {
79+
if &buf[8..11] == b"CR\x02" {
80+
return Ok(Some(Cr2));
81+
}
82+
}
83+
if len >= 8 {
84+
// XXX missing the TIFF part.
85+
}
86+
}
87+
88+
Ok(None)
89+
}
90+
91+
#[cfg(test)]
92+
mod test {
93+
#[test]
94+
fn test_type_for_extension() {
95+
use std::ffi::OsString;
96+
97+
use super::type_for_extension;
98+
use crate::Type;
99+
100+
assert_eq!(type_for_extension(&OsString::from("CR3")), None);
101+
assert_eq!(type_for_extension(&OsString::from("cr3")), Some(Type::Cr3));
102+
assert_eq!(type_for_extension(&OsString::from("NOPE")), None);
103+
}
104+
105+
#[test]
106+
fn test_type_for_content() {
107+
use super::type_for_content;
108+
use crate::{Error, Type};
109+
use std::io::Cursor;
110+
111+
let mut four_bytes = Cursor::new([0_u8; 4].as_slice());
112+
assert_eq!(
113+
type_for_content(&mut four_bytes),
114+
Err(Error::BufferTooSmall)
115+
);
116+
117+
// Canon
118+
let mut crw = Cursor::new(include_bytes!("../testdata/identify/content_crw").as_slice());
119+
assert_eq!(type_for_content(&mut crw), Ok(Some(Type::Crw)));
120+
121+
let mut cr2 = Cursor::new(include_bytes!("../testdata/identify/content_cr2").as_slice());
122+
assert_eq!(type_for_content(&mut cr2), Ok(Some(Type::Cr2)));
123+
124+
let mut cr3 = Cursor::new(include_bytes!("../testdata/identify/content_cr3").as_slice());
125+
assert_eq!(type_for_content(&mut cr3), Ok(Some(Type::Cr3)));
126+
127+
let mut mrw = Cursor::new(include_bytes!("../testdata/identify/content_mrw").as_slice());
128+
assert_eq!(type_for_content(&mut mrw), Ok(Some(Type::Mrw)));
129+
130+
let mut raf = Cursor::new(include_bytes!("../testdata/identify/content_raf").as_slice());
131+
assert_eq!(type_for_content(&mut raf), Ok(Some(Type::Raf)));
132+
}
133+
}

src/lib.rs

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,110 @@
1+
/*
2+
* libopenraw - lib.rs
3+
*
4+
* Copyright (C) 2022 Hubert Figuière
5+
*
6+
* This library is free software: you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public License
8+
* as published by the Free Software Foundation, either version 3 of
9+
* the License, or (at your option) any later version.
10+
*
11+
* This library is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public
17+
* License along with this library. If not, see
18+
* <http://www.gnu.org/licenses/>.
19+
*/
20+
121
mod cr3;
22+
mod factory;
23+
mod identify;
24+
mod raf;
225
mod rawfile;
326
mod thumbnail;
427

528
pub use rawfile::RawFile;
629
pub use rawfile::RawFileImpl;
730

31+
/// Standard Result for libopenraw
832
pub type Result<T> = std::result::Result<T, Error>;
933

10-
#[derive(Debug)]
34+
/// Standard Error for libopenraw
35+
#[derive(Debug, PartialEq)]
1136
pub enum Error {
1237
/// File format is unrecognized
1338
UnrecognizedFormat,
1439
/// Not supported
1540
NotSupported,
1641
/// Not found in file
1742
NotFound,
43+
/// Buffer too small: we expect a bigger amount of data
44+
BufferTooSmall,
45+
/// IO Error
46+
IoError(String),
47+
}
48+
49+
impl From<std::io::Error> for Error {
50+
fn from(err: std::io::Error) -> Error {
51+
Error::IoError(err.to_string())
52+
}
1853
}
1954

55+
impl std::fmt::Display for Error {
56+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57+
match *self {
58+
Self::UnrecognizedFormat => write!(f, "Unrecognized format"),
59+
Self::NotSupported => write!(f, "Operation not supported"),
60+
Self::NotFound => write!(f, "Data not found"),
61+
Self::BufferTooSmall => write!(f, "Buffer is too small"),
62+
Self::IoError(ref err) => write!(f, "IO Error: {}", err),
63+
}
64+
}
65+
}
66+
67+
impl std::error::Error for Error {}
68+
69+
/// RAW file type. This list the type of files, which
70+
/// coincidentally match the vendor, except for DNG.
71+
///
72+
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
2073
pub enum Type {
74+
/// Sony Alpha
75+
Arw,
76+
/// Canon RAW CIFF based
77+
Crw,
78+
/// Canon RAW TIFF based
79+
Cr2,
80+
/// Canon RAW MPEG4 ISO based
2181
Cr3,
82+
/// Adobe Digital Negative
83+
Dng,
84+
/// Epson RAW
85+
Erf,
86+
/// GoPro RAW
87+
Gpr,
88+
/// Minolta RAW
89+
Mrw,
90+
/// Nikon RAW
91+
Nef,
92+
/// Nikon RAW (NRW variant)
93+
Nrw,
94+
/// Olympus RAW
95+
Orf,
96+
/// Pentax RAW
97+
Pef,
98+
/// Fujfilm RAW
99+
Raf,
100+
/// Panasonic RAW (old)
101+
Raw,
102+
/// Panasonic RAW
103+
Rw2,
104+
/// Sony RAW (old)
105+
Sr2,
22106
#[cfg(test)]
107+
/// Value for testing only
23108
Test,
24109
}
25110

src/raf.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* libopenraw - raf.rs
3+
*
4+
* Copyright (C) 2022 Hubert Figuière
5+
*
6+
* This library is free software: you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public License
8+
* as published by the Free Software Foundation, either version 3 of
9+
* the License, or (at your option) any later version.
10+
*
11+
* This library is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public
17+
* License along with this library. If not, see
18+
* <http://www.gnu.org/licenses/>.
19+
*/
20+
21+
pub(crate) const RAF_MAGIC: &[u8] = b"FUJIFILMCCD-RAW ";

0 commit comments

Comments
 (0)