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