/src/image/src/codecs/pnm/decoder.rs
Line | Count | Source (jump to first uncovered line) |
1 | | use std::error; |
2 | | use std::fmt::{self, Display}; |
3 | | use std::io::{self, Read}; |
4 | | use std::mem::size_of; |
5 | | use std::num::ParseIntError; |
6 | | use std::str; |
7 | | |
8 | | use super::{ArbitraryHeader, ArbitraryTuplType, BitmapHeader, GraymapHeader, PixmapHeader}; |
9 | | use super::{HeaderRecord, PnmHeader, PnmSubtype, SampleEncoding}; |
10 | | use crate::color::{ColorType, ExtendedColorType}; |
11 | | use crate::error::{ |
12 | | DecodingError, ImageError, ImageResult, UnsupportedError, UnsupportedErrorKind, |
13 | | }; |
14 | | use crate::io::ReadExt; |
15 | | use crate::{utils, ImageDecoder, ImageFormat}; |
16 | | |
17 | | use byteorder_lite::{BigEndian, ByteOrder, NativeEndian}; |
18 | | |
19 | | /// All errors that can occur when attempting to parse a PNM |
20 | | #[derive(Debug, Clone)] |
21 | | enum DecoderError { |
22 | | /// PNM's "P[123456]" signature wrong or missing |
23 | | PnmMagicInvalid([u8; 2]), |
24 | | /// Couldn't parse the specified string as an integer from the specified source |
25 | | UnparsableValue(ErrorDataSource, String, ParseIntError), |
26 | | |
27 | | /// More than the exactly one allowed plane specified by the format |
28 | | NonAsciiByteInHeader(u8), |
29 | | /// The PAM header contained a non-ASCII byte |
30 | | NonAsciiLineInPamHeader, |
31 | | /// Couldn't parse an integer: expected but did not get an ASCII digit |
32 | | InvalidDigit(ErrorDataSource), |
33 | | |
34 | | /// The byte after the P7 magic was not 0x0A NEWLINE |
35 | | NotNewlineAfterP7Magic(u8), |
36 | | /// The PNM header had too few lines |
37 | | UnexpectedPnmHeaderEnd, |
38 | | |
39 | | /// The specified line was specified twice |
40 | | HeaderLineDuplicated(PnmHeaderLine), |
41 | | /// The line with the specified ID was not understood |
42 | | HeaderLineUnknown(String), |
43 | | /// At least one of the required lines were missing from the header (are `None` here) |
44 | | /// |
45 | | /// Same names as [`PnmHeaderLine`](enum.PnmHeaderLine.html) |
46 | | #[allow(missing_docs)] |
47 | | HeaderLineMissing { |
48 | | height: Option<u32>, |
49 | | width: Option<u32>, |
50 | | depth: Option<u32>, |
51 | | maxval: Option<u32>, |
52 | | }, |
53 | | |
54 | | /// Not enough data was provided to the Decoder to decode the image |
55 | | InputTooShort, |
56 | | /// Sample raster contained unexpected byte |
57 | | UnexpectedByteInRaster(u8), |
58 | | /// Specified sample was out of bounds (e.g. >1 in B&W) |
59 | | SampleOutOfBounds(u8), |
60 | | /// The image's maxval is zero |
61 | | MaxvalZero, |
62 | | /// The image's maxval exceeds 0xFFFF |
63 | | MaxvalTooBig(u32), |
64 | | |
65 | | /// The specified tuple type supports restricted depths and maxvals, those restrictions were not met |
66 | | InvalidDepthOrMaxval { |
67 | | tuple_type: ArbitraryTuplType, |
68 | | depth: u32, |
69 | | maxval: u32, |
70 | | }, |
71 | | /// The specified tuple type supports restricted depths, those restrictions were not met |
72 | | InvalidDepth { |
73 | | tuple_type: ArbitraryTuplType, |
74 | | depth: u32, |
75 | | }, |
76 | | /// The tuple type was not recognised by the parser |
77 | | TupleTypeUnrecognised, |
78 | | |
79 | | /// Overflowed the specified value when parsing |
80 | | Overflow, |
81 | | } |
82 | | |
83 | | impl Display for DecoderError { |
84 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
85 | 0 | match self { |
86 | 0 | DecoderError::PnmMagicInvalid(magic) => f.write_fmt(format_args!( |
87 | 0 | "Expected magic constant for PNM: P1..P7, got [{:#04X?}, {:#04X?}]", |
88 | 0 | magic[0], magic[1] |
89 | 0 | )), |
90 | 0 | DecoderError::UnparsableValue(src, data, err) => { |
91 | 0 | f.write_fmt(format_args!("Error parsing {data:?} as {src}: {err}")) |
92 | | } |
93 | | |
94 | 0 | DecoderError::NonAsciiByteInHeader(c) => { |
95 | 0 | f.write_fmt(format_args!("Non-ASCII character {c:#04X?} in header")) |
96 | | } |
97 | 0 | DecoderError::NonAsciiLineInPamHeader => f.write_str("Non-ASCII line in PAM header"), |
98 | 0 | DecoderError::InvalidDigit(src) => { |
99 | 0 | f.write_fmt(format_args!("Non-ASCII-digit character when parsing number in {src}")) |
100 | | } |
101 | | |
102 | 0 | DecoderError::NotNewlineAfterP7Magic(c) => f.write_fmt(format_args!( |
103 | 0 | "Expected newline after P7 magic, got {c:#04X?}" |
104 | 0 | )), |
105 | 0 | DecoderError::UnexpectedPnmHeaderEnd => f.write_str("Unexpected end of PNM header"), |
106 | | |
107 | 0 | DecoderError::HeaderLineDuplicated(line) => { |
108 | 0 | f.write_fmt(format_args!("Duplicate {line} line")) |
109 | | } |
110 | 0 | DecoderError::HeaderLineUnknown(identifier) => f.write_fmt(format_args!( |
111 | 0 | "Unknown header line with identifier {identifier:?}" |
112 | 0 | )), |
113 | | DecoderError::HeaderLineMissing { |
114 | 0 | height, |
115 | 0 | width, |
116 | 0 | depth, |
117 | 0 | maxval, |
118 | 0 | } => f.write_fmt(format_args!( |
119 | 0 | "Missing header line: have height={height:?}, width={width:?}, depth={depth:?}, maxval={maxval:?}" |
120 | 0 | )), |
121 | | |
122 | | DecoderError::InputTooShort => { |
123 | 0 | f.write_str("Not enough data was provided to the Decoder to decode the image") |
124 | | } |
125 | 0 | DecoderError::UnexpectedByteInRaster(c) => f.write_fmt(format_args!( |
126 | 0 | "Unexpected character {c:#04X?} within sample raster" |
127 | 0 | )), |
128 | 0 | DecoderError::SampleOutOfBounds(val) => { |
129 | 0 | f.write_fmt(format_args!("Sample value {val} outside of bounds")) |
130 | | } |
131 | 0 | DecoderError::MaxvalZero => f.write_str("Image MAXVAL is zero"), |
132 | 0 | DecoderError::MaxvalTooBig(maxval) => { |
133 | 0 | f.write_fmt(format_args!("Image MAXVAL exceeds {}: {}", 0xFFFF, maxval)) |
134 | | } |
135 | | |
136 | | DecoderError::InvalidDepthOrMaxval { |
137 | 0 | tuple_type, |
138 | 0 | depth, |
139 | 0 | maxval, |
140 | 0 | } => f.write_fmt(format_args!( |
141 | 0 | "Invalid depth ({}) or maxval ({}) for tuple type {}", |
142 | 0 | depth, |
143 | 0 | maxval, |
144 | 0 | tuple_type.name() |
145 | 0 | )), |
146 | 0 | DecoderError::InvalidDepth { tuple_type, depth } => f.write_fmt(format_args!( |
147 | 0 | "Invalid depth ({}) for tuple type {}", |
148 | 0 | depth, |
149 | 0 | tuple_type.name() |
150 | 0 | )), |
151 | 0 | DecoderError::TupleTypeUnrecognised => f.write_str("Tuple type not recognized"), |
152 | 0 | DecoderError::Overflow => f.write_str("Overflow when parsing value"), |
153 | | } |
154 | 0 | } |
155 | | } |
156 | | |
157 | | /// Note: should `pnm` be extracted into a separate crate, |
158 | | /// this will need to be hidden until that crate hits version `1.0`. |
159 | | impl From<DecoderError> for ImageError { |
160 | 1.87k | fn from(e: DecoderError) -> ImageError { |
161 | 1.87k | ImageError::Decoding(DecodingError::new(ImageFormat::Pnm.into(), e)) |
162 | 1.87k | } |
163 | | } |
164 | | |
165 | | impl error::Error for DecoderError { |
166 | 0 | fn source(&self) -> Option<&(dyn error::Error + 'static)> { |
167 | 0 | match self { |
168 | 0 | DecoderError::UnparsableValue(_, _, err) => Some(err), |
169 | 0 | _ => None, |
170 | | } |
171 | 0 | } |
172 | | } |
173 | | |
174 | | /// Single-value lines in a PNM header |
175 | | #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] |
176 | | enum PnmHeaderLine { |
177 | | /// "HEIGHT" |
178 | | Height, |
179 | | /// "WIDTH" |
180 | | Width, |
181 | | /// "DEPTH" |
182 | | Depth, |
183 | | /// "MAXVAL", a.k.a. `maxwhite` |
184 | | Maxval, |
185 | | } |
186 | | |
187 | | impl Display for PnmHeaderLine { |
188 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
189 | 0 | f.write_str(match self { |
190 | 0 | PnmHeaderLine::Height => "HEIGHT", |
191 | 0 | PnmHeaderLine::Width => "WIDTH", |
192 | 0 | PnmHeaderLine::Depth => "DEPTH", |
193 | 0 | PnmHeaderLine::Maxval => "MAXVAL", |
194 | | }) |
195 | 0 | } |
196 | | } |
197 | | |
198 | | /// Single-value lines in a PNM header |
199 | | #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] |
200 | | enum ErrorDataSource { |
201 | | /// One of the header lines |
202 | | Line(PnmHeaderLine), |
203 | | /// Value in the preamble |
204 | | Preamble, |
205 | | /// Sample/pixel data |
206 | | Sample, |
207 | | } |
208 | | |
209 | | impl Display for ErrorDataSource { |
210 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
211 | 0 | match self { |
212 | 0 | ErrorDataSource::Line(l) => l.fmt(f), |
213 | 0 | ErrorDataSource::Preamble => f.write_str("number in preamble"), |
214 | 0 | ErrorDataSource::Sample => f.write_str("sample"), |
215 | | } |
216 | 0 | } |
217 | | } |
218 | | |
219 | | /// Dynamic representation, represents all decodable (sample, depth) combinations. |
220 | | #[derive(Clone, Copy)] |
221 | | enum TupleType { |
222 | | PbmBit, |
223 | | BWBit, |
224 | | GrayU8, |
225 | | GrayU16, |
226 | | RGBU8, |
227 | | RGBU16, |
228 | | } |
229 | | |
230 | | trait Sample { |
231 | | type Representation; |
232 | | |
233 | | /// Representation size in bytes |
234 | 1.77k | fn sample_size() -> u32 { |
235 | 1.77k | size_of::<Self::Representation>() as u32 |
236 | 1.77k | } Unexecuted instantiation: <image::codecs::pnm::decoder::U8 as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::U16 as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::BWBit as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::PbmBit as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <_ as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::U8 as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::U16 as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::BWBit as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::PbmBit as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::U8 as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::U16 as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::BWBit as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::PbmBit as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::U8 as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::U16 as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::BWBit as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::PbmBit as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::U8 as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::U16 as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::BWBit as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::PbmBit as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::U8 as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::U16 as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::BWBit as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::PbmBit as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::U8 as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::U16 as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::BWBit as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::PbmBit as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::U8 as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::U16 as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::BWBit as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::PbmBit as image::codecs::pnm::decoder::Sample>::sample_size <image::codecs::pnm::decoder::U8 as image::codecs::pnm::decoder::Sample>::sample_size Line | Count | Source | 234 | 504 | fn sample_size() -> u32 { | 235 | 504 | size_of::<Self::Representation>() as u32 | 236 | 504 | } |
<image::codecs::pnm::decoder::U16 as image::codecs::pnm::decoder::Sample>::sample_size Line | Count | Source | 234 | 658 | fn sample_size() -> u32 { | 235 | 658 | size_of::<Self::Representation>() as u32 | 236 | 658 | } |
<image::codecs::pnm::decoder::BWBit as image::codecs::pnm::decoder::Sample>::sample_size Line | Count | Source | 234 | 123 | fn sample_size() -> u32 { | 235 | 123 | size_of::<Self::Representation>() as u32 | 236 | 123 | } |
<image::codecs::pnm::decoder::PbmBit as image::codecs::pnm::decoder::Sample>::sample_size Line | Count | Source | 234 | 402 | fn sample_size() -> u32 { | 235 | 402 | size_of::<Self::Representation>() as u32 | 236 | 402 | } |
Unexecuted instantiation: <image::codecs::pnm::decoder::U8 as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::U16 as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::BWBit as image::codecs::pnm::decoder::Sample>::sample_size Unexecuted instantiation: <image::codecs::pnm::decoder::PbmBit as image::codecs::pnm::decoder::Sample>::sample_size <image::codecs::pnm::decoder::U8 as image::codecs::pnm::decoder::Sample>::sample_size Line | Count | Source | 234 | 19 | fn sample_size() -> u32 { | 235 | 19 | size_of::<Self::Representation>() as u32 | 236 | 19 | } |
<image::codecs::pnm::decoder::U16 as image::codecs::pnm::decoder::Sample>::sample_size Line | Count | Source | 234 | 55 | fn sample_size() -> u32 { | 235 | 55 | size_of::<Self::Representation>() as u32 | 236 | 55 | } |
<image::codecs::pnm::decoder::BWBit as image::codecs::pnm::decoder::Sample>::sample_size Line | Count | Source | 234 | 1 | fn sample_size() -> u32 { | 235 | 1 | size_of::<Self::Representation>() as u32 | 236 | 1 | } |
<image::codecs::pnm::decoder::PbmBit as image::codecs::pnm::decoder::Sample>::sample_size Line | Count | Source | 234 | 8 | fn sample_size() -> u32 { | 235 | 8 | size_of::<Self::Representation>() as u32 | 236 | 8 | } |
|
237 | 452 | fn bytelen(width: u32, height: u32, samples: u32) -> ImageResult<usize> { |
238 | 452 | Ok((width * height * samples * Self::sample_size()) as usize) |
239 | 452 | } Unexecuted instantiation: <image::codecs::pnm::decoder::U8 as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::U16 as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::BWBit as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <_ as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::U8 as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::U16 as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::BWBit as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::U8 as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::U16 as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::BWBit as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::U8 as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::U16 as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::BWBit as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::U8 as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::U16 as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::BWBit as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::U8 as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::U16 as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::BWBit as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::U8 as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::U16 as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::BWBit as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::U8 as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::U16 as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::BWBit as image::codecs::pnm::decoder::Sample>::bytelen <image::codecs::pnm::decoder::U8 as image::codecs::pnm::decoder::Sample>::bytelen Line | Count | Source | 237 | 197 | fn bytelen(width: u32, height: u32, samples: u32) -> ImageResult<usize> { | 238 | 197 | Ok((width * height * samples * Self::sample_size()) as usize) | 239 | 197 | } |
<image::codecs::pnm::decoder::U16 as image::codecs::pnm::decoder::Sample>::bytelen Line | Count | Source | 237 | 174 | fn bytelen(width: u32, height: u32, samples: u32) -> ImageResult<usize> { | 238 | 174 | Ok((width * height * samples * Self::sample_size()) as usize) | 239 | 174 | } |
<image::codecs::pnm::decoder::BWBit as image::codecs::pnm::decoder::Sample>::bytelen Line | Count | Source | 237 | 61 | fn bytelen(width: u32, height: u32, samples: u32) -> ImageResult<usize> { | 238 | 61 | Ok((width * height * samples * Self::sample_size()) as usize) | 239 | 61 | } |
Unexecuted instantiation: <image::codecs::pnm::decoder::U8 as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::U16 as image::codecs::pnm::decoder::Sample>::bytelen Unexecuted instantiation: <image::codecs::pnm::decoder::BWBit as image::codecs::pnm::decoder::Sample>::bytelen <image::codecs::pnm::decoder::U8 as image::codecs::pnm::decoder::Sample>::bytelen Line | Count | Source | 237 | 7 | fn bytelen(width: u32, height: u32, samples: u32) -> ImageResult<usize> { | 238 | 7 | Ok((width * height * samples * Self::sample_size()) as usize) | 239 | 7 | } |
<image::codecs::pnm::decoder::U16 as image::codecs::pnm::decoder::Sample>::bytelen Line | Count | Source | 237 | 12 | fn bytelen(width: u32, height: u32, samples: u32) -> ImageResult<usize> { | 238 | 12 | Ok((width * height * samples * Self::sample_size()) as usize) | 239 | 12 | } |
<image::codecs::pnm::decoder::BWBit as image::codecs::pnm::decoder::Sample>::bytelen Line | Count | Source | 237 | 1 | fn bytelen(width: u32, height: u32, samples: u32) -> ImageResult<usize> { | 238 | 1 | Ok((width * height * samples * Self::sample_size()) as usize) | 239 | 1 | } |
|
240 | | fn from_bytes(bytes: &[u8], row_size: usize, output_buf: &mut [u8]) -> ImageResult<()>; |
241 | | fn from_ascii(reader: &mut dyn Read, output_buf: &mut [u8]) -> ImageResult<()>; |
242 | | } |
243 | | |
244 | | struct U8; |
245 | | struct U16; |
246 | | struct PbmBit; |
247 | | struct BWBit; |
248 | | |
249 | | trait DecodableImageHeader { |
250 | | fn tuple_type(&self) -> ImageResult<TupleType>; |
251 | | } |
252 | | |
253 | | /// PNM decoder |
254 | | pub struct PnmDecoder<R> { |
255 | | reader: R, |
256 | | header: PnmHeader, |
257 | | tuple: TupleType, |
258 | | } |
259 | | |
260 | | impl<R: Read> PnmDecoder<R> { |
261 | | /// Create a new decoder that decodes from the stream ```read``` |
262 | 3.08k | pub fn new(mut buffered_read: R) -> ImageResult<PnmDecoder<R>> { |
263 | 3.08k | let magic = buffered_read.read_magic_constant()?; |
264 | | |
265 | 3.07k | let subtype = match magic { |
266 | 210 | [b'P', b'1'] => PnmSubtype::Bitmap(SampleEncoding::Ascii), |
267 | 251 | [b'P', b'2'] => PnmSubtype::Graymap(SampleEncoding::Ascii), |
268 | 398 | [b'P', b'3'] => PnmSubtype::Pixmap(SampleEncoding::Ascii), |
269 | 445 | [b'P', b'4'] => PnmSubtype::Bitmap(SampleEncoding::Binary), |
270 | 159 | [b'P', b'5'] => PnmSubtype::Graymap(SampleEncoding::Binary), |
271 | 185 | [b'P', b'6'] => PnmSubtype::Pixmap(SampleEncoding::Binary), |
272 | 1.41k | [b'P', b'7'] => PnmSubtype::ArbitraryMap, |
273 | 18 | _ => return Err(DecoderError::PnmMagicInvalid(magic).into()), |
274 | | }; |
275 | | |
276 | 3.06k | let decoder = match subtype { |
277 | 655 | PnmSubtype::Bitmap(enc) => PnmDecoder::read_bitmap_header(buffered_read, enc), |
278 | 410 | PnmSubtype::Graymap(enc) => PnmDecoder::read_graymap_header(buffered_read, enc), |
279 | 583 | PnmSubtype::Pixmap(enc) => PnmDecoder::read_pixmap_header(buffered_read, enc), |
280 | 1.41k | PnmSubtype::ArbitraryMap => PnmDecoder::read_arbitrary_header(buffered_read), |
281 | 1.58k | }?; |
282 | | |
283 | 1.47k | if utils::check_dimension_overflow( |
284 | 1.47k | decoder.dimensions().0, |
285 | 1.47k | decoder.dimensions().1, |
286 | 1.47k | decoder.color_type().bytes_per_pixel(), |
287 | 1.47k | ) { |
288 | 3 | return Err(ImageError::Unsupported( |
289 | 3 | UnsupportedError::from_format_and_kind( |
290 | 3 | ImageFormat::Pnm.into(), |
291 | 3 | UnsupportedErrorKind::GenericFeature(format!( |
292 | 3 | "Image dimensions ({}x{}) are too large", |
293 | 3 | decoder.dimensions().0, |
294 | 3 | decoder.dimensions().1 |
295 | 3 | )), |
296 | 3 | ), |
297 | 3 | )); |
298 | 1.47k | } |
299 | 1.47k | |
300 | 1.47k | Ok(decoder) |
301 | 3.08k | } Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::new Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<_>>::new Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::new Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::new Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::new Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::new Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::new Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::new Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::new <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::new Line | Count | Source | 262 | 2.95k | pub fn new(mut buffered_read: R) -> ImageResult<PnmDecoder<R>> { | 263 | 2.95k | let magic = buffered_read.read_magic_constant()?; | 264 | | | 265 | 2.94k | let subtype = match magic { | 266 | 206 | [b'P', b'1'] => PnmSubtype::Bitmap(SampleEncoding::Ascii), | 267 | 233 | [b'P', b'2'] => PnmSubtype::Graymap(SampleEncoding::Ascii), | 268 | 389 | [b'P', b'3'] => PnmSubtype::Pixmap(SampleEncoding::Ascii), | 269 | 440 | [b'P', b'4'] => PnmSubtype::Bitmap(SampleEncoding::Binary), | 270 | 155 | [b'P', b'5'] => PnmSubtype::Graymap(SampleEncoding::Binary), | 271 | 168 | [b'P', b'6'] => PnmSubtype::Pixmap(SampleEncoding::Binary), | 272 | 1.33k | [b'P', b'7'] => PnmSubtype::ArbitraryMap, | 273 | 18 | _ => return Err(DecoderError::PnmMagicInvalid(magic).into()), | 274 | | }; | 275 | | | 276 | 2.92k | let decoder = match subtype { | 277 | 646 | PnmSubtype::Bitmap(enc) => PnmDecoder::read_bitmap_header(buffered_read, enc), | 278 | 388 | PnmSubtype::Graymap(enc) => PnmDecoder::read_graymap_header(buffered_read, enc), | 279 | 557 | PnmSubtype::Pixmap(enc) => PnmDecoder::read_pixmap_header(buffered_read, enc), | 280 | 1.33k | PnmSubtype::ArbitraryMap => PnmDecoder::read_arbitrary_header(buffered_read), | 281 | 1.50k | }?; | 282 | | | 283 | 1.42k | if utils::check_dimension_overflow( | 284 | 1.42k | decoder.dimensions().0, | 285 | 1.42k | decoder.dimensions().1, | 286 | 1.42k | decoder.color_type().bytes_per_pixel(), | 287 | 1.42k | ) { | 288 | 3 | return Err(ImageError::Unsupported( | 289 | 3 | UnsupportedError::from_format_and_kind( | 290 | 3 | ImageFormat::Pnm.into(), | 291 | 3 | UnsupportedErrorKind::GenericFeature(format!( | 292 | 3 | "Image dimensions ({}x{}) are too large", | 293 | 3 | decoder.dimensions().0, | 294 | 3 | decoder.dimensions().1 | 295 | 3 | )), | 296 | 3 | ), | 297 | 3 | )); | 298 | 1.42k | } | 299 | 1.42k | | 300 | 1.42k | Ok(decoder) | 301 | 2.95k | } |
Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::new <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::new Line | Count | Source | 262 | 136 | pub fn new(mut buffered_read: R) -> ImageResult<PnmDecoder<R>> { | 263 | 136 | let magic = buffered_read.read_magic_constant()?; | 264 | | | 265 | 136 | let subtype = match magic { | 266 | 4 | [b'P', b'1'] => PnmSubtype::Bitmap(SampleEncoding::Ascii), | 267 | 18 | [b'P', b'2'] => PnmSubtype::Graymap(SampleEncoding::Ascii), | 268 | 9 | [b'P', b'3'] => PnmSubtype::Pixmap(SampleEncoding::Ascii), | 269 | 5 | [b'P', b'4'] => PnmSubtype::Bitmap(SampleEncoding::Binary), | 270 | 4 | [b'P', b'5'] => PnmSubtype::Graymap(SampleEncoding::Binary), | 271 | 17 | [b'P', b'6'] => PnmSubtype::Pixmap(SampleEncoding::Binary), | 272 | 79 | [b'P', b'7'] => PnmSubtype::ArbitraryMap, | 273 | 0 | _ => return Err(DecoderError::PnmMagicInvalid(magic).into()), | 274 | | }; | 275 | | | 276 | 136 | let decoder = match subtype { | 277 | 9 | PnmSubtype::Bitmap(enc) => PnmDecoder::read_bitmap_header(buffered_read, enc), | 278 | 22 | PnmSubtype::Graymap(enc) => PnmDecoder::read_graymap_header(buffered_read, enc), | 279 | 26 | PnmSubtype::Pixmap(enc) => PnmDecoder::read_pixmap_header(buffered_read, enc), | 280 | 79 | PnmSubtype::ArbitraryMap => PnmDecoder::read_arbitrary_header(buffered_read), | 281 | 86 | }?; | 282 | | | 283 | 50 | if utils::check_dimension_overflow( | 284 | 50 | decoder.dimensions().0, | 285 | 50 | decoder.dimensions().1, | 286 | 50 | decoder.color_type().bytes_per_pixel(), | 287 | 50 | ) { | 288 | 0 | return Err(ImageError::Unsupported( | 289 | 0 | UnsupportedError::from_format_and_kind( | 290 | 0 | ImageFormat::Pnm.into(), | 291 | 0 | UnsupportedErrorKind::GenericFeature(format!( | 292 | 0 | "Image dimensions ({}x{}) are too large", | 293 | 0 | decoder.dimensions().0, | 294 | 0 | decoder.dimensions().1 | 295 | 0 | )), | 296 | 0 | ), | 297 | 0 | )); | 298 | 50 | } | 299 | 50 | | 300 | 50 | Ok(decoder) | 301 | 136 | } |
|
302 | | |
303 | | /// Extract the reader and header after an image has been read. |
304 | 0 | pub fn into_inner(self) -> (R, PnmHeader) { |
305 | 0 | (self.reader, self.header) |
306 | 0 | } |
307 | | |
308 | 655 | fn read_bitmap_header(mut reader: R, encoding: SampleEncoding) -> ImageResult<PnmDecoder<R>> { |
309 | 655 | let header = reader.read_bitmap_header(encoding)?; |
310 | 541 | Ok(PnmDecoder { |
311 | 541 | reader, |
312 | 541 | tuple: TupleType::PbmBit, |
313 | 541 | header: PnmHeader { |
314 | 541 | decoded: HeaderRecord::Bitmap(header), |
315 | 541 | encoded: None, |
316 | 541 | }, |
317 | 541 | }) |
318 | 655 | } Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_bitmap_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<_>>::read_bitmap_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_bitmap_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_bitmap_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_bitmap_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_bitmap_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_bitmap_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_bitmap_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_bitmap_header <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_bitmap_header Line | Count | Source | 308 | 646 | fn read_bitmap_header(mut reader: R, encoding: SampleEncoding) -> ImageResult<PnmDecoder<R>> { | 309 | 646 | let header = reader.read_bitmap_header(encoding)?; | 310 | 535 | Ok(PnmDecoder { | 311 | 535 | reader, | 312 | 535 | tuple: TupleType::PbmBit, | 313 | 535 | header: PnmHeader { | 314 | 535 | decoded: HeaderRecord::Bitmap(header), | 315 | 535 | encoded: None, | 316 | 535 | }, | 317 | 535 | }) | 318 | 646 | } |
Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_bitmap_header <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_bitmap_header Line | Count | Source | 308 | 9 | fn read_bitmap_header(mut reader: R, encoding: SampleEncoding) -> ImageResult<PnmDecoder<R>> { | 309 | 9 | let header = reader.read_bitmap_header(encoding)?; | 310 | 6 | Ok(PnmDecoder { | 311 | 6 | reader, | 312 | 6 | tuple: TupleType::PbmBit, | 313 | 6 | header: PnmHeader { | 314 | 6 | decoded: HeaderRecord::Bitmap(header), | 315 | 6 | encoded: None, | 316 | 6 | }, | 317 | 6 | }) | 318 | 9 | } |
|
319 | | |
320 | 410 | fn read_graymap_header(mut reader: R, encoding: SampleEncoding) -> ImageResult<PnmDecoder<R>> { |
321 | 410 | let header = reader.read_graymap_header(encoding)?; |
322 | 349 | let tuple_type = header.tuple_type()?; |
323 | 292 | Ok(PnmDecoder { |
324 | 292 | reader, |
325 | 292 | tuple: tuple_type, |
326 | 292 | header: PnmHeader { |
327 | 292 | decoded: HeaderRecord::Graymap(header), |
328 | 292 | encoded: None, |
329 | 292 | }, |
330 | 292 | }) |
331 | 410 | } Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_graymap_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<_>>::read_graymap_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_graymap_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_graymap_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_graymap_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_graymap_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_graymap_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_graymap_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_graymap_header <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_graymap_header Line | Count | Source | 320 | 388 | fn read_graymap_header(mut reader: R, encoding: SampleEncoding) -> ImageResult<PnmDecoder<R>> { | 321 | 388 | let header = reader.read_graymap_header(encoding)?; | 322 | 327 | let tuple_type = header.tuple_type()?; | 323 | 271 | Ok(PnmDecoder { | 324 | 271 | reader, | 325 | 271 | tuple: tuple_type, | 326 | 271 | header: PnmHeader { | 327 | 271 | decoded: HeaderRecord::Graymap(header), | 328 | 271 | encoded: None, | 329 | 271 | }, | 330 | 271 | }) | 331 | 388 | } |
Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_graymap_header <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_graymap_header Line | Count | Source | 320 | 22 | fn read_graymap_header(mut reader: R, encoding: SampleEncoding) -> ImageResult<PnmDecoder<R>> { | 321 | 22 | let header = reader.read_graymap_header(encoding)?; | 322 | 22 | let tuple_type = header.tuple_type()?; | 323 | 21 | Ok(PnmDecoder { | 324 | 21 | reader, | 325 | 21 | tuple: tuple_type, | 326 | 21 | header: PnmHeader { | 327 | 21 | decoded: HeaderRecord::Graymap(header), | 328 | 21 | encoded: None, | 329 | 21 | }, | 330 | 21 | }) | 331 | 22 | } |
|
332 | | |
333 | 583 | fn read_pixmap_header(mut reader: R, encoding: SampleEncoding) -> ImageResult<PnmDecoder<R>> { |
334 | 583 | let header = reader.read_pixmap_header(encoding)?; |
335 | 482 | let tuple_type = header.tuple_type()?; |
336 | 432 | Ok(PnmDecoder { |
337 | 432 | reader, |
338 | 432 | tuple: tuple_type, |
339 | 432 | header: PnmHeader { |
340 | 432 | decoded: HeaderRecord::Pixmap(header), |
341 | 432 | encoded: None, |
342 | 432 | }, |
343 | 432 | }) |
344 | 583 | } Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_pixmap_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<_>>::read_pixmap_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_pixmap_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_pixmap_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_pixmap_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_pixmap_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_pixmap_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_pixmap_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_pixmap_header <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_pixmap_header Line | Count | Source | 333 | 557 | fn read_pixmap_header(mut reader: R, encoding: SampleEncoding) -> ImageResult<PnmDecoder<R>> { | 334 | 557 | let header = reader.read_pixmap_header(encoding)?; | 335 | 460 | let tuple_type = header.tuple_type()?; | 336 | 410 | Ok(PnmDecoder { | 337 | 410 | reader, | 338 | 410 | tuple: tuple_type, | 339 | 410 | header: PnmHeader { | 340 | 410 | decoded: HeaderRecord::Pixmap(header), | 341 | 410 | encoded: None, | 342 | 410 | }, | 343 | 410 | }) | 344 | 557 | } |
Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_pixmap_header <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_pixmap_header Line | Count | Source | 333 | 26 | fn read_pixmap_header(mut reader: R, encoding: SampleEncoding) -> ImageResult<PnmDecoder<R>> { | 334 | 26 | let header = reader.read_pixmap_header(encoding)?; | 335 | 22 | let tuple_type = header.tuple_type()?; | 336 | 22 | Ok(PnmDecoder { | 337 | 22 | reader, | 338 | 22 | tuple: tuple_type, | 339 | 22 | header: PnmHeader { | 340 | 22 | decoded: HeaderRecord::Pixmap(header), | 341 | 22 | encoded: None, | 342 | 22 | }, | 343 | 22 | }) | 344 | 26 | } |
|
345 | | |
346 | 1.41k | fn read_arbitrary_header(mut reader: R) -> ImageResult<PnmDecoder<R>> { |
347 | 1.41k | let header = reader.read_arbitrary_header()?; |
348 | 570 | let tuple_type = header.tuple_type()?; |
349 | 209 | Ok(PnmDecoder { |
350 | 209 | reader, |
351 | 209 | tuple: tuple_type, |
352 | 209 | header: PnmHeader { |
353 | 209 | decoded: HeaderRecord::Arbitrary(header), |
354 | 209 | encoded: None, |
355 | 209 | }, |
356 | 209 | }) |
357 | 1.41k | } Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_arbitrary_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<_>>::read_arbitrary_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_arbitrary_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_arbitrary_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_arbitrary_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_arbitrary_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_arbitrary_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_arbitrary_header Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_arbitrary_header <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_arbitrary_header Line | Count | Source | 346 | 1.33k | fn read_arbitrary_header(mut reader: R) -> ImageResult<PnmDecoder<R>> { | 347 | 1.33k | let header = reader.read_arbitrary_header()?; | 348 | 569 | let tuple_type = header.tuple_type()?; | 349 | 208 | Ok(PnmDecoder { | 350 | 208 | reader, | 351 | 208 | tuple: tuple_type, | 352 | 208 | header: PnmHeader { | 353 | 208 | decoded: HeaderRecord::Arbitrary(header), | 354 | 208 | encoded: None, | 355 | 208 | }, | 356 | 208 | }) | 357 | 1.33k | } |
Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_arbitrary_header <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_arbitrary_header Line | Count | Source | 346 | 79 | fn read_arbitrary_header(mut reader: R) -> ImageResult<PnmDecoder<R>> { | 347 | 79 | let header = reader.read_arbitrary_header()?; | 348 | 1 | let tuple_type = header.tuple_type()?; | 349 | 1 | Ok(PnmDecoder { | 350 | 1 | reader, | 351 | 1 | tuple: tuple_type, | 352 | 1 | header: PnmHeader { | 353 | 1 | decoded: HeaderRecord::Arbitrary(header), | 354 | 1 | encoded: None, | 355 | 1 | }, | 356 | 1 | }) | 357 | 79 | } |
|
358 | | } |
359 | | |
360 | | trait HeaderReader: Read { |
361 | | /// Reads the two magic constant bytes |
362 | 3.08k | fn read_magic_constant(&mut self) -> ImageResult<[u8; 2]> { |
363 | 3.08k | let mut magic: [u8; 2] = [0, 0]; |
364 | 3.08k | self.read_exact(&mut magic)?; |
365 | 3.07k | Ok(magic) |
366 | 3.08k | } Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_magic_constant Unexecuted instantiation: <_ as image::codecs::pnm::decoder::HeaderReader>::read_magic_constant Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_magic_constant Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_magic_constant Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_magic_constant Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_magic_constant Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_magic_constant Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_magic_constant Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_magic_constant <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_magic_constant Line | Count | Source | 362 | 2.95k | fn read_magic_constant(&mut self) -> ImageResult<[u8; 2]> { | 363 | 2.95k | let mut magic: [u8; 2] = [0, 0]; | 364 | 2.95k | self.read_exact(&mut magic)?; | 365 | 2.94k | Ok(magic) | 366 | 2.95k | } |
Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_magic_constant <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_magic_constant Line | Count | Source | 362 | 136 | fn read_magic_constant(&mut self) -> ImageResult<[u8; 2]> { | 363 | 136 | let mut magic: [u8; 2] = [0, 0]; | 364 | 136 | self.read_exact(&mut magic)?; | 365 | 136 | Ok(magic) | 366 | 136 | } |
|
367 | | |
368 | | /// Reads a string as well as a single whitespace after it, ignoring comments |
369 | 3.90k | fn read_next_string(&mut self) -> ImageResult<String> { |
370 | 3.90k | let mut bytes = Vec::new(); |
371 | 3.90k | |
372 | 3.90k | // pair input bytes with a bool mask to remove comments |
373 | 3.90k | #[allow(clippy::unbuffered_bytes)] |
374 | 5.27M | let mark_comments = self.bytes().scan(true, |partof, read| { |
375 | 5.27M | let byte = match read { |
376 | 0 | Err(err) => return Some((*partof, Err(err))), |
377 | 5.27M | Ok(byte) => byte, |
378 | | }; |
379 | 5.27M | let cur_enabled = *partof && byte != b'#'; |
380 | 5.27M | let next_enabled = cur_enabled || (byte == b'\r' || byte == b'\n'); |
381 | 5.27M | *partof = next_enabled; |
382 | 5.27M | Some((cur_enabled, Ok(byte))) |
383 | 5.27M | }); Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string::{closure#0} Unexecuted instantiation: <_ as image::codecs::pnm::decoder::HeaderReader>::read_next_string::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string::{closure#0} <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string::{closure#0} Line | Count | Source | 374 | 5.26M | let mark_comments = self.bytes().scan(true, |partof, read| { | 375 | 5.26M | let byte = match read { | 376 | 0 | Err(err) => return Some((*partof, Err(err))), | 377 | 5.26M | Ok(byte) => byte, | 378 | | }; | 379 | 5.26M | let cur_enabled = *partof && byte != b'#'; | 380 | 5.26M | let next_enabled = cur_enabled || (byte == b'\r' || byte == b'\n'); | 381 | 5.26M | *partof = next_enabled; | 382 | 5.26M | Some((cur_enabled, Ok(byte))) | 383 | 5.26M | }); |
Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string::{closure#0} <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string::{closure#0} Line | Count | Source | 374 | 7.79k | let mark_comments = self.bytes().scan(true, |partof, read| { | 375 | 7.79k | let byte = match read { | 376 | 0 | Err(err) => return Some((*partof, Err(err))), | 377 | 7.79k | Ok(byte) => byte, | 378 | | }; | 379 | 7.79k | let cur_enabled = *partof && byte != b'#'; | 380 | 7.79k | let next_enabled = cur_enabled || (byte == b'\r' || byte == b'\n'); | 381 | 7.79k | *partof = next_enabled; | 382 | 7.79k | Some((cur_enabled, Ok(byte))) | 383 | 7.79k | }); |
|
384 | | |
385 | 5.27M | for (_, byte) in mark_comments.filter(|e| e.0) { Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string::{closure#1} Unexecuted instantiation: <_ as image::codecs::pnm::decoder::HeaderReader>::read_next_string::{closure#1} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string::{closure#1} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string::{closure#1} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string::{closure#1} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string::{closure#1} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string::{closure#1} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string::{closure#1} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string::{closure#1} <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string::{closure#1} Line | Count | Source | 385 | 5.26M | for (_, byte) in mark_comments.filter(|e| e.0) { |
Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string::{closure#1} <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string::{closure#1} Line | Count | Source | 385 | 7.79k | for (_, byte) in mark_comments.filter(|e| e.0) { |
|
386 | 5.26M | match byte { |
387 | | Ok(b'\t' | b'\n' | b'\x0b' | b'\x0c' | b'\r' | b' ') => { |
388 | 4.88k | if !bytes.is_empty() { |
389 | 3.05k | break; // We're done as we already have some content |
390 | 1.83k | } |
391 | | } |
392 | 5.26M | Ok(byte) if !byte.is_ascii() => { |
393 | 18 | return Err(DecoderError::NonAsciiByteInHeader(byte).into()) |
394 | | } |
395 | 5.26M | Ok(byte) => { |
396 | 5.26M | bytes.push(byte); |
397 | 5.26M | } |
398 | 0 | Err(_) => break, |
399 | | } |
400 | | } |
401 | | |
402 | 3.88k | if bytes.is_empty() { |
403 | 105 | return Err(ImageError::IoError(io::ErrorKind::UnexpectedEof.into())); |
404 | 3.78k | } |
405 | 3.78k | |
406 | 3.78k | if !bytes.as_slice().is_ascii() { |
407 | | // We have only filled the buffer with characters for which `byte.is_ascii()` holds. |
408 | 0 | unreachable!("Non-ASCII character should have returned sooner") |
409 | 3.78k | } |
410 | 3.78k | |
411 | 3.78k | let string = String::from_utf8(bytes) |
412 | 3.78k | // We checked the precondition ourselves a few lines before, `bytes.as_slice().is_ascii()`. |
413 | 3.78k | .unwrap_or_else(|_| unreachable!("Only ASCII characters should be decoded")); |
414 | 3.78k | |
415 | 3.78k | Ok(string) |
416 | 3.90k | } Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string Unexecuted instantiation: <_ as image::codecs::pnm::decoder::HeaderReader>::read_next_string Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string Line | Count | Source | 369 | 3.75k | fn read_next_string(&mut self) -> ImageResult<String> { | 370 | 3.75k | let mut bytes = Vec::new(); | 371 | 3.75k | | 372 | 3.75k | // pair input bytes with a bool mask to remove comments | 373 | 3.75k | #[allow(clippy::unbuffered_bytes)] | 374 | 3.75k | let mark_comments = self.bytes().scan(true, |partof, read| { | 375 | | let byte = match read { | 376 | | Err(err) => return Some((*partof, Err(err))), | 377 | | Ok(byte) => byte, | 378 | | }; | 379 | | let cur_enabled = *partof && byte != b'#'; | 380 | | let next_enabled = cur_enabled || (byte == b'\r' || byte == b'\n'); | 381 | | *partof = next_enabled; | 382 | | Some((cur_enabled, Ok(byte))) | 383 | 3.75k | }); | 384 | | | 385 | 5.26M | for (_, byte) in mark_comments.filter(|e| e.0) { | 386 | 5.26M | match byte { | 387 | | Ok(b'\t' | b'\n' | b'\x0b' | b'\x0c' | b'\r' | b' ') => { | 388 | 4.49k | if !bytes.is_empty() { | 389 | 2.91k | break; // We're done as we already have some content | 390 | 1.58k | } | 391 | | } | 392 | 5.26M | Ok(byte) if !byte.is_ascii() => { | 393 | 16 | return Err(DecoderError::NonAsciiByteInHeader(byte).into()) | 394 | | } | 395 | 5.26M | Ok(byte) => { | 396 | 5.26M | bytes.push(byte); | 397 | 5.26M | } | 398 | 0 | Err(_) => break, | 399 | | } | 400 | | } | 401 | | | 402 | 3.73k | if bytes.is_empty() { | 403 | 105 | return Err(ImageError::IoError(io::ErrorKind::UnexpectedEof.into())); | 404 | 3.62k | } | 405 | 3.62k | | 406 | 3.62k | if !bytes.as_slice().is_ascii() { | 407 | | // We have only filled the buffer with characters for which `byte.is_ascii()` holds. | 408 | 0 | unreachable!("Non-ASCII character should have returned sooner") | 409 | 3.62k | } | 410 | 3.62k | | 411 | 3.62k | let string = String::from_utf8(bytes) | 412 | 3.62k | // We checked the precondition ourselves a few lines before, `bytes.as_slice().is_ascii()`. | 413 | 3.62k | .unwrap_or_else(|_| unreachable!("Only ASCII characters should be decoded")); | 414 | 3.62k | | 415 | 3.62k | Ok(string) | 416 | 3.75k | } |
Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_string Line | Count | Source | 369 | 154 | fn read_next_string(&mut self) -> ImageResult<String> { | 370 | 154 | let mut bytes = Vec::new(); | 371 | 154 | | 372 | 154 | // pair input bytes with a bool mask to remove comments | 373 | 154 | #[allow(clippy::unbuffered_bytes)] | 374 | 154 | let mark_comments = self.bytes().scan(true, |partof, read| { | 375 | | let byte = match read { | 376 | | Err(err) => return Some((*partof, Err(err))), | 377 | | Ok(byte) => byte, | 378 | | }; | 379 | | let cur_enabled = *partof && byte != b'#'; | 380 | | let next_enabled = cur_enabled || (byte == b'\r' || byte == b'\n'); | 381 | | *partof = next_enabled; | 382 | | Some((cur_enabled, Ok(byte))) | 383 | 154 | }); | 384 | | | 385 | 2.80k | for (_, byte) in mark_comments.filter(|e| e.0) { | 386 | 2.41k | match byte { | 387 | | Ok(b'\t' | b'\n' | b'\x0b' | b'\x0c' | b'\r' | b' ') => { | 388 | 393 | if !bytes.is_empty() { | 389 | 147 | break; // We're done as we already have some content | 390 | 246 | } | 391 | | } | 392 | 2.41k | Ok(byte) if !byte.is_ascii() => { | 393 | 2 | return Err(DecoderError::NonAsciiByteInHeader(byte).into()) | 394 | | } | 395 | 2.40k | Ok(byte) => { | 396 | 2.40k | bytes.push(byte); | 397 | 2.40k | } | 398 | 0 | Err(_) => break, | 399 | | } | 400 | | } | 401 | | | 402 | 152 | if bytes.is_empty() { | 403 | 0 | return Err(ImageError::IoError(io::ErrorKind::UnexpectedEof.into())); | 404 | 152 | } | 405 | 152 | | 406 | 152 | if !bytes.as_slice().is_ascii() { | 407 | | // We have only filled the buffer with characters for which `byte.is_ascii()` holds. | 408 | 0 | unreachable!("Non-ASCII character should have returned sooner") | 409 | 152 | } | 410 | 152 | | 411 | 152 | let string = String::from_utf8(bytes) | 412 | 152 | // We checked the precondition ourselves a few lines before, `bytes.as_slice().is_ascii()`. | 413 | 152 | .unwrap_or_else(|_| unreachable!("Only ASCII characters should be decoded")); | 414 | 152 | | 415 | 152 | Ok(string) | 416 | 154 | } |
|
417 | | |
418 | 25.4k | fn read_next_line(&mut self) -> ImageResult<String> { |
419 | 25.4k | let mut buffer = Vec::new(); |
420 | | loop { |
421 | 25.1M | let mut byte = [0]; |
422 | 25.1M | if self.read(&mut byte)? == 0 || byte[0] == b'\n' { |
423 | 25.4k | break; |
424 | 25.1M | } |
425 | 25.1M | buffer.push(byte[0]); |
426 | | } |
427 | | |
428 | 25.4k | String::from_utf8(buffer) |
429 | 25.4k | .map_err(|e| ImageError::Decoding(DecodingError::new(ImageFormat::Pnm.into(), e))) Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_line::{closure#0} Unexecuted instantiation: <_ as image::codecs::pnm::decoder::HeaderReader>::read_next_line::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_line::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_line::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_line::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_line::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_line::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_line::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_line::{closure#0} <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_line::{closure#0} Line | Count | Source | 429 | 13 | .map_err(|e| ImageError::Decoding(DecodingError::new(ImageFormat::Pnm.into(), e))) |
Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_line::{closure#0} <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_line::{closure#0} Line | Count | Source | 429 | 16 | .map_err(|e| ImageError::Decoding(DecodingError::new(ImageFormat::Pnm.into(), e))) |
|
430 | 25.4k | } Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_line Unexecuted instantiation: <_ as image::codecs::pnm::decoder::HeaderReader>::read_next_line Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_line Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_line Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_line Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_line Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_line Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_line Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_line <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_line Line | Count | Source | 418 | 10.7k | fn read_next_line(&mut self) -> ImageResult<String> { | 419 | 10.7k | let mut buffer = Vec::new(); | 420 | | loop { | 421 | 24.4M | let mut byte = [0]; | 422 | 24.4M | if self.read(&mut byte)? == 0 || byte[0] == b'\n' { | 423 | 10.7k | break; | 424 | 24.3M | } | 425 | 24.3M | buffer.push(byte[0]); | 426 | | } | 427 | | | 428 | 10.7k | String::from_utf8(buffer) | 429 | 10.7k | .map_err(|e| ImageError::Decoding(DecodingError::new(ImageFormat::Pnm.into(), e))) | 430 | 10.7k | } |
Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_line <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_line Line | Count | Source | 418 | 14.7k | fn read_next_line(&mut self) -> ImageResult<String> { | 419 | 14.7k | let mut buffer = Vec::new(); | 420 | | loop { | 421 | 769k | let mut byte = [0]; | 422 | 769k | if self.read(&mut byte)? == 0 || byte[0] == b'\n' { | 423 | 14.7k | break; | 424 | 755k | } | 425 | 755k | buffer.push(byte[0]); | 426 | | } | 427 | | | 428 | 14.7k | String::from_utf8(buffer) | 429 | 14.7k | .map_err(|e| ImageError::Decoding(DecodingError::new(ImageFormat::Pnm.into(), e))) | 430 | 14.7k | } |
|
431 | | |
432 | 3.90k | fn read_next_u32(&mut self) -> ImageResult<u32> { |
433 | 3.90k | let s = self.read_next_string()?; |
434 | 3.78k | s.parse::<u32>() |
435 | 3.78k | .map_err(|err| DecoderError::UnparsableValue(ErrorDataSource::Preamble, s, err).into()) Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_u32::{closure#0} Unexecuted instantiation: <_ as image::codecs::pnm::decoder::HeaderReader>::read_next_u32::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_u32::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_u32::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_u32::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_u32::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_u32::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_u32::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_u32::{closure#0} <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_u32::{closure#0} Line | Count | Source | 435 | 148 | .map_err(|err| DecoderError::UnparsableValue(ErrorDataSource::Preamble, s, err).into()) |
Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_u32::{closure#0} <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_u32::{closure#0} Line | Count | Source | 435 | 5 | .map_err(|err| DecoderError::UnparsableValue(ErrorDataSource::Preamble, s, err).into()) |
|
436 | 3.90k | } Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_u32 Unexecuted instantiation: <_ as image::codecs::pnm::decoder::HeaderReader>::read_next_u32 Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_u32 Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_u32 Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_u32 Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_u32 Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_u32 Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_u32 Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_u32 <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_u32 Line | Count | Source | 432 | 3.75k | fn read_next_u32(&mut self) -> ImageResult<u32> { | 433 | 3.75k | let s = self.read_next_string()?; | 434 | 3.62k | s.parse::<u32>() | 435 | 3.62k | .map_err(|err| DecoderError::UnparsableValue(ErrorDataSource::Preamble, s, err).into()) | 436 | 3.75k | } |
Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_u32 <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_next_u32 Line | Count | Source | 432 | 154 | fn read_next_u32(&mut self) -> ImageResult<u32> { | 433 | 154 | let s = self.read_next_string()?; | 434 | 152 | s.parse::<u32>() | 435 | 152 | .map_err(|err| DecoderError::UnparsableValue(ErrorDataSource::Preamble, s, err).into()) | 436 | 154 | } |
|
437 | | |
438 | 655 | fn read_bitmap_header(&mut self, encoding: SampleEncoding) -> ImageResult<BitmapHeader> { |
439 | 655 | let width = self.read_next_u32()?; |
440 | 552 | let height = self.read_next_u32()?; |
441 | 541 | Ok(BitmapHeader { |
442 | 541 | encoding, |
443 | 541 | height, |
444 | 541 | width, |
445 | 541 | }) |
446 | 655 | } Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_bitmap_header Unexecuted instantiation: <_ as image::codecs::pnm::decoder::HeaderReader>::read_bitmap_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_bitmap_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_bitmap_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_bitmap_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_bitmap_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_bitmap_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_bitmap_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_bitmap_header <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_bitmap_header Line | Count | Source | 438 | 646 | fn read_bitmap_header(&mut self, encoding: SampleEncoding) -> ImageResult<BitmapHeader> { | 439 | 646 | let width = self.read_next_u32()?; | 440 | 545 | let height = self.read_next_u32()?; | 441 | 535 | Ok(BitmapHeader { | 442 | 535 | encoding, | 443 | 535 | height, | 444 | 535 | width, | 445 | 535 | }) | 446 | 646 | } |
Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_bitmap_header <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_bitmap_header Line | Count | Source | 438 | 9 | fn read_bitmap_header(&mut self, encoding: SampleEncoding) -> ImageResult<BitmapHeader> { | 439 | 9 | let width = self.read_next_u32()?; | 440 | 7 | let height = self.read_next_u32()?; | 441 | 6 | Ok(BitmapHeader { | 442 | 6 | encoding, | 443 | 6 | height, | 444 | 6 | width, | 445 | 6 | }) | 446 | 9 | } |
|
447 | | |
448 | 410 | fn read_graymap_header(&mut self, encoding: SampleEncoding) -> ImageResult<GraymapHeader> { |
449 | 410 | self.read_pixmap_header(encoding).map( |
450 | 410 | |PixmapHeader { |
451 | | encoding, |
452 | | width, |
453 | | height, |
454 | | maxval, |
455 | 349 | }| GraymapHeader { |
456 | 349 | encoding, |
457 | 349 | width, |
458 | 349 | height, |
459 | 349 | maxwhite: maxval, |
460 | 410 | }, Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_graymap_header::{closure#0} Unexecuted instantiation: <_ as image::codecs::pnm::decoder::HeaderReader>::read_graymap_header::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_graymap_header::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_graymap_header::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_graymap_header::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_graymap_header::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_graymap_header::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_graymap_header::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_graymap_header::{closure#0} <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_graymap_header::{closure#0} Line | Count | Source | 455 | 327 | }| GraymapHeader { | 456 | 327 | encoding, | 457 | 327 | width, | 458 | 327 | height, | 459 | 327 | maxwhite: maxval, | 460 | 327 | }, |
Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_graymap_header::{closure#0} <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_graymap_header::{closure#0} Line | Count | Source | 455 | 22 | }| GraymapHeader { | 456 | 22 | encoding, | 457 | 22 | width, | 458 | 22 | height, | 459 | 22 | maxwhite: maxval, | 460 | 22 | }, |
|
461 | 410 | ) |
462 | 410 | } Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_graymap_header Unexecuted instantiation: <_ as image::codecs::pnm::decoder::HeaderReader>::read_graymap_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_graymap_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_graymap_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_graymap_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_graymap_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_graymap_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_graymap_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_graymap_header <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_graymap_header Line | Count | Source | 448 | 388 | fn read_graymap_header(&mut self, encoding: SampleEncoding) -> ImageResult<GraymapHeader> { | 449 | 388 | self.read_pixmap_header(encoding).map( | 450 | 388 | |PixmapHeader { | 451 | | encoding, | 452 | | width, | 453 | | height, | 454 | | maxval, | 455 | | }| GraymapHeader { | 456 | | encoding, | 457 | | width, | 458 | | height, | 459 | | maxwhite: maxval, | 460 | 388 | }, | 461 | 388 | ) | 462 | 388 | } |
Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_graymap_header <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_graymap_header Line | Count | Source | 448 | 22 | fn read_graymap_header(&mut self, encoding: SampleEncoding) -> ImageResult<GraymapHeader> { | 449 | 22 | self.read_pixmap_header(encoding).map( | 450 | 22 | |PixmapHeader { | 451 | | encoding, | 452 | | width, | 453 | | height, | 454 | | maxval, | 455 | | }| GraymapHeader { | 456 | | encoding, | 457 | | width, | 458 | | height, | 459 | | maxwhite: maxval, | 460 | 22 | }, | 461 | 22 | ) | 462 | 22 | } |
|
463 | | |
464 | 993 | fn read_pixmap_header(&mut self, encoding: SampleEncoding) -> ImageResult<PixmapHeader> { |
465 | 993 | let width = self.read_next_u32()?; |
466 | 859 | let height = self.read_next_u32()?; |
467 | 845 | let maxval = self.read_next_u32()?; |
468 | 831 | Ok(PixmapHeader { |
469 | 831 | encoding, |
470 | 831 | height, |
471 | 831 | width, |
472 | 831 | maxval, |
473 | 831 | }) |
474 | 993 | } Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_pixmap_header Unexecuted instantiation: <_ as image::codecs::pnm::decoder::HeaderReader>::read_pixmap_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_pixmap_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_pixmap_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_pixmap_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_pixmap_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_pixmap_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_pixmap_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_pixmap_header <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_pixmap_header Line | Count | Source | 464 | 945 | fn read_pixmap_header(&mut self, encoding: SampleEncoding) -> ImageResult<PixmapHeader> { | 465 | 945 | let width = self.read_next_u32()?; | 466 | 814 | let height = self.read_next_u32()?; | 467 | 800 | let maxval = self.read_next_u32()?; | 468 | 787 | Ok(PixmapHeader { | 469 | 787 | encoding, | 470 | 787 | height, | 471 | 787 | width, | 472 | 787 | maxval, | 473 | 787 | }) | 474 | 945 | } |
Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_pixmap_header <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_pixmap_header Line | Count | Source | 464 | 48 | fn read_pixmap_header(&mut self, encoding: SampleEncoding) -> ImageResult<PixmapHeader> { | 465 | 48 | let width = self.read_next_u32()?; | 466 | 45 | let height = self.read_next_u32()?; | 467 | 45 | let maxval = self.read_next_u32()?; | 468 | 44 | Ok(PixmapHeader { | 469 | 44 | encoding, | 470 | 44 | height, | 471 | 44 | width, | 472 | 44 | maxval, | 473 | 44 | }) | 474 | 48 | } |
|
475 | | |
476 | 1.41k | fn read_arbitrary_header(&mut self) -> ImageResult<ArbitraryHeader> { |
477 | 2.53k | fn parse_single_value_line( |
478 | 2.53k | line_val: &mut Option<u32>, |
479 | 2.53k | rest: &str, |
480 | 2.53k | line: PnmHeaderLine, |
481 | 2.53k | ) -> ImageResult<()> { |
482 | 2.53k | if line_val.is_some() { |
483 | 10 | Err(DecoderError::HeaderLineDuplicated(line).into()) |
484 | | } else { |
485 | 2.52k | let v = rest.trim().parse().map_err(|err| { |
486 | 107 | DecoderError::UnparsableValue(ErrorDataSource::Line(line), rest.to_owned(), err) |
487 | 2.52k | })?; |
488 | 2.42k | *line_val = Some(v); |
489 | 2.42k | Ok(()) |
490 | | } |
491 | 2.53k | } |
492 | | |
493 | | #[allow(clippy::unbuffered_bytes)] |
494 | 1.41k | match self.bytes().next() { |
495 | 1 | None => return Err(ImageError::IoError(io::ErrorKind::UnexpectedEof.into())), |
496 | 0 | Some(Err(io)) => return Err(ImageError::IoError(io)), |
497 | 1.40k | Some(Ok(b'\n')) => (), |
498 | 10 | Some(Ok(c)) => return Err(DecoderError::NotNewlineAfterP7Magic(c).into()), |
499 | | } |
500 | | |
501 | | let mut line; |
502 | 1.40k | let mut height: Option<u32> = None; |
503 | 1.40k | let mut width: Option<u32> = None; |
504 | 1.40k | let mut depth: Option<u32> = None; |
505 | 1.40k | let mut maxval: Option<u32> = None; |
506 | 1.40k | let mut tupltype: Option<String> = None; |
507 | | loop { |
508 | 25.4k | line = self.read_next_line()?; |
509 | 25.4k | if line.is_empty() { |
510 | 360 | return Err(DecoderError::UnexpectedPnmHeaderEnd.into()); |
511 | 25.0k | } |
512 | 25.0k | if line.as_bytes()[0] == b'#' { |
513 | 970 | continue; |
514 | 24.1k | } |
515 | 24.1k | if !line.is_ascii() { |
516 | 12 | return Err(DecoderError::NonAsciiLineInPamHeader.into()); |
517 | 24.1k | } |
518 | 24.1k | #[allow(deprecated)] |
519 | 24.1k | let (identifier, rest) = line |
520 | 24.1k | .trim_left() |
521 | 24.1k | .split_at(line.find(char::is_whitespace).unwrap_or(line.len())); |
522 | 24.1k | match identifier { |
523 | 24.1k | "ENDHDR" => break, |
524 | 23.5k | "HEIGHT" => parse_single_value_line(&mut height, rest, PnmHeaderLine::Height)?, |
525 | 22.9k | "WIDTH" => parse_single_value_line(&mut width, rest, PnmHeaderLine::Width)?, |
526 | 22.2k | "DEPTH" => parse_single_value_line(&mut depth, rest, PnmHeaderLine::Depth)?, |
527 | 21.5k | "MAXVAL" => parse_single_value_line(&mut maxval, rest, PnmHeaderLine::Maxval)?, |
528 | 20.9k | "TUPLTYPE" => { |
529 | 20.6k | let identifier = rest.trim(); |
530 | 20.6k | if tupltype.is_some() { |
531 | 19.7k | let appended = tupltype.take().map(|mut v| { |
532 | 19.7k | v.push(' '); |
533 | 19.7k | v.push_str(identifier); |
534 | 19.7k | v |
535 | 19.7k | }); Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_arbitrary_header::{closure#0} Unexecuted instantiation: <_ as image::codecs::pnm::decoder::HeaderReader>::read_arbitrary_header::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_arbitrary_header::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_arbitrary_header::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_arbitrary_header::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_arbitrary_header::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_arbitrary_header::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_arbitrary_header::{closure#0} Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_arbitrary_header::{closure#0} <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_arbitrary_header::{closure#0} Line | Count | Source | 531 | 5.55k | let appended = tupltype.take().map(|mut v| { | 532 | 5.55k | v.push(' '); | 533 | 5.55k | v.push_str(identifier); | 534 | 5.55k | v | 535 | 5.55k | }); |
Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_arbitrary_header::{closure#0} <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_arbitrary_header::{closure#0} Line | Count | Source | 531 | 14.1k | let appended = tupltype.take().map(|mut v| { | 532 | 14.1k | v.push(' '); | 533 | 14.1k | v.push_str(identifier); | 534 | 14.1k | v | 535 | 14.1k | }); |
|
536 | 19.7k | tupltype = appended; |
537 | 19.7k | } else { |
538 | 945 | tupltype = Some(identifier.to_string()); |
539 | 945 | } |
540 | | } |
541 | 307 | _ => return Err(DecoderError::HeaderLineUnknown(identifier.to_string()).into()), |
542 | | } |
543 | | } |
544 | | |
545 | 577 | let (Some(h), Some(w), Some(d), Some(m)) = (height, width, depth, maxval) else { |
546 | 7 | return Err(DecoderError::HeaderLineMissing { |
547 | 7 | height, |
548 | 7 | width, |
549 | 7 | depth, |
550 | 7 | maxval, |
551 | 7 | } |
552 | 7 | .into()); |
553 | | }; |
554 | | |
555 | 570 | let tupltype = match tupltype { |
556 | 71 | None => None, |
557 | 499 | Some(ref t) if t == "BLACKANDWHITE" => Some(ArbitraryTuplType::BlackAndWhite), |
558 | 351 | Some(ref t) if t == "BLACKANDWHITE_ALPHA" => { |
559 | 1 | Some(ArbitraryTuplType::BlackAndWhiteAlpha) |
560 | | } |
561 | 350 | Some(ref t) if t == "GRAYSCALE" => Some(ArbitraryTuplType::Grayscale), |
562 | 269 | Some(ref t) if t == "GRAYSCALE_ALPHA" => Some(ArbitraryTuplType::GrayscaleAlpha), |
563 | 267 | Some(ref t) if t == "RGB" => Some(ArbitraryTuplType::RGB), |
564 | 124 | Some(ref t) if t == "RGB_ALPHA" => Some(ArbitraryTuplType::RGBAlpha), |
565 | 123 | Some(other) => Some(ArbitraryTuplType::Custom(other)), |
566 | | }; |
567 | | |
568 | 570 | Ok(ArbitraryHeader { |
569 | 570 | height: h, |
570 | 570 | width: w, |
571 | 570 | depth: d, |
572 | 570 | maxval: m, |
573 | 570 | tupltype, |
574 | 570 | }) |
575 | 1.41k | } Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_arbitrary_header Unexecuted instantiation: <_ as image::codecs::pnm::decoder::HeaderReader>::read_arbitrary_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_arbitrary_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_arbitrary_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_arbitrary_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_arbitrary_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_arbitrary_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_arbitrary_header Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_arbitrary_header <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_arbitrary_header Line | Count | Source | 476 | 1.33k | fn read_arbitrary_header(&mut self) -> ImageResult<ArbitraryHeader> { | 477 | | fn parse_single_value_line( | 478 | | line_val: &mut Option<u32>, | 479 | | rest: &str, | 480 | | line: PnmHeaderLine, | 481 | | ) -> ImageResult<()> { | 482 | | if line_val.is_some() { | 483 | | Err(DecoderError::HeaderLineDuplicated(line).into()) | 484 | | } else { | 485 | | let v = rest.trim().parse().map_err(|err| { | 486 | | DecoderError::UnparsableValue(ErrorDataSource::Line(line), rest.to_owned(), err) | 487 | | })?; | 488 | | *line_val = Some(v); | 489 | | Ok(()) | 490 | | } | 491 | | } | 492 | | | 493 | | #[allow(clippy::unbuffered_bytes)] | 494 | 1.33k | match self.bytes().next() { | 495 | 1 | None => return Err(ImageError::IoError(io::ErrorKind::UnexpectedEof.into())), | 496 | 0 | Some(Err(io)) => return Err(ImageError::IoError(io)), | 497 | 1.32k | Some(Ok(b'\n')) => (), | 498 | 7 | Some(Ok(c)) => return Err(DecoderError::NotNewlineAfterP7Magic(c).into()), | 499 | | } | 500 | | | 501 | | let mut line; | 502 | 1.32k | let mut height: Option<u32> = None; | 503 | 1.32k | let mut width: Option<u32> = None; | 504 | 1.32k | let mut depth: Option<u32> = None; | 505 | 1.32k | let mut maxval: Option<u32> = None; | 506 | 1.32k | let mut tupltype: Option<String> = None; | 507 | | loop { | 508 | 10.7k | line = self.read_next_line()?; | 509 | 10.7k | if line.is_empty() { | 510 | 339 | return Err(DecoderError::UnexpectedPnmHeaderEnd.into()); | 511 | 10.4k | } | 512 | 10.4k | if line.as_bytes()[0] == b'#' { | 513 | 591 | continue; | 514 | 9.82k | } | 515 | 9.82k | if !line.is_ascii() { | 516 | 11 | return Err(DecoderError::NonAsciiLineInPamHeader.into()); | 517 | 9.81k | } | 518 | 9.81k | #[allow(deprecated)] | 519 | 9.81k | let (identifier, rest) = line | 520 | 9.81k | .trim_left() | 521 | 9.81k | .split_at(line.find(char::is_whitespace).unwrap_or(line.len())); | 522 | 9.81k | match identifier { | 523 | 9.81k | "ENDHDR" => break, | 524 | 9.23k | "HEIGHT" => parse_single_value_line(&mut height, rest, PnmHeaderLine::Height)?, | 525 | 8.63k | "WIDTH" => parse_single_value_line(&mut width, rest, PnmHeaderLine::Width)?, | 526 | 7.93k | "DEPTH" => parse_single_value_line(&mut depth, rest, PnmHeaderLine::Depth)?, | 527 | 7.29k | "MAXVAL" => parse_single_value_line(&mut maxval, rest, PnmHeaderLine::Maxval)?, | 528 | 6.70k | "TUPLTYPE" => { | 529 | 6.43k | let identifier = rest.trim(); | 530 | 6.43k | if tupltype.is_some() { | 531 | 5.55k | let appended = tupltype.take().map(|mut v| { | 532 | | v.push(' '); | 533 | | v.push_str(identifier); | 534 | | v | 535 | 5.55k | }); | 536 | 5.55k | tupltype = appended; | 537 | 5.55k | } else { | 538 | 879 | tupltype = Some(identifier.to_string()); | 539 | 879 | } | 540 | | } | 541 | 272 | _ => return Err(DecoderError::HeaderLineUnknown(identifier.to_string()).into()), | 542 | | } | 543 | | } | 544 | | | 545 | 576 | let (Some(h), Some(w), Some(d), Some(m)) = (height, width, depth, maxval) else { | 546 | 7 | return Err(DecoderError::HeaderLineMissing { | 547 | 7 | height, | 548 | 7 | width, | 549 | 7 | depth, | 550 | 7 | maxval, | 551 | 7 | } | 552 | 7 | .into()); | 553 | | }; | 554 | | | 555 | 569 | let tupltype = match tupltype { | 556 | 71 | None => None, | 557 | 498 | Some(ref t) if t == "BLACKANDWHITE" => Some(ArbitraryTuplType::BlackAndWhite), | 558 | 351 | Some(ref t) if t == "BLACKANDWHITE_ALPHA" => { | 559 | 1 | Some(ArbitraryTuplType::BlackAndWhiteAlpha) | 560 | | } | 561 | 350 | Some(ref t) if t == "GRAYSCALE" => Some(ArbitraryTuplType::Grayscale), | 562 | 269 | Some(ref t) if t == "GRAYSCALE_ALPHA" => Some(ArbitraryTuplType::GrayscaleAlpha), | 563 | 267 | Some(ref t) if t == "RGB" => Some(ArbitraryTuplType::RGB), | 564 | 124 | Some(ref t) if t == "RGB_ALPHA" => Some(ArbitraryTuplType::RGBAlpha), | 565 | 123 | Some(other) => Some(ArbitraryTuplType::Custom(other)), | 566 | | }; | 567 | | | 568 | 569 | Ok(ArbitraryHeader { | 569 | 569 | height: h, | 570 | 569 | width: w, | 571 | 569 | depth: d, | 572 | 569 | maxval: m, | 573 | 569 | tupltype, | 574 | 569 | }) | 575 | 1.33k | } |
Unexecuted instantiation: <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_arbitrary_header <std::io::cursor::Cursor<&[u8]> as image::codecs::pnm::decoder::HeaderReader>::read_arbitrary_header Line | Count | Source | 476 | 79 | fn read_arbitrary_header(&mut self) -> ImageResult<ArbitraryHeader> { | 477 | | fn parse_single_value_line( | 478 | | line_val: &mut Option<u32>, | 479 | | rest: &str, | 480 | | line: PnmHeaderLine, | 481 | | ) -> ImageResult<()> { | 482 | | if line_val.is_some() { | 483 | | Err(DecoderError::HeaderLineDuplicated(line).into()) | 484 | | } else { | 485 | | let v = rest.trim().parse().map_err(|err| { | 486 | | DecoderError::UnparsableValue(ErrorDataSource::Line(line), rest.to_owned(), err) | 487 | | })?; | 488 | | *line_val = Some(v); | 489 | | Ok(()) | 490 | | } | 491 | | } | 492 | | | 493 | | #[allow(clippy::unbuffered_bytes)] | 494 | 79 | match self.bytes().next() { | 495 | 0 | None => return Err(ImageError::IoError(io::ErrorKind::UnexpectedEof.into())), | 496 | 0 | Some(Err(io)) => return Err(ImageError::IoError(io)), | 497 | 76 | Some(Ok(b'\n')) => (), | 498 | 3 | Some(Ok(c)) => return Err(DecoderError::NotNewlineAfterP7Magic(c).into()), | 499 | | } | 500 | | | 501 | | let mut line; | 502 | 76 | let mut height: Option<u32> = None; | 503 | 76 | let mut width: Option<u32> = None; | 504 | 76 | let mut depth: Option<u32> = None; | 505 | 76 | let mut maxval: Option<u32> = None; | 506 | 76 | let mut tupltype: Option<String> = None; | 507 | | loop { | 508 | 14.7k | line = self.read_next_line()?; | 509 | 14.6k | if line.is_empty() { | 510 | 21 | return Err(DecoderError::UnexpectedPnmHeaderEnd.into()); | 511 | 14.6k | } | 512 | 14.6k | if line.as_bytes()[0] == b'#' { | 513 | 379 | continue; | 514 | 14.2k | } | 515 | 14.2k | if !line.is_ascii() { | 516 | 1 | return Err(DecoderError::NonAsciiLineInPamHeader.into()); | 517 | 14.2k | } | 518 | 14.2k | #[allow(deprecated)] | 519 | 14.2k | let (identifier, rest) = line | 520 | 14.2k | .trim_left() | 521 | 14.2k | .split_at(line.find(char::is_whitespace).unwrap_or(line.len())); | 522 | 14.2k | match identifier { | 523 | 14.2k | "ENDHDR" => break, | 524 | 14.2k | "HEIGHT" => parse_single_value_line(&mut height, rest, PnmHeaderLine::Height)?, | 525 | 14.2k | "WIDTH" => parse_single_value_line(&mut width, rest, PnmHeaderLine::Width)?, | 526 | 14.2k | "DEPTH" => parse_single_value_line(&mut depth, rest, PnmHeaderLine::Depth)?, | 527 | 14.2k | "MAXVAL" => parse_single_value_line(&mut maxval, rest, PnmHeaderLine::Maxval)?, | 528 | 14.2k | "TUPLTYPE" => { | 529 | 14.2k | let identifier = rest.trim(); | 530 | 14.2k | if tupltype.is_some() { | 531 | 14.1k | let appended = tupltype.take().map(|mut v| { | 532 | | v.push(' '); | 533 | | v.push_str(identifier); | 534 | | v | 535 | 14.1k | }); | 536 | 14.1k | tupltype = appended; | 537 | 14.1k | } else { | 538 | 66 | tupltype = Some(identifier.to_string()); | 539 | 66 | } | 540 | | } | 541 | 35 | _ => return Err(DecoderError::HeaderLineUnknown(identifier.to_string()).into()), | 542 | | } | 543 | | } | 544 | | | 545 | 1 | let (Some(h), Some(w), Some(d), Some(m)) = (height, width, depth, maxval) else { | 546 | 0 | return Err(DecoderError::HeaderLineMissing { | 547 | 0 | height, | 548 | 0 | width, | 549 | 0 | depth, | 550 | 0 | maxval, | 551 | 0 | } | 552 | 0 | .into()); | 553 | | }; | 554 | | | 555 | 1 | let tupltype = match tupltype { | 556 | 0 | None => None, | 557 | 1 | Some(ref t) if t == "BLACKANDWHITE" => Some(ArbitraryTuplType::BlackAndWhite), | 558 | 0 | Some(ref t) if t == "BLACKANDWHITE_ALPHA" => { | 559 | 0 | Some(ArbitraryTuplType::BlackAndWhiteAlpha) | 560 | | } | 561 | 0 | Some(ref t) if t == "GRAYSCALE" => Some(ArbitraryTuplType::Grayscale), | 562 | 0 | Some(ref t) if t == "GRAYSCALE_ALPHA" => Some(ArbitraryTuplType::GrayscaleAlpha), | 563 | 0 | Some(ref t) if t == "RGB" => Some(ArbitraryTuplType::RGB), | 564 | 0 | Some(ref t) if t == "RGB_ALPHA" => Some(ArbitraryTuplType::RGBAlpha), | 565 | 0 | Some(other) => Some(ArbitraryTuplType::Custom(other)), | 566 | | }; | 567 | | | 568 | 1 | Ok(ArbitraryHeader { | 569 | 1 | height: h, | 570 | 1 | width: w, | 571 | 1 | depth: d, | 572 | 1 | maxval: m, | 573 | 1 | tupltype, | 574 | 1 | }) | 575 | 79 | } |
|
576 | | } |
577 | | |
578 | | impl<R> HeaderReader for R where R: Read {} |
579 | | |
580 | | impl<R: Read> ImageDecoder for PnmDecoder<R> { |
581 | 10.0k | fn dimensions(&self) -> (u32, u32) { |
582 | 10.0k | (self.header.width(), self.header.height()) |
583 | 10.0k | } Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::dimensions Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<_> as image::io::decoder::ImageDecoder>::dimensions Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::dimensions Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::dimensions Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::dimensions Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::dimensions Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::dimensions Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::dimensions Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::dimensions <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::dimensions Line | Count | Source | 581 | 9.66k | fn dimensions(&self) -> (u32, u32) { | 582 | 9.66k | (self.header.width(), self.header.height()) | 583 | 9.66k | } |
Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::dimensions <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::dimensions Line | Count | Source | 581 | 350 | fn dimensions(&self) -> (u32, u32) { | 582 | 350 | (self.header.width(), self.header.height()) | 583 | 350 | } |
|
584 | | |
585 | 7.13k | fn color_type(&self) -> ColorType { |
586 | 7.13k | match self.tuple { |
587 | 2.51k | TupleType::PbmBit => ColorType::L8, |
588 | 312 | TupleType::BWBit => ColorType::L8, |
589 | 891 | TupleType::GrayU8 => ColorType::L8, |
590 | 912 | TupleType::GrayU16 => ColorType::L16, |
591 | 1.23k | TupleType::RGBU8 => ColorType::Rgb8, |
592 | 1.27k | TupleType::RGBU16 => ColorType::Rgb16, |
593 | | } |
594 | 7.13k | } Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::color_type Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<_> as image::io::decoder::ImageDecoder>::color_type Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::color_type Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::color_type Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::color_type Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::color_type Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::color_type Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::color_type Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::color_type <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::color_type Line | Count | Source | 585 | 6.88k | fn color_type(&self) -> ColorType { | 586 | 6.88k | match self.tuple { | 587 | 2.48k | TupleType::PbmBit => ColorType::L8, | 588 | 307 | TupleType::BWBit => ColorType::L8, | 589 | 851 | TupleType::GrayU8 => ColorType::L8, | 590 | 847 | TupleType::GrayU16 => ColorType::L16, | 591 | 1.18k | TupleType::RGBU8 => ColorType::Rgb8, | 592 | 1.21k | TupleType::RGBU16 => ColorType::Rgb16, | 593 | | } | 594 | 6.88k | } |
Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::color_type <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::color_type Line | Count | Source | 585 | 250 | fn color_type(&self) -> ColorType { | 586 | 250 | match self.tuple { | 587 | 30 | TupleType::PbmBit => ColorType::L8, | 588 | 5 | TupleType::BWBit => ColorType::L8, | 589 | 40 | TupleType::GrayU8 => ColorType::L8, | 590 | 65 | TupleType::GrayU16 => ColorType::L16, | 591 | 55 | TupleType::RGBU8 => ColorType::Rgb8, | 592 | 55 | TupleType::RGBU16 => ColorType::Rgb16, | 593 | | } | 594 | 250 | } |
|
595 | | |
596 | 0 | fn original_color_type(&self) -> ExtendedColorType { |
597 | 0 | match self.tuple { |
598 | 0 | TupleType::PbmBit => ExtendedColorType::L1, |
599 | 0 | TupleType::BWBit => ExtendedColorType::L1, |
600 | 0 | TupleType::GrayU8 => ExtendedColorType::L8, |
601 | 0 | TupleType::GrayU16 => ExtendedColorType::L16, |
602 | 0 | TupleType::RGBU8 => ExtendedColorType::Rgb8, |
603 | 0 | TupleType::RGBU16 => ExtendedColorType::Rgb16, |
604 | | } |
605 | 0 | } Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::original_color_type Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<_> as image::io::decoder::ImageDecoder>::original_color_type Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::original_color_type Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::original_color_type Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::original_color_type Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::original_color_type Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::original_color_type Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::original_color_type Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::original_color_type Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::original_color_type Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::original_color_type Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::original_color_type |
606 | | |
607 | 1.39k | fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> { |
608 | 1.39k | assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes())); |
609 | 1.39k | match self.tuple { |
610 | 479 | TupleType::PbmBit => self.read_samples::<PbmBit>(1, buf), |
611 | 62 | TupleType::BWBit => self.read_samples::<BWBit>(1, buf), |
612 | 244 | TupleType::RGBU8 => self.read_samples::<U8>(3, buf), |
613 | 254 | TupleType::RGBU16 => self.read_samples::<U16>(3, buf), |
614 | 177 | TupleType::GrayU8 => self.read_samples::<U8>(1, buf), |
615 | 182 | TupleType::GrayU16 => self.read_samples::<U16>(1, buf), |
616 | | } |
617 | 1.39k | } Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::read_image Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<_> as image::io::decoder::ImageDecoder>::read_image Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::read_image Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::read_image Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::read_image Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::read_image Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::read_image Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::read_image Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::read_image <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::read_image Line | Count | Source | 607 | 1.34k | fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> { | 608 | 1.34k | assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes())); | 609 | 1.34k | match self.tuple { | 610 | 473 | TupleType::PbmBit => self.read_samples::<PbmBit>(1, buf), | 611 | 61 | TupleType::BWBit => self.read_samples::<BWBit>(1, buf), | 612 | 233 | TupleType::RGBU8 => self.read_samples::<U8>(3, buf), | 613 | 243 | TupleType::RGBU16 => self.read_samples::<U16>(3, buf), | 614 | 169 | TupleType::GrayU8 => self.read_samples::<U8>(1, buf), | 615 | 169 | TupleType::GrayU16 => self.read_samples::<U16>(1, buf), | 616 | | } | 617 | 1.34k | } |
Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::read_image <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::read_image Line | Count | Source | 607 | 50 | fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> { | 608 | 50 | assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes())); | 609 | 50 | match self.tuple { | 610 | 6 | TupleType::PbmBit => self.read_samples::<PbmBit>(1, buf), | 611 | 1 | TupleType::BWBit => self.read_samples::<BWBit>(1, buf), | 612 | 11 | TupleType::RGBU8 => self.read_samples::<U8>(3, buf), | 613 | 11 | TupleType::RGBU16 => self.read_samples::<U16>(3, buf), | 614 | 8 | TupleType::GrayU8 => self.read_samples::<U8>(1, buf), | 615 | 13 | TupleType::GrayU16 => self.read_samples::<U16>(1, buf), | 616 | | } | 617 | 50 | } |
|
618 | | |
619 | 1.39k | fn read_image_boxed(self: Box<Self>, buf: &mut [u8]) -> ImageResult<()> { |
620 | 1.39k | (*self).read_image(buf) |
621 | 1.39k | } Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::read_image_boxed Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<_> as image::io::decoder::ImageDecoder>::read_image_boxed Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::read_image_boxed Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::read_image_boxed Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::read_image_boxed Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::read_image_boxed Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::read_image_boxed Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::read_image_boxed Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::read_image_boxed <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::read_image_boxed Line | Count | Source | 619 | 1.34k | fn read_image_boxed(self: Box<Self>, buf: &mut [u8]) -> ImageResult<()> { | 620 | 1.34k | (*self).read_image(buf) | 621 | 1.34k | } |
Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::read_image_boxed <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>> as image::io::decoder::ImageDecoder>::read_image_boxed Line | Count | Source | 619 | 50 | fn read_image_boxed(self: Box<Self>, buf: &mut [u8]) -> ImageResult<()> { | 620 | 50 | (*self).read_image(buf) | 621 | 50 | } |
|
622 | | } |
623 | | |
624 | | impl<R: Read> PnmDecoder<R> { |
625 | 1.39k | fn read_samples<S: Sample>(&mut self, components: u32, buf: &mut [u8]) -> ImageResult<()> { |
626 | 1.39k | match self.subtype().sample_encoding() { |
627 | | SampleEncoding::Binary => { |
628 | 804 | let width = self.header.width(); |
629 | 804 | let height = self.header.height(); |
630 | 804 | let bytecount = S::bytelen(width, height, components)?; |
631 | | |
632 | 804 | let mut bytes = vec![]; |
633 | 804 | self.reader.read_exact_vec(&mut bytes, bytecount)?; |
634 | | |
635 | 507 | let width: usize = width.try_into().map_err(|_| DecoderError::Overflow)?; Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<_>>::read_samples::<_>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit>::{closure#0} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit>::{closure#0} |
636 | 507 | let components: usize = |
637 | 507 | components.try_into().map_err(|_| DecoderError::Overflow)?; Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<_>>::read_samples::<_>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit>::{closure#1} Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit>::{closure#1} |
638 | 507 | let row_size = width |
639 | 507 | .checked_mul(components) |
640 | 507 | .ok_or(DecoderError::Overflow)?; |
641 | | |
642 | 507 | S::from_bytes(&bytes, row_size, buf)?; |
643 | | } |
644 | | SampleEncoding::Ascii => { |
645 | 594 | self.read_ascii::<S>(buf)?; |
646 | | } |
647 | | } |
648 | | |
649 | | // Scale samples if 8bit or 16bit is not saturated |
650 | 576 | let current_sample_max = self.header.maximal_sample(); |
651 | 576 | let target_sample_max = 256_u32.pow(S::sample_size()) - 1; |
652 | 576 | |
653 | 576 | if current_sample_max != target_sample_max { |
654 | 568 | let factor = target_sample_max as f32 / current_sample_max as f32; |
655 | 568 | |
656 | 568 | if S::sample_size() == 1 { |
657 | 22.2M | for v in buf.iter_mut() { |
658 | 22.2M | *v = (f32::from(*v) * factor).round() as u8; |
659 | 22.2M | } |
660 | 174 | } else if S::sample_size() == 2 { |
661 | 936k | for chunk in buf.chunks_exact_mut(2) { |
662 | 936k | let v = NativeEndian::read_u16(chunk); |
663 | 936k | NativeEndian::write_u16(chunk, (f32::from(v) * factor).round() as u16); |
664 | 936k | } |
665 | 0 | } |
666 | 8 | } |
667 | | |
668 | 576 | Ok(()) |
669 | 1.39k | } Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<_>>::read_samples::<_> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit> <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8> Line | Count | Source | 625 | 402 | fn read_samples<S: Sample>(&mut self, components: u32, buf: &mut [u8]) -> ImageResult<()> { | 626 | 402 | match self.subtype().sample_encoding() { | 627 | | SampleEncoding::Binary => { | 628 | 197 | let width = self.header.width(); | 629 | 197 | let height = self.header.height(); | 630 | 197 | let bytecount = S::bytelen(width, height, components)?; | 631 | | | 632 | 197 | let mut bytes = vec![]; | 633 | 197 | self.reader.read_exact_vec(&mut bytes, bytecount)?; | 634 | | | 635 | 141 | let width: usize = width.try_into().map_err(|_| DecoderError::Overflow)?; | 636 | 141 | let components: usize = | 637 | 141 | components.try_into().map_err(|_| DecoderError::Overflow)?; | 638 | 141 | let row_size = width | 639 | 141 | .checked_mul(components) | 640 | 141 | .ok_or(DecoderError::Overflow)?; | 641 | | | 642 | 141 | S::from_bytes(&bytes, row_size, buf)?; | 643 | | } | 644 | | SampleEncoding::Ascii => { | 645 | 205 | self.read_ascii::<S>(buf)?; | 646 | | } | 647 | | } | 648 | | | 649 | | // Scale samples if 8bit or 16bit is not saturated | 650 | 155 | let current_sample_max = self.header.maximal_sample(); | 651 | 155 | let target_sample_max = 256_u32.pow(S::sample_size()) - 1; | 652 | 155 | | 653 | 155 | if current_sample_max != target_sample_max { | 654 | 152 | let factor = target_sample_max as f32 / current_sample_max as f32; | 655 | 152 | | 656 | 152 | if S::sample_size() == 1 { | 657 | 1.62M | for v in buf.iter_mut() { | 658 | 1.62M | *v = (f32::from(*v) * factor).round() as u8; | 659 | 1.62M | } | 660 | 0 | } else if S::sample_size() == 2 { | 661 | 0 | for chunk in buf.chunks_exact_mut(2) { | 662 | 0 | let v = NativeEndian::read_u16(chunk); | 663 | 0 | NativeEndian::write_u16(chunk, (f32::from(v) * factor).round() as u16); | 664 | 0 | } | 665 | 0 | } | 666 | 3 | } | 667 | | | 668 | 155 | Ok(()) | 669 | 402 | } |
<image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16> Line | Count | Source | 625 | 412 | fn read_samples<S: Sample>(&mut self, components: u32, buf: &mut [u8]) -> ImageResult<()> { | 626 | 412 | match self.subtype().sample_encoding() { | 627 | | SampleEncoding::Binary => { | 628 | 174 | let width = self.header.width(); | 629 | 174 | let height = self.header.height(); | 630 | 174 | let bytecount = S::bytelen(width, height, components)?; | 631 | | | 632 | 174 | let mut bytes = vec![]; | 633 | 174 | self.reader.read_exact_vec(&mut bytes, bytecount)?; | 634 | | | 635 | 108 | let width: usize = width.try_into().map_err(|_| DecoderError::Overflow)?; | 636 | 108 | let components: usize = | 637 | 108 | components.try_into().map_err(|_| DecoderError::Overflow)?; | 638 | 108 | let row_size = width | 639 | 108 | .checked_mul(components) | 640 | 108 | .ok_or(DecoderError::Overflow)?; | 641 | | | 642 | 108 | S::from_bytes(&bytes, row_size, buf)?; | 643 | | } | 644 | | SampleEncoding::Ascii => { | 645 | 238 | self.read_ascii::<S>(buf)?; | 646 | | } | 647 | | } | 648 | | | 649 | | // Scale samples if 8bit or 16bit is not saturated | 650 | 164 | let current_sample_max = self.header.maximal_sample(); | 651 | 164 | let target_sample_max = 256_u32.pow(S::sample_size()) - 1; | 652 | 164 | | 653 | 164 | if current_sample_max != target_sample_max { | 654 | 160 | let factor = target_sample_max as f32 / current_sample_max as f32; | 655 | 160 | | 656 | 160 | if S::sample_size() == 1 { | 657 | 0 | for v in buf.iter_mut() { | 658 | 0 | *v = (f32::from(*v) * factor).round() as u8; | 659 | 0 | } | 660 | 160 | } else if S::sample_size() == 2 { | 661 | 929k | for chunk in buf.chunks_exact_mut(2) { | 662 | 929k | let v = NativeEndian::read_u16(chunk); | 663 | 929k | NativeEndian::write_u16(chunk, (f32::from(v) * factor).round() as u16); | 664 | 929k | } | 665 | 0 | } | 666 | 4 | } | 667 | | | 668 | 164 | Ok(()) | 669 | 412 | } |
<image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit> Line | Count | Source | 625 | 61 | fn read_samples<S: Sample>(&mut self, components: u32, buf: &mut [u8]) -> ImageResult<()> { | 626 | 61 | match self.subtype().sample_encoding() { | 627 | | SampleEncoding::Binary => { | 628 | 61 | let width = self.header.width(); | 629 | 61 | let height = self.header.height(); | 630 | 61 | let bytecount = S::bytelen(width, height, components)?; | 631 | | | 632 | 61 | let mut bytes = vec![]; | 633 | 61 | self.reader.read_exact_vec(&mut bytes, bytecount)?; | 634 | | | 635 | 38 | let width: usize = width.try_into().map_err(|_| DecoderError::Overflow)?; | 636 | 38 | let components: usize = | 637 | 38 | components.try_into().map_err(|_| DecoderError::Overflow)?; | 638 | 38 | let row_size = width | 639 | 38 | .checked_mul(components) | 640 | 38 | .ok_or(DecoderError::Overflow)?; | 641 | | | 642 | 38 | S::from_bytes(&bytes, row_size, buf)?; | 643 | | } | 644 | | SampleEncoding::Ascii => { | 645 | 0 | self.read_ascii::<S>(buf)?; | 646 | | } | 647 | | } | 648 | | | 649 | | // Scale samples if 8bit or 16bit is not saturated | 650 | 31 | let current_sample_max = self.header.maximal_sample(); | 651 | 31 | let target_sample_max = 256_u32.pow(S::sample_size()) - 1; | 652 | 31 | | 653 | 31 | if current_sample_max != target_sample_max { | 654 | 31 | let factor = target_sample_max as f32 / current_sample_max as f32; | 655 | 31 | | 656 | 31 | if S::sample_size() == 1 { | 657 | 2.99k | for v in buf.iter_mut() { | 658 | 2.99k | *v = (f32::from(*v) * factor).round() as u8; | 659 | 2.99k | } | 660 | 0 | } else if S::sample_size() == 2 { | 661 | 0 | for chunk in buf.chunks_exact_mut(2) { | 662 | 0 | let v = NativeEndian::read_u16(chunk); | 663 | 0 | NativeEndian::write_u16(chunk, (f32::from(v) * factor).round() as u16); | 664 | 0 | } | 665 | 0 | } | 666 | 0 | } | 667 | | | 668 | 31 | Ok(()) | 669 | 61 | } |
<image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit> Line | Count | Source | 625 | 473 | fn read_samples<S: Sample>(&mut self, components: u32, buf: &mut [u8]) -> ImageResult<()> { | 626 | 473 | match self.subtype().sample_encoding() { | 627 | | SampleEncoding::Binary => { | 628 | 347 | let width = self.header.width(); | 629 | 347 | let height = self.header.height(); | 630 | 347 | let bytecount = S::bytelen(width, height, components)?; | 631 | | | 632 | 347 | let mut bytes = vec![]; | 633 | 347 | self.reader.read_exact_vec(&mut bytes, bytecount)?; | 634 | | | 635 | 197 | let width: usize = width.try_into().map_err(|_| DecoderError::Overflow)?; | 636 | 197 | let components: usize = | 637 | 197 | components.try_into().map_err(|_| DecoderError::Overflow)?; | 638 | 197 | let row_size = width | 639 | 197 | .checked_mul(components) | 640 | 197 | .ok_or(DecoderError::Overflow)?; | 641 | | | 642 | 197 | S::from_bytes(&bytes, row_size, buf)?; | 643 | | } | 644 | | SampleEncoding::Ascii => { | 645 | 126 | self.read_ascii::<S>(buf)?; | 646 | | } | 647 | | } | 648 | | | 649 | | // Scale samples if 8bit or 16bit is not saturated | 650 | 201 | let current_sample_max = self.header.maximal_sample(); | 651 | 201 | let target_sample_max = 256_u32.pow(S::sample_size()) - 1; | 652 | 201 | | 653 | 201 | if current_sample_max != target_sample_max { | 654 | 201 | let factor = target_sample_max as f32 / current_sample_max as f32; | 655 | 201 | | 656 | 201 | if S::sample_size() == 1 { | 657 | 20.2M | for v in buf.iter_mut() { | 658 | 20.2M | *v = (f32::from(*v) * factor).round() as u8; | 659 | 20.2M | } | 660 | 0 | } else if S::sample_size() == 2 { | 661 | 0 | for chunk in buf.chunks_exact_mut(2) { | 662 | 0 | let v = NativeEndian::read_u16(chunk); | 663 | 0 | NativeEndian::write_u16(chunk, (f32::from(v) * factor).round() as u16); | 664 | 0 | } | 665 | 0 | } | 666 | 0 | } | 667 | | | 668 | 201 | Ok(()) | 669 | 473 | } |
Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit> <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U8> Line | Count | Source | 625 | 19 | fn read_samples<S: Sample>(&mut self, components: u32, buf: &mut [u8]) -> ImageResult<()> { | 626 | 19 | match self.subtype().sample_encoding() { | 627 | | SampleEncoding::Binary => { | 628 | 7 | let width = self.header.width(); | 629 | 7 | let height = self.header.height(); | 630 | 7 | let bytecount = S::bytelen(width, height, components)?; | 631 | | | 632 | 7 | let mut bytes = vec![]; | 633 | 7 | self.reader.read_exact_vec(&mut bytes, bytecount)?; | 634 | | | 635 | 6 | let width: usize = width.try_into().map_err(|_| DecoderError::Overflow)?; | 636 | 6 | let components: usize = | 637 | 6 | components.try_into().map_err(|_| DecoderError::Overflow)?; | 638 | 6 | let row_size = width | 639 | 6 | .checked_mul(components) | 640 | 6 | .ok_or(DecoderError::Overflow)?; | 641 | | | 642 | 6 | S::from_bytes(&bytes, row_size, buf)?; | 643 | | } | 644 | | SampleEncoding::Ascii => { | 645 | 12 | self.read_ascii::<S>(buf)?; | 646 | | } | 647 | | } | 648 | | | 649 | | // Scale samples if 8bit or 16bit is not saturated | 650 | 6 | let current_sample_max = self.header.maximal_sample(); | 651 | 6 | let target_sample_max = 256_u32.pow(S::sample_size()) - 1; | 652 | 6 | | 653 | 6 | if current_sample_max != target_sample_max { | 654 | 6 | let factor = target_sample_max as f32 / current_sample_max as f32; | 655 | 6 | | 656 | 6 | if S::sample_size() == 1 { | 657 | 3.83k | for v in buf.iter_mut() { | 658 | 3.83k | *v = (f32::from(*v) * factor).round() as u8; | 659 | 3.83k | } | 660 | 0 | } else if S::sample_size() == 2 { | 661 | 0 | for chunk in buf.chunks_exact_mut(2) { | 662 | 0 | let v = NativeEndian::read_u16(chunk); | 663 | 0 | NativeEndian::write_u16(chunk, (f32::from(v) * factor).round() as u16); | 664 | 0 | } | 665 | 0 | } | 666 | 0 | } | 667 | | | 668 | 6 | Ok(()) | 669 | 19 | } |
<image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::U16> Line | Count | Source | 625 | 24 | fn read_samples<S: Sample>(&mut self, components: u32, buf: &mut [u8]) -> ImageResult<()> { | 626 | 24 | match self.subtype().sample_encoding() { | 627 | | SampleEncoding::Binary => { | 628 | 12 | let width = self.header.width(); | 629 | 12 | let height = self.header.height(); | 630 | 12 | let bytecount = S::bytelen(width, height, components)?; | 631 | | | 632 | 12 | let mut bytes = vec![]; | 633 | 12 | self.reader.read_exact_vec(&mut bytes, bytecount)?; | 634 | | | 635 | 12 | let width: usize = width.try_into().map_err(|_| DecoderError::Overflow)?; | 636 | 12 | let components: usize = | 637 | 12 | components.try_into().map_err(|_| DecoderError::Overflow)?; | 638 | 12 | let row_size = width | 639 | 12 | .checked_mul(components) | 640 | 12 | .ok_or(DecoderError::Overflow)?; | 641 | | | 642 | 12 | S::from_bytes(&bytes, row_size, buf)?; | 643 | | } | 644 | | SampleEncoding::Ascii => { | 645 | 12 | self.read_ascii::<S>(buf)?; | 646 | | } | 647 | | } | 648 | | | 649 | | // Scale samples if 8bit or 16bit is not saturated | 650 | 15 | let current_sample_max = self.header.maximal_sample(); | 651 | 15 | let target_sample_max = 256_u32.pow(S::sample_size()) - 1; | 652 | 15 | | 653 | 15 | if current_sample_max != target_sample_max { | 654 | 14 | let factor = target_sample_max as f32 / current_sample_max as f32; | 655 | 14 | | 656 | 14 | if S::sample_size() == 1 { | 657 | 0 | for v in buf.iter_mut() { | 658 | 0 | *v = (f32::from(*v) * factor).round() as u8; | 659 | 0 | } | 660 | 14 | } else if S::sample_size() == 2 { | 661 | 6.23k | for chunk in buf.chunks_exact_mut(2) { | 662 | 6.23k | let v = NativeEndian::read_u16(chunk); | 663 | 6.23k | NativeEndian::write_u16(chunk, (f32::from(v) * factor).round() as u16); | 664 | 6.23k | } | 665 | 0 | } | 666 | 1 | } | 667 | | | 668 | 15 | Ok(()) | 669 | 24 | } |
<image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::BWBit> Line | Count | Source | 625 | 1 | fn read_samples<S: Sample>(&mut self, components: u32, buf: &mut [u8]) -> ImageResult<()> { | 626 | 1 | match self.subtype().sample_encoding() { | 627 | | SampleEncoding::Binary => { | 628 | 1 | let width = self.header.width(); | 629 | 1 | let height = self.header.height(); | 630 | 1 | let bytecount = S::bytelen(width, height, components)?; | 631 | | | 632 | 1 | let mut bytes = vec![]; | 633 | 1 | self.reader.read_exact_vec(&mut bytes, bytecount)?; | 634 | | | 635 | 1 | let width: usize = width.try_into().map_err(|_| DecoderError::Overflow)?; | 636 | 1 | let components: usize = | 637 | 1 | components.try_into().map_err(|_| DecoderError::Overflow)?; | 638 | 1 | let row_size = width | 639 | 1 | .checked_mul(components) | 640 | 1 | .ok_or(DecoderError::Overflow)?; | 641 | | | 642 | 1 | S::from_bytes(&bytes, row_size, buf)?; | 643 | | } | 644 | | SampleEncoding::Ascii => { | 645 | 0 | self.read_ascii::<S>(buf)?; | 646 | | } | 647 | | } | 648 | | | 649 | | // Scale samples if 8bit or 16bit is not saturated | 650 | 0 | let current_sample_max = self.header.maximal_sample(); | 651 | 0 | let target_sample_max = 256_u32.pow(S::sample_size()) - 1; | 652 | 0 |
| 653 | 0 | if current_sample_max != target_sample_max { | 654 | 0 | let factor = target_sample_max as f32 / current_sample_max as f32; | 655 | 0 |
| 656 | 0 | if S::sample_size() == 1 { | 657 | 0 | for v in buf.iter_mut() { | 658 | 0 | *v = (f32::from(*v) * factor).round() as u8; | 659 | 0 | } | 660 | 0 | } else if S::sample_size() == 2 { | 661 | 0 | for chunk in buf.chunks_exact_mut(2) { | 662 | 0 | let v = NativeEndian::read_u16(chunk); | 663 | 0 | NativeEndian::write_u16(chunk, (f32::from(v) * factor).round() as u16); | 664 | 0 | } | 665 | 0 | } | 666 | 0 | } | 667 | | | 668 | 0 | Ok(()) | 669 | 1 | } |
<image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_samples::<image::codecs::pnm::decoder::PbmBit> Line | Count | Source | 625 | 6 | fn read_samples<S: Sample>(&mut self, components: u32, buf: &mut [u8]) -> ImageResult<()> { | 626 | 6 | match self.subtype().sample_encoding() { | 627 | | SampleEncoding::Binary => { | 628 | 5 | let width = self.header.width(); | 629 | 5 | let height = self.header.height(); | 630 | 5 | let bytecount = S::bytelen(width, height, components)?; | 631 | | | 632 | 5 | let mut bytes = vec![]; | 633 | 5 | self.reader.read_exact_vec(&mut bytes, bytecount)?; | 634 | | | 635 | 4 | let width: usize = width.try_into().map_err(|_| DecoderError::Overflow)?; | 636 | 4 | let components: usize = | 637 | 4 | components.try_into().map_err(|_| DecoderError::Overflow)?; | 638 | 4 | let row_size = width | 639 | 4 | .checked_mul(components) | 640 | 4 | .ok_or(DecoderError::Overflow)?; | 641 | | | 642 | 4 | S::from_bytes(&bytes, row_size, buf)?; | 643 | | } | 644 | | SampleEncoding::Ascii => { | 645 | 1 | self.read_ascii::<S>(buf)?; | 646 | | } | 647 | | } | 648 | | | 649 | | // Scale samples if 8bit or 16bit is not saturated | 650 | 4 | let current_sample_max = self.header.maximal_sample(); | 651 | 4 | let target_sample_max = 256_u32.pow(S::sample_size()) - 1; | 652 | 4 | | 653 | 4 | if current_sample_max != target_sample_max { | 654 | 4 | let factor = target_sample_max as f32 / current_sample_max as f32; | 655 | 4 | | 656 | 4 | if S::sample_size() == 1 { | 657 | 285k | for v in buf.iter_mut() { | 658 | 285k | *v = (f32::from(*v) * factor).round() as u8; | 659 | 285k | } | 660 | 0 | } else if S::sample_size() == 2 { | 661 | 0 | for chunk in buf.chunks_exact_mut(2) { | 662 | 0 | let v = NativeEndian::read_u16(chunk); | 663 | 0 | NativeEndian::write_u16(chunk, (f32::from(v) * factor).round() as u16); | 664 | 0 | } | 665 | 0 | } | 666 | 0 | } | 667 | | | 668 | 4 | Ok(()) | 669 | 6 | } |
|
670 | | |
671 | 594 | fn read_ascii<Basic: Sample>(&mut self, output_buf: &mut [u8]) -> ImageResult<()> { |
672 | 594 | Basic::from_ascii(&mut self.reader, output_buf) |
673 | 594 | } Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::U8> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::U16> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::BWBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::PbmBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<_>>::read_ascii::<_> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::U8> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::U16> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::BWBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::PbmBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::U8> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::U16> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::BWBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::PbmBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::U8> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::U16> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::BWBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::PbmBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::U8> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::U16> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::BWBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::PbmBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::U8> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::U16> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::BWBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::PbmBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::U8> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::U16> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::BWBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::PbmBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::U8> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::U16> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::BWBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::PbmBit> <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::U8> Line | Count | Source | 671 | 205 | fn read_ascii<Basic: Sample>(&mut self, output_buf: &mut [u8]) -> ImageResult<()> { | 672 | 205 | Basic::from_ascii(&mut self.reader, output_buf) | 673 | 205 | } |
<image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::U16> Line | Count | Source | 671 | 238 | fn read_ascii<Basic: Sample>(&mut self, output_buf: &mut [u8]) -> ImageResult<()> { | 672 | 238 | Basic::from_ascii(&mut self.reader, output_buf) | 673 | 238 | } |
Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::BWBit> <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::PbmBit> Line | Count | Source | 671 | 126 | fn read_ascii<Basic: Sample>(&mut self, output_buf: &mut [u8]) -> ImageResult<()> { | 672 | 126 | Basic::from_ascii(&mut self.reader, output_buf) | 673 | 126 | } |
Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::U8> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::U16> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::BWBit> Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::PbmBit> <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::U8> Line | Count | Source | 671 | 12 | fn read_ascii<Basic: Sample>(&mut self, output_buf: &mut [u8]) -> ImageResult<()> { | 672 | 12 | Basic::from_ascii(&mut self.reader, output_buf) | 673 | 12 | } |
<image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::U16> Line | Count | Source | 671 | 12 | fn read_ascii<Basic: Sample>(&mut self, output_buf: &mut [u8]) -> ImageResult<()> { | 672 | 12 | Basic::from_ascii(&mut self.reader, output_buf) | 673 | 12 | } |
Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::BWBit> <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::read_ascii::<image::codecs::pnm::decoder::PbmBit> Line | Count | Source | 671 | 1 | fn read_ascii<Basic: Sample>(&mut self, output_buf: &mut [u8]) -> ImageResult<()> { | 672 | 1 | Basic::from_ascii(&mut self.reader, output_buf) | 673 | 1 | } |
|
674 | | |
675 | | /// Get the pnm subtype, depending on the magic constant contained in the header |
676 | 1.39k | pub fn subtype(&self) -> PnmSubtype { |
677 | 1.39k | self.header.subtype() |
678 | 1.39k | } Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::subtype Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<_>>::subtype Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::subtype Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::subtype Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::subtype Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::subtype Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::subtype Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::subtype Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::subtype <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::subtype Line | Count | Source | 676 | 1.34k | pub fn subtype(&self) -> PnmSubtype { | 677 | 1.34k | self.header.subtype() | 678 | 1.34k | } |
Unexecuted instantiation: <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::subtype <image::codecs::pnm::decoder::PnmDecoder<std::io::cursor::Cursor<&[u8]>>>::subtype Line | Count | Source | 676 | 50 | pub fn subtype(&self) -> PnmSubtype { | 677 | 50 | self.header.subtype() | 678 | 50 | } |
|
679 | | } |
680 | | |
681 | 5.73k | fn read_separated_ascii<T: TryFrom<u16>>(reader: &mut dyn Read) -> ImageResult<T> { |
682 | 25.2k | let is_separator = |v: &u8| matches!(*v, b'\t' | b'\n' | b'\x0b' | b'\x0c' | b'\r' | b' '); image::codecs::pnm::decoder::read_separated_ascii::<u8>::{closure#0} Line | Count | Source | 682 | 11.5k | let is_separator = |v: &u8| matches!(*v, b'\t' | b'\n' | b'\x0b' | b'\x0c' | b'\r' | b' '); |
image::codecs::pnm::decoder::read_separated_ascii::<u16>::{closure#0} Line | Count | Source | 682 | 13.7k | let is_separator = |v: &u8| matches!(*v, b'\t' | b'\n' | b'\x0b' | b'\x0c' | b'\r' | b' '); |
|
683 | | |
684 | 5.73k | let mut v: u16 = 0; |
685 | 5.73k | let mut had_any = false; |
686 | | #[allow(clippy::unbuffered_bytes)] |
687 | 7.61k | for rc in reader |
688 | 5.73k | .bytes() |
689 | 12.4k | .skip_while(|v| v.as_ref().ok().is_some_and(is_separator)) image::codecs::pnm::decoder::read_separated_ascii::<u8>::{closure#1} Line | Count | Source | 689 | 5.21k | .skip_while(|v| v.as_ref().ok().is_some_and(is_separator)) |
image::codecs::pnm::decoder::read_separated_ascii::<u16>::{closure#1} Line | Count | Source | 689 | 7.19k | .skip_while(|v| v.as_ref().ok().is_some_and(is_separator)) |
|
690 | 12.8k | .take_while(|v| v.as_ref().ok().is_some_and(|c| !is_separator(c))) image::codecs::pnm::decoder::read_separated_ascii::<u8>::{closure#2} Line | Count | Source | 690 | 6.31k | .take_while(|v| v.as_ref().ok().is_some_and(|c| !is_separator(c))) |
image::codecs::pnm::decoder::read_separated_ascii::<u16>::{closure#2} Line | Count | Source | 690 | 6.58k | .take_while(|v| v.as_ref().ok().is_some_and(|c| !is_separator(c))) |
image::codecs::pnm::decoder::read_separated_ascii::<u8>::{closure#2}::{closure#0} Line | Count | Source | 690 | 6.31k | .take_while(|v| v.as_ref().ok().is_some_and(|c| !is_separator(c))) |
image::codecs::pnm::decoder::read_separated_ascii::<u16>::{closure#2}::{closure#0} Line | Count | Source | 690 | 6.58k | .take_while(|v| v.as_ref().ok().is_some_and(|c| !is_separator(c))) |
|
691 | | { |
692 | 7.61k | let c = rc?; |
693 | 7.61k | let digit = match c { |
694 | 7.59k | b'0'..=b'9' => u16::from(c - b'0'), |
695 | 42 | _ => return Err(DecoderError::InvalidDigit(ErrorDataSource::Sample).into()), |
696 | | }; |
697 | 7.57k | v = v.checked_mul(10).ok_or(DecoderError::Overflow)?; |
698 | 7.57k | v = v.checked_add(digit).ok_or(DecoderError::Overflow)?; |
699 | 7.57k | had_any = true; |
700 | | } |
701 | | |
702 | 5.69k | if !had_any { |
703 | 337 | return Err(DecoderError::InputTooShort.into()); |
704 | 5.35k | } |
705 | 5.35k | |
706 | 5.35k | Ok(T::try_from(v).or(Err(DecoderError::Overflow))?) |
707 | 5.73k | } image::codecs::pnm::decoder::read_separated_ascii::<u8> Line | Count | Source | 681 | 2.84k | fn read_separated_ascii<T: TryFrom<u16>>(reader: &mut dyn Read) -> ImageResult<T> { | 682 | 2.84k | let is_separator = |v: &u8| matches!(*v, b'\t' | b'\n' | b'\x0b' | b'\x0c' | b'\r' | b' '); | 683 | | | 684 | 2.84k | let mut v: u16 = 0; | 685 | 2.84k | let mut had_any = false; | 686 | | #[allow(clippy::unbuffered_bytes)] | 687 | 3.69k | for rc in reader | 688 | 2.84k | .bytes() | 689 | 2.84k | .skip_while(|v| v.as_ref().ok().is_some_and(is_separator)) | 690 | 2.84k | .take_while(|v| v.as_ref().ok().is_some_and(|c| !is_separator(c))) | 691 | | { | 692 | 3.69k | let c = rc?; | 693 | 3.69k | let digit = match c { | 694 | 3.68k | b'0'..=b'9' => u16::from(c - b'0'), | 695 | 21 | _ => return Err(DecoderError::InvalidDigit(ErrorDataSource::Sample).into()), | 696 | | }; | 697 | 3.67k | v = v.checked_mul(10).ok_or(DecoderError::Overflow)?; | 698 | 3.67k | v = v.checked_add(digit).ok_or(DecoderError::Overflow)?; | 699 | 3.67k | had_any = true; | 700 | | } | 701 | | | 702 | 2.82k | if !had_any { | 703 | 169 | return Err(DecoderError::InputTooShort.into()); | 704 | 2.65k | } | 705 | 2.65k | | 706 | 2.65k | Ok(T::try_from(v).or(Err(DecoderError::Overflow))?) | 707 | 2.84k | } |
image::codecs::pnm::decoder::read_separated_ascii::<u16> Line | Count | Source | 681 | 2.88k | fn read_separated_ascii<T: TryFrom<u16>>(reader: &mut dyn Read) -> ImageResult<T> { | 682 | 2.88k | let is_separator = |v: &u8| matches!(*v, b'\t' | b'\n' | b'\x0b' | b'\x0c' | b'\r' | b' '); | 683 | | | 684 | 2.88k | let mut v: u16 = 0; | 685 | 2.88k | let mut had_any = false; | 686 | | #[allow(clippy::unbuffered_bytes)] | 687 | 3.92k | for rc in reader | 688 | 2.88k | .bytes() | 689 | 2.88k | .skip_while(|v| v.as_ref().ok().is_some_and(is_separator)) | 690 | 2.88k | .take_while(|v| v.as_ref().ok().is_some_and(|c| !is_separator(c))) | 691 | | { | 692 | 3.92k | let c = rc?; | 693 | 3.92k | let digit = match c { | 694 | 3.91k | b'0'..=b'9' => u16::from(c - b'0'), | 695 | 21 | _ => return Err(DecoderError::InvalidDigit(ErrorDataSource::Sample).into()), | 696 | | }; | 697 | 3.89k | v = v.checked_mul(10).ok_or(DecoderError::Overflow)?; | 698 | 3.89k | v = v.checked_add(digit).ok_or(DecoderError::Overflow)?; | 699 | 3.89k | had_any = true; | 700 | | } | 701 | | | 702 | 2.86k | if !had_any { | 703 | 168 | return Err(DecoderError::InputTooShort.into()); | 704 | 2.69k | } | 705 | 2.69k | | 706 | 2.69k | Ok(T::try_from(v).or(Err(DecoderError::Overflow))?) | 707 | 2.88k | } |
|
708 | | |
709 | | impl Sample for U8 { |
710 | | type Representation = u8; |
711 | | |
712 | 186 | fn from_bytes(bytes: &[u8], _row_size: usize, output_buf: &mut [u8]) -> ImageResult<()> { |
713 | 186 | output_buf.copy_from_slice(bytes); |
714 | 186 | Ok(()) |
715 | 186 | } |
716 | | |
717 | 217 | fn from_ascii(reader: &mut dyn Read, output_buf: &mut [u8]) -> ImageResult<()> { |
718 | 2.86k | for b in output_buf { |
719 | 2.84k | *b = read_separated_ascii(reader)?; |
720 | | } |
721 | 14 | Ok(()) |
722 | 217 | } |
723 | | } |
724 | | |
725 | | impl Sample for U16 { |
726 | | type Representation = u16; |
727 | | |
728 | 120 | fn from_bytes(bytes: &[u8], _row_size: usize, output_buf: &mut [u8]) -> ImageResult<()> { |
729 | 120 | output_buf.copy_from_slice(bytes); |
730 | 1.14M | for chunk in output_buf.chunks_exact_mut(2) { |
731 | 1.14M | let v = BigEndian::read_u16(chunk); |
732 | 1.14M | NativeEndian::write_u16(chunk, v); |
733 | 1.14M | } |
734 | 120 | Ok(()) |
735 | 120 | } |
736 | | |
737 | 250 | fn from_ascii(reader: &mut dyn Read, output_buf: &mut [u8]) -> ImageResult<()> { |
738 | 2.88k | for chunk in output_buf.chunks_exact_mut(2) { |
739 | 2.88k | let v = read_separated_ascii::<u16>(reader)?; |
740 | 2.69k | NativeEndian::write_u16(chunk, v); |
741 | | } |
742 | 59 | Ok(()) |
743 | 250 | } |
744 | | } |
745 | | |
746 | | // The image is encoded in rows of bits, high order bits first. Any bits beyond the row bits should |
747 | | // be ignored. Also, contrary to rgb, black pixels are encoded as a 1 while white is 0. This will |
748 | | // need to be reversed for the grayscale output. |
749 | | impl Sample for PbmBit { |
750 | | type Representation = u8; |
751 | | |
752 | 352 | fn bytelen(width: u32, height: u32, samples: u32) -> ImageResult<usize> { |
753 | 352 | let count = width * samples; |
754 | 352 | let linelen = (count / 8) + u32::from((count % 8) != 0); |
755 | 352 | Ok((linelen * height) as usize) |
756 | 352 | } |
757 | | |
758 | 201 | fn from_bytes(bytes: &[u8], row_size: usize, output_buf: &mut [u8]) -> ImageResult<()> { |
759 | 201 | let mut expanded = utils::expand_bits(1, row_size.try_into().unwrap(), bytes); |
760 | 20.5M | for b in &mut expanded { |
761 | 20.5M | *b = !*b; |
762 | 20.5M | } |
763 | 201 | output_buf.copy_from_slice(&expanded); |
764 | 201 | Ok(()) |
765 | 201 | } |
766 | | |
767 | 127 | fn from_ascii(reader: &mut dyn Read, output_buf: &mut [u8]) -> ImageResult<()> { |
768 | 127 | #[allow(clippy::unbuffered_bytes)] |
769 | 127 | let mut bytes = reader.bytes(); |
770 | 525 | for b in output_buf { |
771 | | loop { |
772 | 2.00k | let byte = bytes |
773 | 2.00k | .next() |
774 | 2.00k | .ok_or_else::<ImageError, _>(|| DecoderError::InputTooShort.into())??; |
775 | 1.88k | match byte { |
776 | 1.48k | b'\t' | b'\n' | b'\x0b' | b'\x0c' | b'\r' | b' ' => continue, |
777 | 202 | b'0' => *b = 255, |
778 | 196 | b'1' => *b = 0, |
779 | 1 | c => return Err(DecoderError::UnexpectedByteInRaster(c).into()), |
780 | | } |
781 | 398 | break; |
782 | | } |
783 | | } |
784 | | |
785 | 4 | Ok(()) |
786 | 127 | } |
787 | | } |
788 | | |
789 | | // Encoded just like a normal U8 but we check the values. |
790 | | impl Sample for BWBit { |
791 | | type Representation = u8; |
792 | | |
793 | 39 | fn from_bytes(bytes: &[u8], row_size: usize, output_buf: &mut [u8]) -> ImageResult<()> { |
794 | 39 | U8::from_bytes(bytes, row_size, output_buf)?; |
795 | 3.01k | if let Some(val) = output_buf.iter().find(|&val| *val > 1) { |
796 | 8 | return Err(DecoderError::SampleOutOfBounds(*val).into()); |
797 | 31 | } |
798 | 31 | Ok(()) |
799 | 39 | } |
800 | | |
801 | 0 | fn from_ascii(_reader: &mut dyn Read, _output_buf: &mut [u8]) -> ImageResult<()> { |
802 | 0 | unreachable!("BW bits from anymaps are never encoded as ASCII") |
803 | | } |
804 | | } |
805 | | |
806 | | impl DecodableImageHeader for BitmapHeader { |
807 | 0 | fn tuple_type(&self) -> ImageResult<TupleType> { |
808 | 0 | Ok(TupleType::PbmBit) |
809 | 0 | } |
810 | | } |
811 | | |
812 | | impl DecodableImageHeader for GraymapHeader { |
813 | 349 | fn tuple_type(&self) -> ImageResult<TupleType> { |
814 | 209 | match self.maxwhite { |
815 | 2 | 0 => Err(DecoderError::MaxvalZero.into()), |
816 | 347 | v if v <= 0xFF => Ok(TupleType::GrayU8), |
817 | 209 | v if v <= 0xFFFF => Ok(TupleType::GrayU16), |
818 | 55 | _ => Err(DecoderError::MaxvalTooBig(self.maxwhite).into()), |
819 | | } |
820 | 349 | } |
821 | | } |
822 | | |
823 | | impl DecodableImageHeader for PixmapHeader { |
824 | 482 | fn tuple_type(&self) -> ImageResult<TupleType> { |
825 | 275 | match self.maxval { |
826 | 1 | 0 => Err(DecoderError::MaxvalZero.into()), |
827 | 481 | v if v <= 0xFF => Ok(TupleType::RGBU8), |
828 | 275 | v if v <= 0xFFFF => Ok(TupleType::RGBU16), |
829 | 49 | _ => Err(DecoderError::MaxvalTooBig(self.maxval).into()), |
830 | | } |
831 | 482 | } |
832 | | } |
833 | | |
834 | | impl DecodableImageHeader for ArbitraryHeader { |
835 | 570 | fn tuple_type(&self) -> ImageResult<TupleType> { |
836 | 7 | match self.tupltype { |
837 | 570 | _ if self.maxval == 0 => Err(DecoderError::MaxvalZero.into()), |
838 | 69 | None if self.depth == 1 => Ok(TupleType::GrayU8), |
839 | 41 | None if self.depth == 2 => Err(ImageError::Unsupported( |
840 | 1 | UnsupportedError::from_format_and_kind( |
841 | 1 | ImageFormat::Pnm.into(), |
842 | 1 | UnsupportedErrorKind::Color(ExtendedColorType::La8), |
843 | 1 | ), |
844 | 1 | )), |
845 | 40 | None if self.depth == 3 => Ok(TupleType::RGBU8), |
846 | 7 | None if self.depth == 4 => Err(ImageError::Unsupported( |
847 | 3 | UnsupportedError::from_format_and_kind( |
848 | 3 | ImageFormat::Pnm.into(), |
849 | 3 | UnsupportedErrorKind::Color(ExtendedColorType::Rgba8), |
850 | 3 | ), |
851 | 3 | )), |
852 | | |
853 | 148 | Some(ArbitraryTuplType::BlackAndWhite) if self.maxval == 1 && self.depth == 1 => { |
854 | 63 | Ok(TupleType::BWBit) |
855 | | } |
856 | 85 | Some(ArbitraryTuplType::BlackAndWhite) => Err(DecoderError::InvalidDepthOrMaxval { |
857 | 85 | tuple_type: ArbitraryTuplType::BlackAndWhite, |
858 | 85 | maxval: self.maxval, |
859 | 85 | depth: self.depth, |
860 | 85 | } |
861 | 85 | .into()), |
862 | | |
863 | 81 | Some(ArbitraryTuplType::Grayscale) if self.depth == 1 && self.maxval <= 0xFF => { |
864 | 14 | Ok(TupleType::GrayU8) |
865 | | } |
866 | 67 | Some(ArbitraryTuplType::Grayscale) if self.depth <= 1 && self.maxval <= 0xFFFF => { |
867 | 29 | Ok(TupleType::GrayU16) |
868 | | } |
869 | 38 | Some(ArbitraryTuplType::Grayscale) => Err(DecoderError::InvalidDepthOrMaxval { |
870 | 38 | tuple_type: ArbitraryTuplType::Grayscale, |
871 | 38 | maxval: self.maxval, |
872 | 38 | depth: self.depth, |
873 | 38 | } |
874 | 38 | .into()), |
875 | | |
876 | 143 | Some(ArbitraryTuplType::RGB) if self.depth == 3 && self.maxval <= 0xFF => { |
877 | 14 | Ok(TupleType::RGBU8) |
878 | | } |
879 | 129 | Some(ArbitraryTuplType::RGB) if self.depth == 3 && self.maxval <= 0xFFFF => { |
880 | 28 | Ok(TupleType::RGBU16) |
881 | | } |
882 | 101 | Some(ArbitraryTuplType::RGB) => Err(DecoderError::InvalidDepth { |
883 | 101 | tuple_type: ArbitraryTuplType::RGB, |
884 | 101 | depth: self.depth, |
885 | 101 | } |
886 | 101 | .into()), |
887 | | |
888 | 1 | Some(ArbitraryTuplType::BlackAndWhiteAlpha) => Err(ImageError::Unsupported( |
889 | 1 | UnsupportedError::from_format_and_kind( |
890 | 1 | ImageFormat::Pnm.into(), |
891 | 1 | UnsupportedErrorKind::GenericFeature(format!( |
892 | 1 | "Color type {}", |
893 | 1 | ArbitraryTuplType::BlackAndWhiteAlpha.name() |
894 | 1 | )), |
895 | 1 | ), |
896 | 1 | )), |
897 | 1 | Some(ArbitraryTuplType::GrayscaleAlpha) => Err(ImageError::Unsupported( |
898 | 1 | UnsupportedError::from_format_and_kind( |
899 | 1 | ImageFormat::Pnm.into(), |
900 | 1 | UnsupportedErrorKind::Color(ExtendedColorType::La8), |
901 | 1 | ), |
902 | 1 | )), |
903 | 1 | Some(ArbitraryTuplType::RGBAlpha) => Err(ImageError::Unsupported( |
904 | 1 | UnsupportedError::from_format_and_kind( |
905 | 1 | ImageFormat::Pnm.into(), |
906 | 1 | UnsupportedErrorKind::Color(ExtendedColorType::Rgba8), |
907 | 1 | ), |
908 | 1 | )), |
909 | 118 | Some(ArbitraryTuplType::Custom(ref custom)) => Err(ImageError::Unsupported( |
910 | 118 | UnsupportedError::from_format_and_kind( |
911 | 118 | ImageFormat::Pnm.into(), |
912 | 118 | UnsupportedErrorKind::GenericFeature(format!("Tuple type {custom:?}")), |
913 | 118 | ), |
914 | 118 | )), |
915 | 4 | None => Err(DecoderError::TupleTypeUnrecognised.into()), |
916 | | } |
917 | 570 | } |
918 | | } |
919 | | |
920 | | #[cfg(test)] |
921 | | mod tests { |
922 | | use super::*; |
923 | | /// Tests reading of a valid blackandwhite pam |
924 | | #[test] |
925 | | fn pam_blackandwhite() { |
926 | | let pamdata = b"P7 |
927 | | WIDTH 4 |
928 | | HEIGHT 4 |
929 | | DEPTH 1 |
930 | | MAXVAL 1 |
931 | | TUPLTYPE BLACKANDWHITE |
932 | | # Comment line |
933 | | ENDHDR |
934 | | \x01\x00\x00\x01\x01\x00\x00\x01\x01\x00\x00\x01\x01\x00\x00\x01"; |
935 | | let decoder = PnmDecoder::new(&pamdata[..]).unwrap(); |
936 | | assert_eq!(decoder.color_type(), ColorType::L8); |
937 | | assert_eq!(decoder.original_color_type(), ExtendedColorType::L1); |
938 | | assert_eq!(decoder.dimensions(), (4, 4)); |
939 | | assert_eq!(decoder.subtype(), PnmSubtype::ArbitraryMap); |
940 | | |
941 | | let mut image = vec![0; decoder.total_bytes() as usize]; |
942 | | decoder.read_image(&mut image).unwrap(); |
943 | | assert_eq!( |
944 | | image, |
945 | | vec![ |
946 | | 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, |
947 | | 0x00, 0xFF |
948 | | ] |
949 | | ); |
950 | | match PnmDecoder::new(&pamdata[..]).unwrap().into_inner() { |
951 | | ( |
952 | | _, |
953 | | PnmHeader { |
954 | | decoded: |
955 | | HeaderRecord::Arbitrary(ArbitraryHeader { |
956 | | width: 4, |
957 | | height: 4, |
958 | | maxval: 1, |
959 | | depth: 1, |
960 | | tupltype: Some(ArbitraryTuplType::BlackAndWhite), |
961 | | }), |
962 | | encoded: _, |
963 | | }, |
964 | | ) => (), |
965 | | _ => panic!("Decoded header is incorrect"), |
966 | | } |
967 | | } |
968 | | |
969 | | /// Tests reading of a valid grayscale pam |
970 | | #[test] |
971 | | fn pam_grayscale() { |
972 | | let pamdata = b"P7 |
973 | | WIDTH 4 |
974 | | HEIGHT 4 |
975 | | DEPTH 1 |
976 | | MAXVAL 255 |
977 | | TUPLTYPE GRAYSCALE |
978 | | # Comment line |
979 | | ENDHDR |
980 | | \xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef"; |
981 | | let decoder = PnmDecoder::new(&pamdata[..]).unwrap(); |
982 | | assert_eq!(decoder.color_type(), ColorType::L8); |
983 | | assert_eq!(decoder.dimensions(), (4, 4)); |
984 | | assert_eq!(decoder.subtype(), PnmSubtype::ArbitraryMap); |
985 | | |
986 | | let mut image = vec![0; decoder.total_bytes() as usize]; |
987 | | decoder.read_image(&mut image).unwrap(); |
988 | | assert_eq!( |
989 | | image, |
990 | | vec![ |
991 | | 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, |
992 | | 0xbe, 0xef |
993 | | ] |
994 | | ); |
995 | | match PnmDecoder::new(&pamdata[..]).unwrap().into_inner() { |
996 | | ( |
997 | | _, |
998 | | PnmHeader { |
999 | | decoded: |
1000 | | HeaderRecord::Arbitrary(ArbitraryHeader { |
1001 | | width: 4, |
1002 | | height: 4, |
1003 | | depth: 1, |
1004 | | maxval: 255, |
1005 | | tupltype: Some(ArbitraryTuplType::Grayscale), |
1006 | | }), |
1007 | | encoded: _, |
1008 | | }, |
1009 | | ) => (), |
1010 | | _ => panic!("Decoded header is incorrect"), |
1011 | | } |
1012 | | } |
1013 | | |
1014 | | /// Tests reading of a valid rgb pam |
1015 | | #[test] |
1016 | | fn pam_rgb() { |
1017 | | let pamdata = b"P7 |
1018 | | # Comment line |
1019 | | MAXVAL 255 |
1020 | | TUPLTYPE RGB |
1021 | | DEPTH 3 |
1022 | | WIDTH 2 |
1023 | | HEIGHT 2 |
1024 | | ENDHDR |
1025 | | \xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef"; |
1026 | | let decoder = PnmDecoder::new(&pamdata[..]).unwrap(); |
1027 | | assert_eq!(decoder.color_type(), ColorType::Rgb8); |
1028 | | assert_eq!(decoder.dimensions(), (2, 2)); |
1029 | | assert_eq!(decoder.subtype(), PnmSubtype::ArbitraryMap); |
1030 | | |
1031 | | let mut image = vec![0; decoder.total_bytes() as usize]; |
1032 | | decoder.read_image(&mut image).unwrap(); |
1033 | | assert_eq!( |
1034 | | image, |
1035 | | vec![0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef] |
1036 | | ); |
1037 | | match PnmDecoder::new(&pamdata[..]).unwrap().into_inner() { |
1038 | | ( |
1039 | | _, |
1040 | | PnmHeader { |
1041 | | decoded: |
1042 | | HeaderRecord::Arbitrary(ArbitraryHeader { |
1043 | | maxval: 255, |
1044 | | tupltype: Some(ArbitraryTuplType::RGB), |
1045 | | depth: 3, |
1046 | | width: 2, |
1047 | | height: 2, |
1048 | | }), |
1049 | | encoded: _, |
1050 | | }, |
1051 | | ) => (), |
1052 | | _ => panic!("Decoded header is incorrect"), |
1053 | | } |
1054 | | } |
1055 | | |
1056 | | #[test] |
1057 | | fn pbm_binary() { |
1058 | | // The data contains two rows of the image (each line is padded to the full byte). For |
1059 | | // comments on its format, see documentation of `impl SampleType for PbmBit`. |
1060 | | let pbmbinary = [&b"P4 6 2\n"[..], &[0b0110_1100_u8, 0b1011_0111]].concat(); |
1061 | | let decoder = PnmDecoder::new(&pbmbinary[..]).unwrap(); |
1062 | | assert_eq!(decoder.color_type(), ColorType::L8); |
1063 | | assert_eq!(decoder.original_color_type(), ExtendedColorType::L1); |
1064 | | assert_eq!(decoder.dimensions(), (6, 2)); |
1065 | | assert_eq!( |
1066 | | decoder.subtype(), |
1067 | | PnmSubtype::Bitmap(SampleEncoding::Binary) |
1068 | | ); |
1069 | | let mut image = vec![0; decoder.total_bytes() as usize]; |
1070 | | decoder.read_image(&mut image).unwrap(); |
1071 | | assert_eq!(image, vec![255, 0, 0, 255, 0, 0, 0, 255, 0, 0, 255, 0]); |
1072 | | match PnmDecoder::new(&pbmbinary[..]).unwrap().into_inner() { |
1073 | | ( |
1074 | | _, |
1075 | | PnmHeader { |
1076 | | decoded: |
1077 | | HeaderRecord::Bitmap(BitmapHeader { |
1078 | | encoding: SampleEncoding::Binary, |
1079 | | width: 6, |
1080 | | height: 2, |
1081 | | }), |
1082 | | encoded: _, |
1083 | | }, |
1084 | | ) => (), |
1085 | | _ => panic!("Decoded header is incorrect"), |
1086 | | } |
1087 | | } |
1088 | | |
1089 | | /// A previous infinite loop. |
1090 | | #[test] |
1091 | | fn pbm_binary_ascii_termination() { |
1092 | | use std::io::{BufReader, Cursor, Error, ErrorKind, Read, Result}; |
1093 | | struct FailRead(Cursor<&'static [u8]>); |
1094 | | |
1095 | | impl Read for FailRead { |
1096 | | fn read(&mut self, buf: &mut [u8]) -> Result<usize> { |
1097 | | match self.0.read(buf) { |
1098 | | Ok(n) if n > 0 => Ok(n), |
1099 | | _ => Err(Error::new( |
1100 | | ErrorKind::BrokenPipe, |
1101 | | "Simulated broken pipe error", |
1102 | | )), |
1103 | | } |
1104 | | } |
1105 | | } |
1106 | | |
1107 | | let pbmbinary = BufReader::new(FailRead(Cursor::new(b"P1 1 1\n"))); |
1108 | | |
1109 | | let decoder = PnmDecoder::new(pbmbinary).unwrap(); |
1110 | | let mut image = vec![0; decoder.total_bytes() as usize]; |
1111 | | decoder |
1112 | | .read_image(&mut image) |
1113 | | .expect_err("Image is malformed"); |
1114 | | } |
1115 | | |
1116 | | #[test] |
1117 | | fn pbm_ascii() { |
1118 | | // The data contains two rows of the image (each line is padded to the full byte). For |
1119 | | // comments on its format, see documentation of `impl SampleType for PbmBit`. Tests all |
1120 | | // whitespace characters that should be allowed (the 6 characters according to POSIX). |
1121 | | let pbmbinary = b"P1 6 2\n 0 1 1 0 1 1\n1 0 1 1 0\t\n\x0b\x0c\r1"; |
1122 | | let decoder = PnmDecoder::new(&pbmbinary[..]).unwrap(); |
1123 | | assert_eq!(decoder.color_type(), ColorType::L8); |
1124 | | assert_eq!(decoder.original_color_type(), ExtendedColorType::L1); |
1125 | | assert_eq!(decoder.dimensions(), (6, 2)); |
1126 | | assert_eq!(decoder.subtype(), PnmSubtype::Bitmap(SampleEncoding::Ascii)); |
1127 | | |
1128 | | let mut image = vec![0; decoder.total_bytes() as usize]; |
1129 | | decoder.read_image(&mut image).unwrap(); |
1130 | | assert_eq!(image, vec![255, 0, 0, 255, 0, 0, 0, 255, 0, 0, 255, 0]); |
1131 | | match PnmDecoder::new(&pbmbinary[..]).unwrap().into_inner() { |
1132 | | ( |
1133 | | _, |
1134 | | PnmHeader { |
1135 | | decoded: |
1136 | | HeaderRecord::Bitmap(BitmapHeader { |
1137 | | encoding: SampleEncoding::Ascii, |
1138 | | width: 6, |
1139 | | height: 2, |
1140 | | }), |
1141 | | encoded: _, |
1142 | | }, |
1143 | | ) => (), |
1144 | | _ => panic!("Decoded header is incorrect"), |
1145 | | } |
1146 | | } |
1147 | | |
1148 | | #[test] |
1149 | | fn pbm_ascii_nospace() { |
1150 | | // The data contains two rows of the image (each line is padded to the full byte). Notably, |
1151 | | // it is completely within specification for the ascii data not to contain separating |
1152 | | // whitespace for the pbm format or any mix. |
1153 | | let pbmbinary = b"P1 6 2\n011011101101"; |
1154 | | let decoder = PnmDecoder::new(&pbmbinary[..]).unwrap(); |
1155 | | assert_eq!(decoder.color_type(), ColorType::L8); |
1156 | | assert_eq!(decoder.original_color_type(), ExtendedColorType::L1); |
1157 | | assert_eq!(decoder.dimensions(), (6, 2)); |
1158 | | assert_eq!(decoder.subtype(), PnmSubtype::Bitmap(SampleEncoding::Ascii)); |
1159 | | |
1160 | | let mut image = vec![0; decoder.total_bytes() as usize]; |
1161 | | decoder.read_image(&mut image).unwrap(); |
1162 | | assert_eq!(image, vec![255, 0, 0, 255, 0, 0, 0, 255, 0, 0, 255, 0]); |
1163 | | match PnmDecoder::new(&pbmbinary[..]).unwrap().into_inner() { |
1164 | | ( |
1165 | | _, |
1166 | | PnmHeader { |
1167 | | decoded: |
1168 | | HeaderRecord::Bitmap(BitmapHeader { |
1169 | | encoding: SampleEncoding::Ascii, |
1170 | | width: 6, |
1171 | | height: 2, |
1172 | | }), |
1173 | | encoded: _, |
1174 | | }, |
1175 | | ) => (), |
1176 | | _ => panic!("Decoded header is incorrect"), |
1177 | | } |
1178 | | } |
1179 | | |
1180 | | #[test] |
1181 | | fn pgm_binary() { |
1182 | | // The data contains two rows of the image (each line is padded to the full byte). For |
1183 | | // comments on its format, see documentation of `impl SampleType for PbmBit`. |
1184 | | let elements = (0..16).collect::<Vec<_>>(); |
1185 | | let pbmbinary = [&b"P5 4 4 255\n"[..], &elements].concat(); |
1186 | | let decoder = PnmDecoder::new(&pbmbinary[..]).unwrap(); |
1187 | | assert_eq!(decoder.color_type(), ColorType::L8); |
1188 | | assert_eq!(decoder.dimensions(), (4, 4)); |
1189 | | assert_eq!( |
1190 | | decoder.subtype(), |
1191 | | PnmSubtype::Graymap(SampleEncoding::Binary) |
1192 | | ); |
1193 | | let mut image = vec![0; decoder.total_bytes() as usize]; |
1194 | | decoder.read_image(&mut image).unwrap(); |
1195 | | assert_eq!(image, elements); |
1196 | | match PnmDecoder::new(&pbmbinary[..]).unwrap().into_inner() { |
1197 | | ( |
1198 | | _, |
1199 | | PnmHeader { |
1200 | | decoded: |
1201 | | HeaderRecord::Graymap(GraymapHeader { |
1202 | | encoding: SampleEncoding::Binary, |
1203 | | width: 4, |
1204 | | height: 4, |
1205 | | maxwhite: 255, |
1206 | | }), |
1207 | | encoded: _, |
1208 | | }, |
1209 | | ) => (), |
1210 | | _ => panic!("Decoded header is incorrect"), |
1211 | | } |
1212 | | } |
1213 | | |
1214 | | #[test] |
1215 | | fn pgm_ascii() { |
1216 | | // The data contains two rows of the image (each line is padded to the full byte). For |
1217 | | // comments on its format, see documentation of `impl SampleType for PbmBit`. |
1218 | | let pbmbinary = b"P2 4 4 255\n 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"; |
1219 | | let decoder = PnmDecoder::new(&pbmbinary[..]).unwrap(); |
1220 | | assert_eq!(decoder.color_type(), ColorType::L8); |
1221 | | assert_eq!(decoder.dimensions(), (4, 4)); |
1222 | | assert_eq!( |
1223 | | decoder.subtype(), |
1224 | | PnmSubtype::Graymap(SampleEncoding::Ascii) |
1225 | | ); |
1226 | | let mut image = vec![0; decoder.total_bytes() as usize]; |
1227 | | decoder.read_image(&mut image).unwrap(); |
1228 | | assert_eq!(image, (0..16).collect::<Vec<_>>()); |
1229 | | match PnmDecoder::new(&pbmbinary[..]).unwrap().into_inner() { |
1230 | | ( |
1231 | | _, |
1232 | | PnmHeader { |
1233 | | decoded: |
1234 | | HeaderRecord::Graymap(GraymapHeader { |
1235 | | encoding: SampleEncoding::Ascii, |
1236 | | width: 4, |
1237 | | height: 4, |
1238 | | maxwhite: 255, |
1239 | | }), |
1240 | | encoded: _, |
1241 | | }, |
1242 | | ) => (), |
1243 | | _ => panic!("Decoded header is incorrect"), |
1244 | | } |
1245 | | } |
1246 | | |
1247 | | #[test] |
1248 | | fn ppm_ascii() { |
1249 | | let ascii = b"P3 1 1 2000\n0 1000 2000"; |
1250 | | let decoder = PnmDecoder::new(&ascii[..]).unwrap(); |
1251 | | let mut image = vec![0; decoder.total_bytes() as usize]; |
1252 | | decoder.read_image(&mut image).unwrap(); |
1253 | | assert_eq!( |
1254 | | image, |
1255 | | [ |
1256 | | 0_u16.to_ne_bytes(), |
1257 | | (u16::MAX / 2 + 1).to_ne_bytes(), |
1258 | | u16::MAX.to_ne_bytes() |
1259 | | ] |
1260 | | .into_iter() |
1261 | | .flatten() |
1262 | | .collect::<Vec<_>>() |
1263 | | ); |
1264 | | } |
1265 | | |
1266 | | #[test] |
1267 | | fn dimension_overflow() { |
1268 | | let pamdata = b"P7 |
1269 | | # Comment line |
1270 | | MAXVAL 255 |
1271 | | TUPLTYPE RGB |
1272 | | DEPTH 3 |
1273 | | WIDTH 4294967295 |
1274 | | HEIGHT 4294967295 |
1275 | | ENDHDR |
1276 | | \xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef"; |
1277 | | |
1278 | | assert!(PnmDecoder::new(&pamdata[..]).is_err()); |
1279 | | } |
1280 | | |
1281 | | #[test] |
1282 | | fn issue_1508() { |
1283 | | let _ = crate::load_from_memory(b"P391919 16999 1 1 9 919 16999 1 9999 999* 99999 N"); |
1284 | | } |
1285 | | |
1286 | | #[test] |
1287 | | fn issue_1616_overflow() { |
1288 | | let data = [ |
1289 | | 80, 54, 10, 52, 50, 57, 52, 56, 50, 57, 52, 56, 35, 56, 10, 52, 10, 48, 10, 12, 12, 56, |
1290 | | ]; |
1291 | | // Validate: we have a header. Note: we might already calculate that this will fail but |
1292 | | // then we could not return information about the header to the caller. |
1293 | | let decoder = PnmDecoder::new(&data[..]).unwrap(); |
1294 | | let mut image = vec![0; decoder.total_bytes() as usize]; |
1295 | | let _ = decoder.read_image(&mut image); |
1296 | | } |
1297 | | |
1298 | | #[test] |
1299 | | fn data_too_short() { |
1300 | | let data = b"P3 16 16 1\n"; |
1301 | | let decoder = PnmDecoder::new(&data[..]).unwrap(); |
1302 | | let mut image = vec![0; decoder.total_bytes() as usize]; |
1303 | | |
1304 | | let _ = decoder.read_image(&mut image).unwrap_err(); |
1305 | | } |
1306 | | } |