1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
extern crate jpeg_decoder;
use std::io::{Cursor, Read};
use color::ColorType;
use image::{ImageDecoder, ImageError, ImageResult};
pub struct JPEGDecoder<R> {
decoder: jpeg_decoder::Decoder<R>,
metadata: jpeg_decoder::ImageInfo,
}
impl<R: Read> JPEGDecoder<R> {
pub fn new(r: R) -> ImageResult<JPEGDecoder<R>> {
let mut decoder = jpeg_decoder::Decoder::new(r);
decoder.read_info()?;
let mut metadata = decoder.info().unwrap();
if metadata.pixel_format == jpeg_decoder::PixelFormat::CMYK32 {
metadata.pixel_format = jpeg_decoder::PixelFormat::RGB24;
}
Ok(JPEGDecoder {
decoder,
metadata,
})
}
}
impl<R: Read> ImageDecoder for JPEGDecoder<R> {
type Reader = Cursor<Vec<u8>>;
fn dimensions(&self) -> (u64, u64) {
(self.metadata.width as u64, self.metadata.height as u64)
}
fn colortype(&self) -> ColorType {
self.metadata.pixel_format.into()
}
fn into_reader(self) -> ImageResult<Self::Reader> {
Ok(Cursor::new(self.read_image()?))
}
fn read_image(mut self) -> ImageResult<Vec<u8>> {
let mut data = self.decoder.decode()?;
data = match self.decoder.info().unwrap().pixel_format {
jpeg_decoder::PixelFormat::CMYK32 => cmyk_to_rgb(&data),
_ => data,
};
Ok(data)
}
}
fn cmyk_to_rgb(input: &[u8]) -> Vec<u8> {
let size = input.len() - input.len() / 4;
let mut output = Vec::with_capacity(size);
for pixel in input.chunks(4) {
let c = f32::from(pixel[0]) / 255.0;
let m = f32::from(pixel[1]) / 255.0;
let y = f32::from(pixel[2]) / 255.0;
let k = f32::from(pixel[3]) / 255.0;
let c = c * (1.0 - k) + k;
let m = m * (1.0 - k) + k;
let y = y * (1.0 - k) + k;
let r = (1.0 - c) * 255.0;
let g = (1.0 - m) * 255.0;
let b = (1.0 - y) * 255.0;
output.push(r as u8);
output.push(g as u8);
output.push(b as u8);
}
output
}
impl From<jpeg_decoder::PixelFormat> for ColorType {
fn from(pixel_format: jpeg_decoder::PixelFormat) -> ColorType {
use self::jpeg_decoder::PixelFormat::*;
match pixel_format {
L8 => ColorType::Gray(8),
RGB24 => ColorType::RGB(8),
CMYK32 => panic!(),
}
}
}
impl From<jpeg_decoder::Error> for ImageError {
fn from(err: jpeg_decoder::Error) -> ImageError {
use self::jpeg_decoder::Error::*;
match err {
Format(desc) => ImageError::FormatError(desc),
Unsupported(desc) => ImageError::UnsupportedError(format!("{:?}", desc)),
Io(err) => ImageError::IoError(err),
Internal(err) => ImageError::FormatError(err.description().to_owned()),
}
}
}