From a990de90fe41456a23e58bd087d2f107d321f3a1 Mon Sep 17 00:00:00 2001 From: Valentin Popov Date: Fri, 19 Jul 2024 16:37:58 +0400 Subject: Deleted vendor folder --- vendor/image/src/codecs/hdr/decoder.rs | 1033 -------------------------------- vendor/image/src/codecs/hdr/encoder.rs | 433 ------------- vendor/image/src/codecs/hdr/mod.rs | 15 - 3 files changed, 1481 deletions(-) delete mode 100644 vendor/image/src/codecs/hdr/decoder.rs delete mode 100644 vendor/image/src/codecs/hdr/encoder.rs delete mode 100644 vendor/image/src/codecs/hdr/mod.rs (limited to 'vendor/image/src/codecs/hdr') diff --git a/vendor/image/src/codecs/hdr/decoder.rs b/vendor/image/src/codecs/hdr/decoder.rs deleted file mode 100644 index 8329d57..0000000 --- a/vendor/image/src/codecs/hdr/decoder.rs +++ /dev/null @@ -1,1033 +0,0 @@ -use crate::Primitive; -use num_traits::identities::Zero; -#[cfg(test)] -use std::borrow::Cow; -use std::convert::TryFrom; -use std::io::{self, BufRead, Cursor, Read, Seek}; -use std::iter::Iterator; -use std::marker::PhantomData; -use std::num::{ParseFloatError, ParseIntError}; -use std::path::Path; -use std::{error, fmt, mem}; - -use crate::color::{ColorType, Rgb}; -use crate::error::{ - DecodingError, ImageError, ImageFormatHint, ImageResult, ParameterError, ParameterErrorKind, - UnsupportedError, UnsupportedErrorKind, -}; -use crate::image::{self, ImageDecoder, ImageDecoderRect, ImageFormat, Progress}; - -/// Errors that can occur during decoding and parsing of a HDR image -#[derive(Debug, Clone, PartialEq, Eq)] -enum DecoderError { - /// HDR's "#?RADIANCE" signature wrong or missing - RadianceHdrSignatureInvalid, - /// EOF before end of header - TruncatedHeader, - /// EOF instead of image dimensions - TruncatedDimensions, - - /// A value couldn't be parsed - UnparsableF32(LineType, ParseFloatError), - /// A value couldn't be parsed - UnparsableU32(LineType, ParseIntError), - /// Not enough numbers in line - LineTooShort(LineType), - - /// COLORCORR contains too many numbers in strict mode - ExtraneousColorcorrNumbers, - - /// Dimensions line had too few elements - DimensionsLineTooShort(usize, usize), - /// Dimensions line had too many elements - DimensionsLineTooLong(usize), - - /// The length of a scanline (1) wasn't a match for the specified length (2) - WrongScanlineLength(usize, usize), - /// First pixel of a scanline is a run length marker - FirstPixelRlMarker, -} - -impl fmt::Display for DecoderError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - DecoderError::RadianceHdrSignatureInvalid => { - f.write_str("Radiance HDR signature not found") - } - DecoderError::TruncatedHeader => f.write_str("EOF in header"), - DecoderError::TruncatedDimensions => f.write_str("EOF in dimensions line"), - DecoderError::UnparsableF32(line, pe) => { - f.write_fmt(format_args!("Cannot parse {} value as f32: {}", line, pe)) - } - DecoderError::UnparsableU32(line, pe) => { - f.write_fmt(format_args!("Cannot parse {} value as u32: {}", line, pe)) - } - DecoderError::LineTooShort(line) => { - f.write_fmt(format_args!("Not enough numbers in {}", line)) - } - DecoderError::ExtraneousColorcorrNumbers => f.write_str("Extra numbers in COLORCORR"), - DecoderError::DimensionsLineTooShort(elements, expected) => f.write_fmt(format_args!( - "Dimensions line too short: have {} elements, expected {}", - elements, expected - )), - DecoderError::DimensionsLineTooLong(expected) => f.write_fmt(format_args!( - "Dimensions line too long, expected {} elements", - expected - )), - DecoderError::WrongScanlineLength(len, expected) => f.write_fmt(format_args!( - "Wrong length of decoded scanline: got {}, expected {}", - len, expected - )), - DecoderError::FirstPixelRlMarker => { - f.write_str("First pixel of a scanline shouldn't be run length marker") - } - } - } -} - -impl From for ImageError { - fn from(e: DecoderError) -> ImageError { - ImageError::Decoding(DecodingError::new(ImageFormat::Hdr.into(), e)) - } -} - -impl error::Error for DecoderError { - fn source(&self) -> Option<&(dyn error::Error + 'static)> { - match self { - DecoderError::UnparsableF32(_, err) => Some(err), - DecoderError::UnparsableU32(_, err) => Some(err), - _ => None, - } - } -} - -/// Lines which contain parsable data that can fail -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] -enum LineType { - Exposure, - Pixaspect, - Colorcorr, - DimensionsHeight, - DimensionsWidth, -} - -impl fmt::Display for LineType { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(match self { - LineType::Exposure => "EXPOSURE", - LineType::Pixaspect => "PIXASPECT", - LineType::Colorcorr => "COLORCORR", - LineType::DimensionsHeight => "height dimension", - LineType::DimensionsWidth => "width dimension", - }) - } -} - -/// Adapter to conform to `ImageDecoder` trait -#[derive(Debug)] -pub struct HdrAdapter { - inner: Option>, - // data: Option>, - meta: HdrMetadata, -} - -impl HdrAdapter { - /// Creates adapter - pub fn new(r: R) -> ImageResult> { - let decoder = HdrDecoder::new(r)?; - let meta = decoder.metadata(); - Ok(HdrAdapter { - inner: Some(decoder), - meta, - }) - } - - /// Allows reading old Radiance HDR images - pub fn new_nonstrict(r: R) -> ImageResult> { - let decoder = HdrDecoder::with_strictness(r, false)?; - let meta = decoder.metadata(); - Ok(HdrAdapter { - inner: Some(decoder), - meta, - }) - } - - /// Read the actual data of the image, and store it in Self::data. - fn read_image_data(&mut self, buf: &mut [u8]) -> ImageResult<()> { - assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes())); - match self.inner.take() { - Some(decoder) => { - let img: Vec> = decoder.read_image_ldr()?; - for (i, Rgb(data)) in img.into_iter().enumerate() { - buf[(i * 3)..][..3].copy_from_slice(&data); - } - - Ok(()) - } - None => Err(ImageError::Parameter(ParameterError::from_kind( - ParameterErrorKind::NoMoreData, - ))), - } - } -} - -/// Wrapper struct around a `Cursor>` -pub struct HdrReader(Cursor>, PhantomData); -impl Read for HdrReader { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.0.read(buf) - } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - if self.0.position() == 0 && buf.is_empty() { - mem::swap(buf, self.0.get_mut()); - Ok(buf.len()) - } else { - self.0.read_to_end(buf) - } - } -} - -impl<'a, R: 'a + BufRead> ImageDecoder<'a> for HdrAdapter { - type Reader = HdrReader; - - fn dimensions(&self) -> (u32, u32) { - (self.meta.width, self.meta.height) - } - - fn color_type(&self) -> ColorType { - ColorType::Rgb8 - } - - fn into_reader(self) -> ImageResult { - Ok(HdrReader( - Cursor::new(image::decoder_to_vec(self)?), - PhantomData, - )) - } - - fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> { - self.read_image_data(buf) - } -} - -impl<'a, R: 'a + BufRead + Seek> ImageDecoderRect<'a> for HdrAdapter { - fn read_rect_with_progress( - &mut self, - x: u32, - y: u32, - width: u32, - height: u32, - buf: &mut [u8], - progress_callback: F, - ) -> ImageResult<()> { - image::load_rect( - x, - y, - width, - height, - buf, - progress_callback, - self, - |_, _| unreachable!(), - |s, buf| s.read_image_data(buf), - ) - } -} - -/// Radiance HDR file signature -pub const SIGNATURE: &[u8] = b"#?RADIANCE"; -const SIGNATURE_LENGTH: usize = 10; - -/// An Radiance HDR decoder -#[derive(Debug)] -pub struct HdrDecoder { - r: R, - width: u32, - height: u32, - meta: HdrMetadata, -} - -/// Refer to [wikipedia](https://en.wikipedia.org/wiki/RGBE_image_format) -#[repr(C)] -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] -pub struct Rgbe8Pixel { - /// Color components - pub c: [u8; 3], - /// Exponent - pub e: u8, -} - -/// Creates `Rgbe8Pixel` from components -pub fn rgbe8(r: u8, g: u8, b: u8, e: u8) -> Rgbe8Pixel { - Rgbe8Pixel { c: [r, g, b], e } -} - -impl Rgbe8Pixel { - /// Converts `Rgbe8Pixel` into `Rgb` linearly - #[inline] - pub fn to_hdr(self) -> Rgb { - if self.e == 0 { - Rgb([0.0, 0.0, 0.0]) - } else { - // let exp = f32::ldexp(1., self.e as isize - (128 + 8)); // unstable - let exp = f32::exp2(>::from(self.e) - (128.0 + 8.0)); - Rgb([ - exp * >::from(self.c[0]), - exp * >::from(self.c[1]), - exp * >::from(self.c[2]), - ]) - } - } - - /// Converts `Rgbe8Pixel` into `Rgb` with scale=1 and gamma=2.2 - /// - /// color_ldr = (color_hdr*scale)gamma - /// - /// # Panic - /// - /// Panics when `T::max_value()` cannot be represented as f32. - #[inline] - pub fn to_ldr(self) -> Rgb { - self.to_ldr_scale_gamma(1.0, 2.2) - } - - /// Converts `Rgbe8Pixel` into `Rgb` using provided scale and gamma - /// - /// color_ldr = (color_hdr*scale)gamma - /// - /// # Panic - /// - /// Panics when `T::max_value()` cannot be represented as f32. - /// Panics when scale or gamma is NaN - #[inline] - pub fn to_ldr_scale_gamma(self, scale: f32, gamma: f32) -> Rgb { - let Rgb(data) = self.to_hdr(); - let (r, g, b) = (data[0], data[1], data[2]); - #[inline] - fn sg(v: f32, scale: f32, gamma: f32) -> T { - let t_max = T::max_value(); - // Disassembly shows that t_max_f32 is compiled into constant - let t_max_f32: f32 = num_traits::NumCast::from(t_max) - .expect("to_ldr_scale_gamma: maximum value of type is not representable as f32"); - let fv = f32::powf(v * scale, gamma) * t_max_f32 + 0.5; - if fv < 0.0 { - T::zero() - } else if fv > t_max_f32 { - t_max - } else { - num_traits::NumCast::from(fv) - .expect("to_ldr_scale_gamma: cannot convert f32 to target type. NaN?") - } - } - Rgb([ - sg(r, scale, gamma), - sg(g, scale, gamma), - sg(b, scale, gamma), - ]) - } -} - -impl HdrDecoder { - /// Reads Radiance HDR image header from stream `r` - /// if the header is valid, creates HdrDecoder - /// strict mode is enabled - pub fn new(reader: R) -> ImageResult> { - HdrDecoder::with_strictness(reader, true) - } - - /// Reads Radiance HDR image header from stream `reader`, - /// if the header is valid, creates `HdrDecoder`. - /// - /// strict enables strict mode - /// - /// Warning! Reading wrong file in non-strict mode - /// could consume file size worth of memory in the process. - pub fn with_strictness(mut reader: R, strict: bool) -> ImageResult> { - let mut attributes = HdrMetadata::new(); - - { - // scope to make borrowck happy - let r = &mut reader; - if strict { - let mut signature = [0; SIGNATURE_LENGTH]; - r.read_exact(&mut signature)?; - if signature != SIGNATURE { - return Err(DecoderError::RadianceHdrSignatureInvalid.into()); - } // no else - // skip signature line ending - read_line_u8(r)?; - } else { - // Old Radiance HDR files (*.pic) don't use signature - // Let them be parsed in non-strict mode - } - // read header data until empty line - loop { - match read_line_u8(r)? { - None => { - // EOF before end of header - return Err(DecoderError::TruncatedHeader.into()); - } - Some(line) => { - if line.is_empty() { - // end of header - break; - } else if line[0] == b'#' { - // line[0] will not panic, line.len() == 0 is false here - // skip comments - continue; - } // no else - // process attribute line - let line = String::from_utf8_lossy(&line[..]); - attributes.update_header_info(&line, strict)?; - } // <= Some(line) - } // match read_line_u8() - } // loop - } // scope to end borrow of reader - // parse dimensions - let (width, height) = match read_line_u8(&mut reader)? { - None => { - // EOF instead of image dimensions - return Err(DecoderError::TruncatedDimensions.into()); - } - Some(dimensions) => { - let dimensions = String::from_utf8_lossy(&dimensions[..]); - parse_dimensions_line(&dimensions, strict)? - } - }; - - // color type is always rgb8 - if crate::utils::check_dimension_overflow(width, height, ColorType::Rgb8.bytes_per_pixel()) - { - return Err(ImageError::Unsupported( - UnsupportedError::from_format_and_kind( - ImageFormat::Hdr.into(), - UnsupportedErrorKind::GenericFeature(format!( - "Image dimensions ({}x{}) are too large", - width, height - )), - ), - )); - } - - Ok(HdrDecoder { - r: reader, - - width, - height, - meta: HdrMetadata { - width, - height, - ..attributes - }, - }) - } // end with_strictness - - /// Returns file metadata. Refer to `HdrMetadata` for details. - pub fn metadata(&self) -> HdrMetadata { - self.meta.clone() - } - - /// Consumes decoder and returns a vector of RGBE8 pixels - pub fn read_image_native(mut self) -> ImageResult> { - // Don't read anything if image is empty - if self.width == 0 || self.height == 0 { - return Ok(vec![]); - } - // expression self.width > 0 && self.height > 0 is true from now to the end of this method - let pixel_count = self.width as usize * self.height as usize; - let mut ret = vec![Default::default(); pixel_count]; - for chunk in ret.chunks_mut(self.width as usize) { - read_scanline(&mut self.r, chunk)?; - } - Ok(ret) - } - - /// Consumes decoder and returns a vector of transformed pixels - pub fn read_image_transform T>( - mut self, - f: F, - output_slice: &mut [T], - ) -> ImageResult<()> { - assert_eq!( - output_slice.len(), - self.width as usize * self.height as usize - ); - - // Don't read anything if image is empty - if self.width == 0 || self.height == 0 { - return Ok(()); - } - - let chunks_iter = output_slice.chunks_mut(self.width as usize); - - let mut buf = vec![Default::default(); self.width as usize]; - for chunk in chunks_iter { - // read_scanline overwrites the entire buffer or returns an Err, - // so not resetting the buffer here is ok. - read_scanline(&mut self.r, &mut buf[..])?; - for (dst, &pix) in chunk.iter_mut().zip(buf.iter()) { - *dst = f(pix); - } - } - Ok(()) - } - - /// Consumes decoder and returns a vector of `Rgb` pixels. - /// scale = 1, gamma = 2.2 - pub fn read_image_ldr(self) -> ImageResult>> { - let mut ret = vec![Rgb([0, 0, 0]); self.width as usize * self.height as usize]; - self.read_image_transform(|pix| pix.to_ldr(), &mut ret[..])?; - Ok(ret) - } - - /// Consumes decoder and returns a vector of `Rgb` pixels. - /// - pub fn read_image_hdr(self) -> ImageResult>> { - let mut ret = vec![Rgb([0.0, 0.0, 0.0]); self.width as usize * self.height as usize]; - self.read_image_transform(|pix| pix.to_hdr(), &mut ret[..])?; - Ok(ret) - } -} - -impl IntoIterator for HdrDecoder { - type Item = ImageResult; - type IntoIter = HdrImageDecoderIterator; - - fn into_iter(self) -> Self::IntoIter { - HdrImageDecoderIterator { - r: self.r, - scanline_cnt: self.height as usize, - buf: vec![Default::default(); self.width as usize], - col: 0, - scanline: 0, - trouble: true, // make first call to `next()` read scanline - error_encountered: false, - } - } -} - -/// Scanline buffered pixel by pixel iterator -pub struct HdrImageDecoderIterator { - r: R, - scanline_cnt: usize, - buf: Vec, // scanline buffer - col: usize, // current position in scanline - scanline: usize, // current scanline - trouble: bool, // optimization, true indicates that we need to check something - error_encountered: bool, -} - -impl HdrImageDecoderIterator { - // Advances counter to the next pixel - #[inline] - fn advance(&mut self) { - self.col += 1; - if self.col == self.buf.len() { - self.col = 0; - self.scanline += 1; - self.trouble = true; - } - } -} - -impl Iterator for HdrImageDecoderIterator { - type Item = ImageResult; - - fn next(&mut self) -> Option { - if !self.trouble { - let ret = self.buf[self.col]; - self.advance(); - Some(Ok(ret)) - } else { - // some condition is pending - if self.buf.is_empty() || self.scanline == self.scanline_cnt { - // No more pixels - return None; - } // no else - if self.error_encountered { - self.advance(); - // Error was encountered. Keep producing errors. - // ImageError can't implement Clone, so just dump some error - return Some(Err(ImageError::Parameter(ParameterError::from_kind( - ParameterErrorKind::FailedAlready, - )))); - } // no else - if self.col == 0 { - // fill scanline buffer - match read_scanline(&mut self.r, &mut self.buf[..]) { - Ok(_) => { - // no action required - } - Err(err) => { - self.advance(); - self.error_encountered = true; - self.trouble = true; - return Some(Err(err)); - } - } - } // no else - self.trouble = false; - let ret = self.buf[0]; - self.advance(); - Some(Ok(ret)) - } - } - - fn size_hint(&self) -> (usize, Option) { - let total_cnt = self.buf.len() * self.scanline_cnt; - let cur_cnt = self.buf.len() * self.scanline + self.col; - let remaining = total_cnt - cur_cnt; - (remaining, Some(remaining)) - } -} - -impl ExactSizeIterator for HdrImageDecoderIterator {} - -// Precondition: buf.len() > 0 -fn read_scanline(r: &mut R, buf: &mut [Rgbe8Pixel]) -> ImageResult<()> { - assert!(!buf.is_empty()); - let width = buf.len(); - // first 4 bytes in scanline allow to determine compression method - let fb = read_rgbe(r)?; - if fb.c[0] == 2 && fb.c[1] == 2 && fb.c[2] < 128 { - // denormalized pixel value (2,2,<128,_) indicates new per component RLE method - // decode_component guarantees that offset is within 0 .. width - // therefore we can skip bounds checking here, but we will not - decode_component(r, width, |offset, value| buf[offset].c[0] = value)?; - decode_component(r, width, |offset, value| buf[offset].c[1] = value)?; - decode_component(r, width, |offset, value| buf[offset].c[2] = value)?; - decode_component(r, width, |offset, value| buf[offset].e = value)?; - } else { - // old RLE method (it was considered old around 1991, should it be here?) - decode_old_rle(r, fb, buf)?; - } - Ok(()) -} - -#[inline(always)] -fn read_byte(r: &mut R) -> io::Result { - let mut buf = [0u8]; - r.read_exact(&mut buf[..])?; - Ok(buf[0]) -} - -// Guarantees that first parameter of set_component will be within pos .. pos+width -#[inline] -fn decode_component( - r: &mut R, - width: usize, - mut set_component: S, -) -> ImageResult<()> { - let mut buf = [0; 128]; - let mut pos = 0; - while pos < width { - // increment position by a number of decompressed values - pos += { - let rl = read_byte(r)?; - if rl <= 128 { - // sanity check - if pos + rl as usize > width { - return Err(DecoderError::WrongScanlineLength(pos + rl as usize, width).into()); - } - // read values - r.read_exact(&mut buf[0..rl as usize])?; - for (offset, &value) in buf[0..rl as usize].iter().enumerate() { - set_component(pos + offset, value); - } - rl as usize - } else { - // run - let rl = rl - 128; - // sanity check - if pos + rl as usize > width { - return Err(DecoderError::WrongScanlineLength(pos + rl as usize, width).into()); - } - // fill with same value - let value = read_byte(r)?; - for offset in 0..rl as usize { - set_component(pos + offset, value); - } - rl as usize - } - }; - } - if pos != width { - return Err(DecoderError::WrongScanlineLength(pos, width).into()); - } - Ok(()) -} - -// Decodes scanline, places it into buf -// Precondition: buf.len() > 0 -// fb - first 4 bytes of scanline -fn decode_old_rle(r: &mut R, fb: Rgbe8Pixel, buf: &mut [Rgbe8Pixel]) -> ImageResult<()> { - assert!(!buf.is_empty()); - let width = buf.len(); - // convenience function. - // returns run length if pixel is a run length marker - #[inline] - fn rl_marker(pix: Rgbe8Pixel) -> Option { - if pix.c == [1, 1, 1] { - Some(pix.e as usize) - } else { - None - } - } - // first pixel in scanline should not be run length marker - // it is error if it is - if rl_marker(fb).is_some() { - return Err(DecoderError::FirstPixelRlMarker.into()); - } - buf[0] = fb; // set first pixel of scanline - - let mut x_off = 1; // current offset from beginning of a scanline - let mut rl_mult = 1; // current run length multiplier - let mut prev_pixel = fb; - while x_off < width { - let pix = read_rgbe(r)?; - // it's harder to forget to increase x_off if I write this this way. - x_off += { - if let Some(rl) = rl_marker(pix) { - // rl_mult takes care of consecutive RL markers - let rl = rl * rl_mult; - rl_mult *= 256; - if x_off + rl <= width { - // do run - for b in &mut buf[x_off..x_off + rl] { - *b = prev_pixel; - } - } else { - return Err(DecoderError::WrongScanlineLength(x_off + rl, width).into()); - }; - rl // value to increase x_off by - } else { - rl_mult = 1; // chain of consecutive RL markers is broken - prev_pixel = pix; - buf[x_off] = pix; - 1 // value to increase x_off by - } - }; - } - if x_off != width { - return Err(DecoderError::WrongScanlineLength(x_off, width).into()); - } - Ok(()) -} - -fn read_rgbe(r: &mut R) -> io::Result { - let mut buf = [0u8; 4]; - r.read_exact(&mut buf[..])?; - Ok(Rgbe8Pixel { - c: [buf[0], buf[1], buf[2]], - e: buf[3], - }) -} - -/// Metadata for Radiance HDR image -#[derive(Debug, Clone)] -pub struct HdrMetadata { - /// Width of decoded image. It could be either scanline length, - /// or scanline count, depending on image orientation. - pub width: u32, - /// Height of decoded image. It depends on orientation too. - pub height: u32, - /// Orientation matrix. For standard orientation it is ((1,0),(0,1)) - left to right, top to bottom. - /// First pair tells how resulting pixel coordinates change along a scanline. - /// Second pair tells how they change from one scanline to the next. - pub orientation: ((i8, i8), (i8, i8)), - /// Divide color values by exposure to get to get physical radiance in - /// watts/steradian/m2 - /// - /// Image may not contain physical data, even if this field is set. - pub exposure: Option, - /// Divide color values by corresponding tuple member (r, g, b) to get to get physical radiance - /// in watts/steradian/m2 - /// - /// Image may not contain physical data, even if this field is set. - pub color_correction: Option<(f32, f32, f32)>, - /// Pixel height divided by pixel width - pub pixel_aspect_ratio: Option, - /// All lines contained in image header are put here. Ordering of lines is preserved. - /// Lines in the form "key=value" are represented as ("key", "value"). - /// All other lines are ("", "line") - pub custom_attributes: Vec<(String, String)>, -} - -impl HdrMetadata { - fn new() -> HdrMetadata { - HdrMetadata { - width: 0, - height: 0, - orientation: ((1, 0), (0, 1)), - exposure: None, - color_correction: None, - pixel_aspect_ratio: None, - custom_attributes: vec![], - } - } - - // Updates header info, in strict mode returns error for malformed lines (no '=' separator) - // unknown attributes are skipped - fn update_header_info(&mut self, line: &str, strict: bool) -> ImageResult<()> { - // split line at first '=' - // old Radiance HDR files (*.pic) feature tabs in key, so vvv trim - let maybe_key_value = split_at_first(line, "=").map(|(key, value)| (key.trim(), value)); - // save all header lines in custom_attributes - match maybe_key_value { - Some((key, val)) => self - .custom_attributes - .push((key.to_owned(), val.to_owned())), - None => self.custom_attributes.push(("".into(), line.to_owned())), - } - // parse known attributes - match maybe_key_value { - Some(("FORMAT", val)) => { - if val.trim() != "32-bit_rle_rgbe" { - // XYZE isn't supported yet - return Err(ImageError::Unsupported( - UnsupportedError::from_format_and_kind( - ImageFormat::Hdr.into(), - UnsupportedErrorKind::Format(ImageFormatHint::Name(limit_string_len( - val, 20, - ))), - ), - )); - } - } - Some(("EXPOSURE", val)) => { - match val.trim().parse::() { - Ok(v) => { - self.exposure = Some(self.exposure.unwrap_or(1.0) * v); // all encountered exposure values should be multiplied - } - Err(parse_error) => { - if strict { - return Err(DecoderError::UnparsableF32( - LineType::Exposure, - parse_error, - ) - .into()); - } // no else, skip this line in non-strict mode - } - }; - } - Some(("PIXASPECT", val)) => { - match val.trim().parse::() { - Ok(v) => { - self.pixel_aspect_ratio = Some(self.pixel_aspect_ratio.unwrap_or(1.0) * v); - // all encountered exposure values should be multiplied - } - Err(parse_error) => { - if strict { - return Err(DecoderError::UnparsableF32( - LineType::Pixaspect, - parse_error, - ) - .into()); - } // no else, skip this line in non-strict mode - } - }; - } - Some(("COLORCORR", val)) => { - let mut rgbcorr = [1.0, 1.0, 1.0]; - match parse_space_separated_f32(val, &mut rgbcorr, LineType::Colorcorr) { - Ok(extra_numbers) => { - if strict && extra_numbers { - return Err(DecoderError::ExtraneousColorcorrNumbers.into()); - } // no else, just ignore extra numbers - let (rc, gc, bc) = self.color_correction.unwrap_or((1.0, 1.0, 1.0)); - self.color_correction = - Some((rc * rgbcorr[0], gc * rgbcorr[1], bc * rgbcorr[2])); - } - Err(err) => { - if strict { - return Err(err); - } // no else, skip malformed line in non-strict mode - } - } - } - None => { - // old Radiance HDR files (*.pic) contain commands in a header - // just skip them - } - _ => { - // skip unknown attribute - } - } // match attributes - Ok(()) - } -} - -fn parse_space_separated_f32(line: &str, vals: &mut [f32], line_tp: LineType) -> ImageResult { - let mut nums = line.split_whitespace(); - for val in vals.iter_mut() { - if let Some(num) = nums.next() { - match num.parse::() { - Ok(v) => *val = v, - Err(err) => return Err(DecoderError::UnparsableF32(line_tp, err).into()), - } - } else { - // not enough numbers in line - return Err(DecoderError::LineTooShort(line_tp).into()); - } - } - Ok(nums.next().is_some()) -} - -// Parses dimension line "-Y height +X width" -// returns (width, height) or error -fn parse_dimensions_line(line: &str, strict: bool) -> ImageResult<(u32, u32)> { - const DIMENSIONS_COUNT: usize = 4; - - let mut dim_parts = line.split_whitespace(); - let c1_tag = dim_parts - .next() - .ok_or(DecoderError::DimensionsLineTooShort(0, DIMENSIONS_COUNT))?; - let c1_str = dim_parts - .next() - .ok_or(DecoderError::DimensionsLineTooShort(1, DIMENSIONS_COUNT))?; - let c2_tag = dim_parts - .next() - .ok_or(DecoderError::DimensionsLineTooShort(2, DIMENSIONS_COUNT))?; - let c2_str = dim_parts - .next() - .ok_or(DecoderError::DimensionsLineTooShort(3, DIMENSIONS_COUNT))?; - if strict && dim_parts.next().is_some() { - // extra data in dimensions line - return Err(DecoderError::DimensionsLineTooLong(DIMENSIONS_COUNT).into()); - } // no else - // dimensions line is in the form "-Y 10 +X 20" - // There are 8 possible orientations: +Y +X, +X -Y and so on - match (c1_tag, c2_tag) { - ("-Y", "+X") => { - // Common orientation (left-right, top-down) - // c1_str is height, c2_str is width - let height = c1_str - .parse::() - .map_err(|pe| DecoderError::UnparsableU32(LineType::DimensionsHeight, pe))?; - let width = c2_str - .parse::() - .map_err(|pe| DecoderError::UnparsableU32(LineType::DimensionsWidth, pe))?; - Ok((width, height)) - } - _ => Err(ImageError::Unsupported( - UnsupportedError::from_format_and_kind( - ImageFormat::Hdr.into(), - UnsupportedErrorKind::GenericFeature(format!( - "Orientation {} {}", - limit_string_len(c1_tag, 4), - limit_string_len(c2_tag, 4) - )), - ), - )), - } // final expression. Returns value -} - -// Returns string with no more than len+3 characters -fn limit_string_len(s: &str, len: usize) -> String { - let s_char_len = s.chars().count(); - if s_char_len > len { - s.chars().take(len).chain("...".chars()).collect() - } else { - s.into() - } -} - -// Splits string into (before separator, after separator) tuple -// or None if separator isn't found -fn split_at_first<'a>(s: &'a str, separator: &str) -> Option<(&'a str, &'a str)> { - match s.find(separator) { - None | Some(0) => None, - Some(p) if p >= s.len() - separator.len() => None, - Some(p) => Some((&s[..p], &s[(p + separator.len())..])), - } -} - -#[test] -fn split_at_first_test() { - assert_eq!(split_at_first(&Cow::Owned("".into()), "="), None); - assert_eq!(split_at_first(&Cow::Owned("=".into()), "="), None); - assert_eq!(split_at_first(&Cow::Owned("= ".into()), "="), None); - assert_eq!( - split_at_first(&Cow::Owned(" = ".into()), "="), - Some((" ", " ")) - ); - assert_eq!( - split_at_first(&Cow::Owned("EXPOSURE= ".into()), "="), - Some(("EXPOSURE", " ")) - ); - assert_eq!( - split_at_first(&Cow::Owned("EXPOSURE= =".into()), "="), - Some(("EXPOSURE", " =")) - ); - assert_eq!( - split_at_first(&Cow::Owned("EXPOSURE== =".into()), "=="), - Some(("EXPOSURE", " =")) - ); - assert_eq!(split_at_first(&Cow::Owned("EXPOSURE".into()), ""), None); -} - -// Reads input until b"\n" or EOF -// Returns vector of read bytes NOT including end of line characters -// or return None to indicate end of file -fn read_line_u8(r: &mut R) -> ::std::io::Result>> { - let mut ret = Vec::with_capacity(16); - match r.read_until(b'\n', &mut ret) { - Ok(0) => Ok(None), - Ok(_) => { - if let Some(&b'\n') = ret[..].last() { - let _ = ret.pop(); - } - Ok(Some(ret)) - } - Err(err) => Err(err), - } -} - -#[test] -fn read_line_u8_test() { - let buf: Vec<_> = (&b"One\nTwo\nThree\nFour\n\n\n"[..]).into(); - let input = &mut ::std::io::Cursor::new(buf); - assert_eq!(&read_line_u8(input).unwrap().unwrap()[..], &b"One"[..]); - assert_eq!(&read_line_u8(input).unwrap().unwrap()[..], &b"Two"[..]); - assert_eq!(&read_line_u8(input).unwrap().unwrap()[..], &b"Three"[..]); - assert_eq!(&read_line_u8(input).unwrap().unwrap()[..], &b"Four"[..]); - assert_eq!(&read_line_u8(input).unwrap().unwrap()[..], &b""[..]); - assert_eq!(&read_line_u8(input).unwrap().unwrap()[..], &b""[..]); - assert_eq!(read_line_u8(input).unwrap(), None); -} - -/// Helper function for reading raw 3-channel f32 images -pub fn read_raw_file>(path: P) -> ::std::io::Result>> { - use byteorder::{LittleEndian as LE, ReadBytesExt}; - use std::fs::File; - use std::io::BufReader; - - let mut r = BufReader::new(File::open(path)?); - let w = r.read_u32::()? as usize; - let h = r.read_u32::()? as usize; - let c = r.read_u32::()? as usize; - assert_eq!(c, 3); - let cnt = w * h; - let mut ret = Vec::with_capacity(cnt); - for _ in 0..cnt { - let cr = r.read_f32::()?; - let cg = r.read_f32::()?; - let cb = r.read_f32::()?; - ret.push(Rgb([cr, cg, cb])); - } - Ok(ret) -} - -#[cfg(test)] -mod test { - use super::*; - use std::io::Cursor; - - #[test] - fn dimension_overflow() { - let data = b"#?RADIANCE\nFORMAT=32-bit_rle_rgbe\n\n -Y 4294967295 +X 4294967295"; - - assert!(HdrAdapter::new(Cursor::new(data)).is_err()); - assert!(HdrAdapter::new_nonstrict(Cursor::new(data)).is_err()); - } -} diff --git a/vendor/image/src/codecs/hdr/encoder.rs b/vendor/image/src/codecs/hdr/encoder.rs deleted file mode 100644 index c3a176d..0000000 --- a/vendor/image/src/codecs/hdr/encoder.rs +++ /dev/null @@ -1,433 +0,0 @@ -use crate::codecs::hdr::{rgbe8, Rgbe8Pixel, SIGNATURE}; -use crate::color::Rgb; -use crate::error::ImageResult; -use std::cmp::Ordering; -use std::io::{Result, Write}; - -/// Radiance HDR encoder -pub struct HdrEncoder { - w: W, -} - -impl HdrEncoder { - /// Creates encoder - pub fn new(w: W) -> HdrEncoder { - HdrEncoder { w } - } - - /// Encodes the image ```data``` - /// that has dimensions ```width``` and ```height``` - pub fn encode(mut self, data: &[Rgb], width: usize, height: usize) -> ImageResult<()> { - assert!(data.len() >= width * height); - let w = &mut self.w; - w.write_all(SIGNATURE)?; - w.write_all(b"\n")?; - w.write_all(b"# Rust HDR encoder\n")?; - w.write_all(b"FORMAT=32-bit_rle_rgbe\n\n")?; - w.write_all(format!("-Y {} +X {}\n", height, width).as_bytes())?; - - if !(8..=32_768).contains(&width) { - for &pix in data { - write_rgbe8(w, to_rgbe8(pix))?; - } - } else { - // new RLE marker contains scanline width - let marker = rgbe8(2, 2, (width / 256) as u8, (width % 256) as u8); - // buffers for encoded pixels - let mut bufr = vec![0; width]; - let mut bufg = vec![0; width]; - let mut bufb = vec![0; width]; - let mut bufe = vec![0; width]; - let mut rle_buf = vec![0; width]; - for scanline in data.chunks(width) { - for ((((r, g), b), e), &pix) in bufr - .iter_mut() - .zip(bufg.iter_mut()) - .zip(bufb.iter_mut()) - .zip(bufe.iter_mut()) - .zip(scanline.iter()) - { - let cp = to_rgbe8(pix); - *r = cp.c[0]; - *g = cp.c[1]; - *b = cp.c[2]; - *e = cp.e; - } - write_rgbe8(w, marker)?; // New RLE encoding marker - rle_buf.clear(); - rle_compress(&bufr[..], &mut rle_buf); - w.write_all(&rle_buf[..])?; - rle_buf.clear(); - rle_compress(&bufg[..], &mut rle_buf); - w.write_all(&rle_buf[..])?; - rle_buf.clear(); - rle_compress(&bufb[..], &mut rle_buf); - w.write_all(&rle_buf[..])?; - rle_buf.clear(); - rle_compress(&bufe[..], &mut rle_buf); - w.write_all(&rle_buf[..])?; - } - } - Ok(()) - } -} - -#[derive(Debug, PartialEq, Eq)] -enum RunOrNot { - Run(u8, usize), - Norun(usize, usize), -} -use self::RunOrNot::{Norun, Run}; - -const RUN_MAX_LEN: usize = 127; -const NORUN_MAX_LEN: usize = 128; - -struct RunIterator<'a> { - data: &'a [u8], - curidx: usize, -} - -impl<'a> RunIterator<'a> { - fn new(data: &'a [u8]) -> RunIterator<'a> { - RunIterator { data, curidx: 0 } - } -} - -impl<'a> Iterator for RunIterator<'a> { - type Item = RunOrNot; - - fn next(&mut self) -> Option { - if self.curidx == self.data.len() { - None - } else { - let cv = self.data[self.curidx]; - let crun = self.data[self.curidx..] - .iter() - .take_while(|&&v| v == cv) - .take(RUN_MAX_LEN) - .count(); - let ret = if crun > 2 { - Run(cv, crun) - } else { - Norun(self.curidx, crun) - }; - self.curidx += crun; - Some(ret) - } - } -} - -struct NorunCombineIterator<'a> { - runiter: RunIterator<'a>, - prev: Option, -} - -impl<'a> NorunCombineIterator<'a> { - fn new(data: &'a [u8]) -> NorunCombineIterator<'a> { - NorunCombineIterator { - runiter: RunIterator::new(data), - prev: None, - } - } -} - -// Combines sequential noruns produced by RunIterator -impl<'a> Iterator for NorunCombineIterator<'a> { - type Item = RunOrNot; - fn next(&mut self) -> Option { - loop { - match self.prev.take() { - Some(Run(c, len)) => { - // Just return stored run - return Some(Run(c, len)); - } - Some(Norun(idx, len)) => { - // Let's see if we need to continue norun - match self.runiter.next() { - Some(Norun(_, len1)) => { - // norun continues - let clen = len + len1; // combined length - match clen.cmp(&NORUN_MAX_LEN) { - Ordering::Equal => return Some(Norun(idx, clen)), - Ordering::Greater => { - // combined norun exceeds maximum length. store extra part of norun - self.prev = - Some(Norun(idx + NORUN_MAX_LEN, clen - NORUN_MAX_LEN)); - // then return maximal norun - return Some(Norun(idx, NORUN_MAX_LEN)); - } - Ordering::Less => { - // len + len1 < NORUN_MAX_LEN - self.prev = Some(Norun(idx, len + len1)); - // combine and continue loop - } - } - } - Some(Run(c, len1)) => { - // Run encountered. Store it - self.prev = Some(Run(c, len1)); - return Some(Norun(idx, len)); // and return combined norun - } - None => { - // End of sequence - return Some(Norun(idx, len)); // return combined norun - } - } - } // End match self.prev.take() == Some(NoRun()) - None => { - // No norun to combine - match self.runiter.next() { - Some(Norun(idx, len)) => { - self.prev = Some(Norun(idx, len)); - // store for combine and continue the loop - } - Some(Run(c, len)) => { - // Some run. Just return it - return Some(Run(c, len)); - } - None => { - // That's all, folks - return None; - } - } - } // End match self.prev.take() == None - } // End match - } // End loop - } -} - -// Appends RLE compressed ```data``` to ```rle``` -fn rle_compress(data: &[u8], rle: &mut Vec) { - rle.clear(); - if data.is_empty() { - rle.push(0); // Technically correct. It means read next 0 bytes. - return; - } - // Task: split data into chunks of repeating (max 127) and non-repeating bytes (max 128) - // Prepend non-repeating chunk with its length - // Replace repeating byte with (run length + 128) and the byte - for rnr in NorunCombineIterator::new(data) { - match rnr { - Run(c, len) => { - assert!(len <= 127); - rle.push(128u8 + len as u8); - rle.push(c); - } - Norun(idx, len) => { - assert!(len <= 128); - rle.push(len as u8); - rle.extend_from_slice(&data[idx..idx + len]); - } - } - } -} - -fn write_rgbe8(w: &mut W, v: Rgbe8Pixel) -> Result<()> { - w.write_all(&[v.c[0], v.c[1], v.c[2], v.e]) -} - -/// Converts ```Rgb``` into ```Rgbe8Pixel``` -pub fn to_rgbe8(pix: Rgb) -> Rgbe8Pixel { - let pix = pix.0; - let mx = f32::max(pix[0], f32::max(pix[1], pix[2])); - if mx <= 0.0 { - Rgbe8Pixel { c: [0, 0, 0], e: 0 } - } else { - // let (frac, exp) = mx.frexp(); // unstable yet - let exp = mx.log2().floor() as i32 + 1; - let mul = f32::powi(2.0, exp); - let mut conv = [0u8; 3]; - for (cv, &sv) in conv.iter_mut().zip(pix.iter()) { - *cv = f32::trunc(sv / mul * 256.0) as u8; - } - Rgbe8Pixel { - c: conv, - e: (exp + 128) as u8, - } - } -} - -#[test] -fn to_rgbe8_test() { - use crate::codecs::hdr::rgbe8; - let test_cases = vec![rgbe8(0, 0, 0, 0), rgbe8(1, 1, 128, 128)]; - for &pix in &test_cases { - assert_eq!(pix, to_rgbe8(pix.to_hdr())); - } - for mc in 128..255 { - // TODO: use inclusive range when stable - let pix = rgbe8(mc, mc, mc, 100); - assert_eq!(pix, to_rgbe8(pix.to_hdr())); - let pix = rgbe8(mc, 0, mc, 130); - assert_eq!(pix, to_rgbe8(pix.to_hdr())); - let pix = rgbe8(0, 0, mc, 140); - assert_eq!(pix, to_rgbe8(pix.to_hdr())); - let pix = rgbe8(1, 0, mc, 150); - assert_eq!(pix, to_rgbe8(pix.to_hdr())); - let pix = rgbe8(1, mc, 10, 128); - assert_eq!(pix, to_rgbe8(pix.to_hdr())); - for c in 0..255 { - // Radiance HDR seems to be pre IEEE 754. - // exponent can be -128 (represented as 0u8), so some colors cannot be represented in normalized f32 - // Let's exclude exponent value of -128 (0u8) from testing - let pix = rgbe8(1, mc, c, if c == 0 { 1 } else { c }); - assert_eq!(pix, to_rgbe8(pix.to_hdr())); - } - } - fn relative_dist(a: Rgb, b: Rgb) -> f32 { - // maximal difference divided by maximal value - let max_diff = - a.0.iter() - .zip(b.0.iter()) - .fold(0.0, |diff, (&a, &b)| f32::max(diff, (a - b).abs())); - let max_val = - a.0.iter() - .chain(b.0.iter()) - .fold(0.0, |maxv, &a| f32::max(maxv, a)); - if max_val == 0.0 { - 0.0 - } else { - max_diff / max_val - } - } - let test_values = vec![ - 0.000_001, 0.000_02, 0.000_3, 0.004, 0.05, 0.6, 7.0, 80.0, 900.0, 1_000.0, 20_000.0, - 300_000.0, - ]; - for &r in &test_values { - for &g in &test_values { - for &b in &test_values { - let c1 = Rgb([r, g, b]); - let c2 = to_rgbe8(c1).to_hdr(); - let rel_dist = relative_dist(c1, c2); - // Maximal value is normalized to the range 128..256, thus we have 1/128 precision - assert!( - rel_dist <= 1.0 / 128.0, - "Relative distance ({}) exceeds 1/128 for {:?} and {:?}", - rel_dist, - c1, - c2 - ); - } - } - } -} - -#[test] -fn runiterator_test() { - let data = []; - let mut run_iter = RunIterator::new(&data[..]); - assert_eq!(run_iter.next(), None); - let data = [5]; - let mut run_iter = RunIterator::new(&data[..]); - assert_eq!(run_iter.next(), Some(Norun(0, 1))); - assert_eq!(run_iter.next(), None); - let data = [1, 1]; - let mut run_iter = RunIterator::new(&data[..]); - assert_eq!(run_iter.next(), Some(Norun(0, 2))); - assert_eq!(run_iter.next(), None); - let data = [0, 0, 0]; - let mut run_iter = RunIterator::new(&data[..]); - assert_eq!(run_iter.next(), Some(Run(0u8, 3))); - assert_eq!(run_iter.next(), None); - let data = [0, 0, 1, 1]; - let mut run_iter = RunIterator::new(&data[..]); - assert_eq!(run_iter.next(), Some(Norun(0, 2))); - assert_eq!(run_iter.next(), Some(Norun(2, 2))); - assert_eq!(run_iter.next(), None); - let data = [0, 0, 0, 1, 1]; - let mut run_iter = RunIterator::new(&data[..]); - assert_eq!(run_iter.next(), Some(Run(0u8, 3))); - assert_eq!(run_iter.next(), Some(Norun(3, 2))); - assert_eq!(run_iter.next(), None); - let data = [1, 2, 2, 2]; - let mut run_iter = RunIterator::new(&data[..]); - assert_eq!(run_iter.next(), Some(Norun(0, 1))); - assert_eq!(run_iter.next(), Some(Run(2u8, 3))); - assert_eq!(run_iter.next(), None); - let data = [1, 1, 2, 2, 2]; - let mut run_iter = RunIterator::new(&data[..]); - assert_eq!(run_iter.next(), Some(Norun(0, 2))); - assert_eq!(run_iter.next(), Some(Run(2u8, 3))); - assert_eq!(run_iter.next(), None); - let data = [2; 128]; - let mut run_iter = RunIterator::new(&data[..]); - assert_eq!(run_iter.next(), Some(Run(2u8, 127))); - assert_eq!(run_iter.next(), Some(Norun(127, 1))); - assert_eq!(run_iter.next(), None); - let data = [2; 129]; - let mut run_iter = RunIterator::new(&data[..]); - assert_eq!(run_iter.next(), Some(Run(2u8, 127))); - assert_eq!(run_iter.next(), Some(Norun(127, 2))); - assert_eq!(run_iter.next(), None); - let data = [2; 130]; - let mut run_iter = RunIterator::new(&data[..]); - assert_eq!(run_iter.next(), Some(Run(2u8, 127))); - assert_eq!(run_iter.next(), Some(Run(2u8, 3))); - assert_eq!(run_iter.next(), None); -} - -#[test] -fn noruncombine_test() { - fn a(mut v: Vec, mut other: Vec) -> Vec { - v.append(&mut other); - v - } - - let v = vec![]; - let mut rsi = NorunCombineIterator::new(&v[..]); - assert_eq!(rsi.next(), None); - - let v = vec![1]; - let mut rsi = NorunCombineIterator::new(&v[..]); - assert_eq!(rsi.next(), Some(Norun(0, 1))); - assert_eq!(rsi.next(), None); - - let v = vec![2, 2]; - let mut rsi = NorunCombineIterator::new(&v[..]); - assert_eq!(rsi.next(), Some(Norun(0, 2))); - assert_eq!(rsi.next(), None); - - let v = vec![3, 3, 3]; - let mut rsi = NorunCombineIterator::new(&v[..]); - assert_eq!(rsi.next(), Some(Run(3, 3))); - assert_eq!(rsi.next(), None); - - let v = vec![4, 4, 3, 3, 3]; - let mut rsi = NorunCombineIterator::new(&v[..]); - assert_eq!(rsi.next(), Some(Norun(0, 2))); - assert_eq!(rsi.next(), Some(Run(3, 3))); - assert_eq!(rsi.next(), None); - - let v = vec![40; 400]; - let mut rsi = NorunCombineIterator::new(&v[..]); - assert_eq!(rsi.next(), Some(Run(40, 127))); - assert_eq!(rsi.next(), Some(Run(40, 127))); - assert_eq!(rsi.next(), Some(Run(40, 127))); - assert_eq!(rsi.next(), Some(Run(40, 19))); - assert_eq!(rsi.next(), None); - - let v = a(a(vec![5; 3], vec![6; 129]), vec![7, 3, 7, 10, 255]); - let mut rsi = NorunCombineIterator::new(&v[..]); - assert_eq!(rsi.next(), Some(Run(5, 3))); - assert_eq!(rsi.next(), Some(Run(6, 127))); - assert_eq!(rsi.next(), Some(Norun(130, 7))); - assert_eq!(rsi.next(), None); - - let v = a(a(vec![5; 2], vec![6; 129]), vec![7, 3, 7, 7, 255]); - let mut rsi = NorunCombineIterator::new(&v[..]); - assert_eq!(rsi.next(), Some(Norun(0, 2))); - assert_eq!(rsi.next(), Some(Run(6, 127))); - assert_eq!(rsi.next(), Some(Norun(129, 7))); - assert_eq!(rsi.next(), None); - - let v: Vec<_> = ::std::iter::repeat(()) - .flat_map(|_| (0..2)) - .take(257) - .collect(); - let mut rsi = NorunCombineIterator::new(&v[..]); - assert_eq!(rsi.next(), Some(Norun(0, 128))); - assert_eq!(rsi.next(), Some(Norun(128, 128))); - assert_eq!(rsi.next(), Some(Norun(256, 1))); - assert_eq!(rsi.next(), None); -} diff --git a/vendor/image/src/codecs/hdr/mod.rs b/vendor/image/src/codecs/hdr/mod.rs deleted file mode 100644 index b3325bc..0000000 --- a/vendor/image/src/codecs/hdr/mod.rs +++ /dev/null @@ -1,15 +0,0 @@ -//! Decoding of Radiance HDR Images -//! -//! A decoder for Radiance HDR images -//! -//! # Related Links -//! -//! * -//! * -//! - -mod decoder; -mod encoder; - -pub use self::decoder::*; -pub use self::encoder::*; -- cgit v1.2.3