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
110
111
112
113
114
115
116
117
118
119
use byteorder::{LittleEndian, ReadBytesExt};
use std::default::Default;
use std::io;
use std::io::{Cursor, Read};
use image;
use image::ImageDecoder;
use image::ImageResult;
use color;
use super::vp8::Frame;
use super::vp8::VP8Decoder;
pub struct WebpDecoder<R> {
r: R,
frame: Frame,
have_frame: bool,
}
impl<R: Read> WebpDecoder<R> {
pub fn new(r: R) -> ImageResult<WebpDecoder<R>> {
let f: Frame = Default::default();
let mut decoder = WebpDecoder {
r,
have_frame: false,
frame: f,
};
decoder.read_metadata()?;
Ok(decoder)
}
fn read_riff_header(&mut self) -> ImageResult<u32> {
let mut riff = Vec::with_capacity(4);
try!(self.r.by_ref().take(4).read_to_end(&mut riff));
let size = try!(self.r.read_u32::<LittleEndian>());
let mut webp = Vec::with_capacity(4);
try!(self.r.by_ref().take(4).read_to_end(&mut webp));
if &*riff != b"RIFF" {
return Err(image::ImageError::FormatError(
"Invalid RIFF signature.".to_string(),
));
}
if &*webp != b"WEBP" {
return Err(image::ImageError::FormatError(
"Invalid WEBP signature.".to_string(),
));
}
Ok(size)
}
fn read_vp8_header(&mut self) -> ImageResult<()> {
let mut vp8 = Vec::with_capacity(4);
try!(self.r.by_ref().take(4).read_to_end(&mut vp8));
if &*vp8 != b"VP8 " {
return Err(image::ImageError::FormatError(
"Invalid VP8 signature.".to_string(),
));
}
let _len = try!(self.r.read_u32::<LittleEndian>());
Ok(())
}
fn read_frame(&mut self) -> ImageResult<()> {
let mut framedata = Vec::new();
try!(self.r.read_to_end(&mut framedata));
let m = io::Cursor::new(framedata);
let mut v = VP8Decoder::new(m);
let frame = try!(v.decode_frame());
self.frame = frame.clone();
Ok(())
}
fn read_metadata(&mut self) -> ImageResult<()> {
if !self.have_frame {
try!(self.read_riff_header());
try!(self.read_vp8_header());
try!(self.read_frame());
self.have_frame = true;
}
Ok(())
}
}
impl<R: Read> ImageDecoder for WebpDecoder<R> {
type Reader = Cursor<Vec<u8>>;
fn dimensions(&self) -> (u64, u64) {
(self.frame.width as u64, self.frame.height as u64)
}
fn colortype(&self) -> color::ColorType {
color::ColorType::Gray(8)
}
fn into_reader(self) -> ImageResult<Self::Reader> {
Ok(Cursor::new(self.frame.ybuf))
}
fn read_image(self) -> ImageResult<Vec<u8>> {
Ok(self.frame.ybuf)
}
}