Vendor rawler 0.7.2 unmodified
The crate as crates.io publishes it, minus .cargo-ok, its Cargo.lock and data/testdata (13 MB of sample files only its own tests read). Not yet routed through [patch.crates-io]; the next commit is the patch.
This commit is contained in:
Vendored
+257
@@ -0,0 +1,257 @@
|
||||
//! Library to extract the raw data and some metadata from digital camera
|
||||
//! images. Given an image in a supported format and camera you will be able to get
|
||||
//! everything needed to process the image
|
||||
//!
|
||||
//! # Example
|
||||
//! ```rust,no_run
|
||||
//! use std::env;
|
||||
//! use std::fs::File;
|
||||
//! use std::io::prelude::*;
|
||||
//! use std::io::BufWriter;
|
||||
//!
|
||||
//! fn main() {
|
||||
//! let args: Vec<_> = env::args().collect();
|
||||
//! if args.len() != 2 {
|
||||
//! println!("Usage: {} <file>", args[0]);
|
||||
//! std::process::exit(2);
|
||||
//! }
|
||||
//! let file = &args[1];
|
||||
//! let image = rawler::decode_file(file).unwrap();
|
||||
//!
|
||||
//! // Write out the image as a grayscale PPM
|
||||
//! let mut f = BufWriter::new(File::create(format!("{}.ppm",file)).unwrap());
|
||||
//! let preamble = format!("P6 {} {} {}\n", image.width, image.height, 65535).into_bytes();
|
||||
//! f.write_all(&preamble).unwrap();
|
||||
//! if let rawler::RawImageData::Integer(data) = image.data {
|
||||
//! for pix in data {
|
||||
//! // Do an extremely crude "demosaic" by setting R=G=B
|
||||
//! let pixhigh = (pix>>8) as u8;
|
||||
//! let pixlow = (pix&0x0f) as u8;
|
||||
//! f.write_all(&[pixhigh, pixlow, pixhigh, pixlow, pixhigh, pixlow]).unwrap()
|
||||
//! }
|
||||
//! } else {
|
||||
//! eprintln!("Don't know how to process non-integer raw files");
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
#![deny(
|
||||
//missing_docs,
|
||||
unstable_features,
|
||||
//unused_import_braces,
|
||||
//unused_qualifications
|
||||
)]
|
||||
// Clippy configuration
|
||||
#![allow(
|
||||
clippy::needless_doctest_main,
|
||||
clippy::identity_op, // we often use x + 0 to better document an algorithm
|
||||
clippy::too_many_arguments,
|
||||
clippy::bool_assert_comparison,
|
||||
clippy::upper_case_acronyms,
|
||||
clippy::eq_op,
|
||||
clippy::needless_range_loop,
|
||||
clippy::manual_range_patterns,
|
||||
clippy::unnecessary_cast,
|
||||
clippy::get_first,
|
||||
clippy::vec_init_then_push,
|
||||
clippy::only_used_in_recursion,
|
||||
//clippy::seek_from_current, // TODO
|
||||
clippy::needless_lifetimes,
|
||||
clippy::type_complexity,
|
||||
//clippy::cast_abs_to_unsigned,
|
||||
//clippy::needless_return,
|
||||
//clippy::derivable_impls,
|
||||
//clippy::useless_vec,
|
||||
)]
|
||||
|
||||
use decoders::Camera;
|
||||
use decoders::Decoder;
|
||||
use decoders::RawDecodeParams;
|
||||
use formats::jfif::JfifError;
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
pub mod analyze;
|
||||
pub mod bitarray;
|
||||
pub mod bits;
|
||||
pub mod buffer;
|
||||
pub mod cfa;
|
||||
pub mod decoders;
|
||||
pub mod decompressors;
|
||||
pub mod devtools;
|
||||
pub mod dng;
|
||||
pub(crate) mod envparams;
|
||||
pub mod exif;
|
||||
pub mod formats;
|
||||
pub mod imgop;
|
||||
pub mod lens;
|
||||
pub mod ljpeg92;
|
||||
pub mod packed;
|
||||
pub mod pixarray;
|
||||
pub mod pumps;
|
||||
pub mod rawimage;
|
||||
pub mod rawsource;
|
||||
pub mod tags;
|
||||
pub mod tiles;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use cfa::CFA;
|
||||
pub use decoders::Orientation;
|
||||
#[doc(hidden)]
|
||||
pub use decoders::RawLoader;
|
||||
use formats::tiff::TiffError;
|
||||
pub use rawimage::RawImage;
|
||||
pub use rawimage::RawImageData;
|
||||
use rawsource::RawSource;
|
||||
|
||||
lazy_static! {
|
||||
static ref LOADER: RawLoader = decoders::RawLoader::new();
|
||||
}
|
||||
|
||||
use std::io::Read;
|
||||
use std::io::Seek;
|
||||
use std::path::Path;
|
||||
use thiserror::Error;
|
||||
|
||||
pub(crate) const ISSUE_HINT: &str = "Please open an issue at https://github.com/dnglab/dnglab/issues and provide this message (optionally the RAW file, if you can license it under CC0-license).";
|
||||
|
||||
pub trait ReadTrait: Read + Seek {}
|
||||
|
||||
impl<T: Read + Seek> ReadTrait for T {}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum RawlerError {
|
||||
#[error("Error: {}, model '{}', make: '{}', mode: '{}'", what, model, make, mode)]
|
||||
Unsupported { what: String, model: String, make: String, mode: String },
|
||||
|
||||
#[error("Failed to decode image, possibly corrupt image. Origin error was: {}", _0)]
|
||||
DecoderFailed(String),
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, RawlerError>;
|
||||
|
||||
impl RawlerError {
|
||||
pub fn unsupported(camera: &Camera, what: impl AsRef<str>) -> Self {
|
||||
Self::Unsupported {
|
||||
what: what.as_ref().to_string(),
|
||||
model: camera.model.clone(),
|
||||
make: camera.make.clone(),
|
||||
mode: camera.mode.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_io_error(context: impl AsRef<str>, path: impl AsRef<Path>, error: std::io::Error) -> Self {
|
||||
Self::DecoderFailed(format!(
|
||||
"I/O error in context '{}', {} on file: {}",
|
||||
context.as_ref(),
|
||||
error,
|
||||
path.as_ref().display()
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for RawlerError {
|
||||
fn from(err: std::io::Error) -> Self {
|
||||
log::error!("I/O error: {}", err.to_string());
|
||||
log::error!("Backtrace:\n{:?}", backtrace::Backtrace::new());
|
||||
Self::DecoderFailed(format!("I/O Error without context: {}", err))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&String> for RawlerError {
|
||||
fn from(str: &String) -> Self {
|
||||
Self::DecoderFailed(str.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for RawlerError {
|
||||
fn from(str: &str) -> Self {
|
||||
Self::DecoderFailed(str.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::fmt::Arguments<'_>> for RawlerError {
|
||||
fn from(fmt: std::fmt::Arguments) -> Self {
|
||||
Self::DecoderFailed(fmt.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for RawlerError {
|
||||
fn from(str: String) -> Self {
|
||||
Self::DecoderFailed(str)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TiffError> for RawlerError {
|
||||
fn from(err: TiffError) -> Self {
|
||||
Self::DecoderFailed(err.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<JfifError> for RawlerError {
|
||||
fn from(err: JfifError) -> Self {
|
||||
Self::DecoderFailed(err.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
/// Take a path to a raw file and return a decoded image or an error
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust,ignore
|
||||
/// let image = match rawler::decode_file("path/to/your/file.RAW") {
|
||||
/// Ok(val) => val,
|
||||
/// Err(e) => ... some appropriate action when the file is unreadable ...
|
||||
/// };
|
||||
/// ```
|
||||
pub fn decode_file<P: AsRef<Path>>(path: P) -> Result<RawImage> {
|
||||
LOADER.decode_file(path.as_ref())
|
||||
}
|
||||
|
||||
/// Take a readable source and return a decoded image or an error
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust,ignore
|
||||
/// let mut file = match File::open(path).unwrap();
|
||||
/// let image = match rawler::decode(&mut file) {
|
||||
/// Ok(val) => val,
|
||||
/// Err(e) => ... some appropriate action when the file is unreadable ...
|
||||
/// };
|
||||
/// ```
|
||||
pub fn decode(rawfile: &RawSource, params: &RawDecodeParams) -> Result<RawImage> {
|
||||
LOADER.decode(rawfile, params, false)
|
||||
}
|
||||
|
||||
// Used to force lazy_static initializations. Useful for fuzzing.
|
||||
#[doc(hidden)]
|
||||
pub fn force_initialization() {
|
||||
lazy_static::initialize(&LOADER);
|
||||
}
|
||||
|
||||
// Used for fuzzing targets that just want to test the actual decoders instead of the full formats
|
||||
// with all their TIFF and other crazyness
|
||||
#[doc(hidden)]
|
||||
pub fn decode_unwrapped(rawfile: &RawSource) -> Result<RawImageData> {
|
||||
LOADER.decode_unwrapped(rawfile)
|
||||
}
|
||||
|
||||
// Used for fuzzing everything but the decoders themselves
|
||||
#[doc(hidden)]
|
||||
pub fn decode_dummy(rawfile: &RawSource) -> Result<RawImage> {
|
||||
LOADER.decode(rawfile, &RawDecodeParams::default(), true)
|
||||
}
|
||||
|
||||
pub fn get_decoder(rawfile: &RawSource) -> Result<Box<dyn Decoder>> {
|
||||
LOADER.get_decoder(rawfile)
|
||||
}
|
||||
|
||||
pub fn raw_image_count_file<P: AsRef<Path>>(path: P) -> Result<usize> {
|
||||
LOADER.raw_image_count_file(path.as_ref())
|
||||
}
|
||||
|
||||
pub fn global_loader() -> &'static RawLoader {
|
||||
&LOADER
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn init_test_logger() {
|
||||
let _ = env_logger::builder().is_test(true).filter_level(log::LevelFilter::Debug).try_init();
|
||||
}
|
||||
Reference in New Issue
Block a user