1use std::io::{self, BufRead, Read, Seek};
9use std::iter;
10
11use image::{ColorType, ExtendedColorType, ImageDecoder, ImageError, ImageResult};
12
13pub struct PCXDecoder<R>
15where
16 R: Read,
17{
18 dimensions: (u32, u32),
19 inner: pcx::Reader<R>,
20}
21
22impl<R> PCXDecoder<R>
23where
24 R: BufRead + Seek,
25{
26 pub fn new(r: R) -> Result<PCXDecoder<R>, ImageError> {
28 let inner = pcx::Reader::new(r).map_err(convert_pcx_decode_error)?;
29 let dimensions = (u32::from(inner.width()), u32::from(inner.height()));
30
31 Ok(PCXDecoder { dimensions, inner })
32 }
33}
34
35fn convert_pcx_decode_error(err: io::Error) -> ImageError {
36 ImageError::IoError(err)
37}
38
39impl<R: BufRead + Seek> ImageDecoder for PCXDecoder<R> {
40 fn dimensions(&self) -> (u32, u32) {
41 self.dimensions
42 }
43
44 fn color_type(&self) -> ColorType {
45 ColorType::Rgb8
46 }
47
48 fn original_color_type(&self) -> ExtendedColorType {
49 if self.inner.is_paletted() {
50 return ExtendedColorType::Unknown(self.inner.header.bit_depth);
51 }
52
53 match (
54 self.inner.header.number_of_color_planes,
55 self.inner.header.bit_depth,
56 ) {
57 (1, 1) => ExtendedColorType::L1,
58 (1, 2) => ExtendedColorType::L2,
59 (1, 4) => ExtendedColorType::L4,
60 (1, 8) => ExtendedColorType::L8,
61 (3, 1) => ExtendedColorType::Rgb1,
62 (3, 2) => ExtendedColorType::Rgb2,
63 (3, 4) => ExtendedColorType::Rgb4,
64 (3, 8) => ExtendedColorType::Rgb8,
65 (4, 1) => ExtendedColorType::Rgba1,
66 (4, 2) => ExtendedColorType::Rgba2,
67 (4, 4) => ExtendedColorType::Rgba4,
68 (4, 8) => ExtendedColorType::Rgba8,
69 (_, _) => unreachable!(),
70 }
71 }
72
73 fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> {
74 assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes()));
75
76 let height = self.inner.height() as usize;
77 let width = self.inner.width() as usize;
78
79 match self.inner.palette_length() {
80 None => {
82 for i in 0..height {
83 let offset = i * 3 * width;
84 self.inner
85 .next_row_rgb(&mut buf[offset..offset + (width * 3)])
86 .map_err(convert_pcx_decode_error)?;
87 }
88 }
89
90 Some(palette_length) => {
95 let mut pal_buf: Vec<u8> = iter::repeat_n(0, height * width).collect();
96
97 for i in 0..height {
98 let offset = i * width;
99 self.inner
100 .next_row_paletted(&mut pal_buf[offset..offset + width])
101 .map_err(convert_pcx_decode_error)?;
102 }
103
104 let mut palette: Vec<u8> =
105 std::iter::repeat_n(0, 3 * palette_length as usize).collect();
106 self.inner
107 .read_palette(&mut palette[..])
108 .map_err(convert_pcx_decode_error)?;
109
110 for i in 0..height {
111 for j in 0..width {
112 let pixel = pal_buf[i * width + j] as usize;
113 let offset = i * width * 3 + j * 3;
114
115 buf[offset] = palette[pixel * 3];
116 buf[offset + 1] = palette[pixel * 3 + 1];
117 buf[offset + 2] = palette[pixel * 3 + 2];
118 }
119 }
120 }
121 }
122
123 Ok(())
124 }
125
126 fn read_image_boxed(self: Box<Self>, buf: &mut [u8]) -> ImageResult<()> {
127 (*self).read_image(buf)
128 }
129}