Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 1 addition & 40 deletions src/codecs/bmp/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ use crate::color::ColorType;
use crate::error::{
DecodingError, ImageError, ImageResult, UnsupportedError, UnsupportedErrorKind,
};
use crate::io::free_functions::load_rect;
use crate::io::ReadExt;
use crate::{ImageDecoder, ImageDecoderRect, ImageFormat};
use crate::{ImageDecoder, ImageFormat};

const BITMAPCOREHEADER_SIZE: u32 = 12;
const BITMAPINFOHEADER_SIZE: u32 = 40;
Expand Down Expand Up @@ -1415,34 +1414,6 @@ impl<R: BufRead + Seek> ImageDecoder for BmpDecoder<R> {
}
}

impl<R: BufRead + Seek> ImageDecoderRect for BmpDecoder<R> {
fn read_rect(
&mut self,
x: u32,
y: u32,
width: u32,
height: u32,
buf: &mut [u8],
row_pitch: usize,
) -> ImageResult<()> {
let start = self.reader.stream_position()?;
load_rect(
x,
y,
width,
height,
buf,
row_pitch,
self,
self.total_bytes() as usize,
|_, _| Ok(()),
|s, buf| s.read_image_data(buf),
)?;
self.reader.seek(SeekFrom::Start(start))?;
Ok(())
}
}

#[cfg(test)]
mod test {
use std::io::{BufReader, Cursor};
Expand All @@ -1464,16 +1435,6 @@ mod test {
}
}

#[test]
fn read_rect() {
let f =
BufReader::new(std::fs::File::open("tests/images/bmp/images/Core_8_Bit.bmp").unwrap());
let mut decoder = BmpDecoder::new(f).unwrap();

let mut buf: Vec<u8> = vec![0; 8 * 8 * 3];
decoder.read_rect(0, 0, 8, 8, &mut buf, 8 * 3).unwrap();
}

#[test]
fn read_rle_too_short() {
let data = vec![
Expand Down
117 changes: 2 additions & 115 deletions src/codecs/farbfeld.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ use crate::color::ExtendedColorType;
use crate::error::{
DecodingError, ImageError, ImageResult, UnsupportedError, UnsupportedErrorKind,
};
use crate::io::free_functions::load_rect;
use crate::{ColorType, ImageDecoder, ImageDecoderRect, ImageEncoder, ImageFormat};
use crate::{ColorType, ImageDecoder, ImageEncoder, ImageFormat};

/// farbfeld Reader
pub struct FarbfeldReader<R: Read> {
Expand Down Expand Up @@ -215,36 +214,6 @@ impl<R: Read> ImageDecoder for FarbfeldDecoder<R> {
}
}

impl<R: Read + Seek> ImageDecoderRect for FarbfeldDecoder<R> {
fn read_rect(
&mut self,
x: u32,
y: u32,
width: u32,
height: u32,
buf: &mut [u8],
row_pitch: usize,
) -> ImageResult<()> {
// A "scanline" (defined as "shortest non-caching read" in the doc) is just one channel in this case

let start = self.reader.stream_position()?;
load_rect(
x,
y,
width,
height,
buf,
row_pitch,
self,
2,
|s, scanline| s.reader.seek(SeekFrom::Start(scanline * 2)).map(|_| ()),
|s, buf| s.reader.read_exact(buf),
)?;
self.reader.seek(SeekFrom::Start(start))?;
Ok(())
}
}

/// farbfeld encoder
pub struct FarbfeldEncoder<W: Write> {
w: W,
Expand Down Expand Up @@ -314,94 +283,12 @@ impl<W: Write> ImageEncoder for FarbfeldEncoder<W> {
#[cfg(test)]
mod tests {
use crate::codecs::farbfeld::FarbfeldDecoder;
use crate::ImageDecoderRect;
use byteorder_lite::{ByteOrder, NativeEndian};
use std::io::{Cursor, Seek, SeekFrom};

static RECTANGLE_IN: &[u8] = b"farbfeld\
\x00\x00\x00\x02\x00\x00\x00\x03\
\xFF\x01\xFE\x02\xFD\x03\xFC\x04\xFB\x05\xFA\x06\xF9\x07\xF8\x08\
\xF7\x09\xF6\x0A\xF5\x0B\xF4\x0C\xF3\x0D\xF2\x0E\xF1\x0F\xF0\x10\
\xEF\x11\xEE\x12\xED\x13\xEC\x14\xEB\x15\xEA\x16\xE9\x17\xE8\x18";

#[test]
fn read_rect_1x2() {
static RECTANGLE_OUT: &[u16] = &[
0xF30D, 0xF20E, 0xF10F, 0xF010, 0xEB15, 0xEA16, 0xE917, 0xE818,
];

read_rect(1, 1, 1, 2, RECTANGLE_OUT);
}

#[test]
fn read_rect_2x2() {
static RECTANGLE_OUT: &[u16] = &[
0xFF01, 0xFE02, 0xFD03, 0xFC04, 0xFB05, 0xFA06, 0xF907, 0xF808, 0xF709, 0xF60A, 0xF50B,
0xF40C, 0xF30D, 0xF20E, 0xF10F, 0xF010,
];

read_rect(0, 0, 2, 2, RECTANGLE_OUT);
}

#[test]
fn read_rect_2x1() {
static RECTANGLE_OUT: &[u16] = &[
0xEF11, 0xEE12, 0xED13, 0xEC14, 0xEB15, 0xEA16, 0xE917, 0xE818,
];

read_rect(0, 2, 2, 1, RECTANGLE_OUT);
}

#[test]
fn read_rect_2x3() {
static RECTANGLE_OUT: &[u16] = &[
0xFF01, 0xFE02, 0xFD03, 0xFC04, 0xFB05, 0xFA06, 0xF907, 0xF808, 0xF709, 0xF60A, 0xF50B,
0xF40C, 0xF30D, 0xF20E, 0xF10F, 0xF010, 0xEF11, 0xEE12, 0xED13, 0xEC14, 0xEB15, 0xEA16,
0xE917, 0xE818,
];

read_rect(0, 0, 2, 3, RECTANGLE_OUT);
}

#[test]
fn read_rect_in_stream() {
static RECTANGLE_OUT: &[u16] = &[0xEF11, 0xEE12, 0xED13, 0xEC14];

let mut input = vec![];
input.extend_from_slice(b"This is a 31-byte-long prologue");
input.extend_from_slice(RECTANGLE_IN);
let mut input_cur = Cursor::new(input);
input_cur.seek(SeekFrom::Start(31)).unwrap();

let mut out_buf = [0u8; 64];
FarbfeldDecoder::new(input_cur)
.unwrap()
.read_rect(0, 2, 1, 1, &mut out_buf, 8)
.unwrap();
let exp = degenerate_pixels(RECTANGLE_OUT);
assert_eq!(&out_buf[..exp.len()], &exp[..]);
}
use std::io::Cursor;

#[test]
fn dimension_overflow() {
let header = b"farbfeld\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF";

assert!(FarbfeldDecoder::new(Cursor::new(header)).is_err());
}

fn read_rect(x: u32, y: u32, width: u32, height: u32, exp_wide: &[u16]) {
let mut out_buf = [0u8; 64];
FarbfeldDecoder::new(Cursor::new(RECTANGLE_IN))
.unwrap()
.read_rect(x, y, width, height, &mut out_buf, width as usize * 8)
.unwrap();
let exp = degenerate_pixels(exp_wide);
assert_eq!(&out_buf[..exp.len()], &exp[..]);
}

fn degenerate_pixels(exp_wide: &[u16]) -> Vec<u8> {
let mut exp = vec![0u8; exp_wide.len() * 2];
NativeEndian::write_u16_into(exp_wide, &mut exp);
exp
}
}
20 changes: 0 additions & 20 deletions src/io/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,26 +175,6 @@ impl<T: ?Sized + ImageDecoder> ImageDecoder for Box<T> {
}
}

/// Specialized image decoding not be supported by all formats
pub trait ImageDecoderRect: ImageDecoder {
/// Decode a rectangular section of the image.
///
/// This function takes a slice of bytes and writes the pixel data of the image into it.
/// The rectangle is specified by the x and y coordinates of the top left corner, the width
/// and height of the rectangle, and the row pitch of the buffer. The row pitch is the number
/// of bytes between the start of one row and the start of the next row. The row pitch must be
/// at least as large as the width of the rectangle in bytes.
fn read_rect(
&mut self,
x: u32,
y: u32,
width: u32,
height: u32,
buf: &mut [u8],
row_pitch: usize,
) -> ImageResult<()>;
}

/// `AnimationDecoder` trait
pub trait AnimationDecoder<'a> {
/// Consume the decoder producing a series of frames.
Expand Down
Loading
Loading