1 | use crate::util::*; |
2 | use crate::{ImageResult, ImageSize}; |
3 | |
4 | use std::io::{BufRead, Seek, SeekFrom}; |
5 | |
6 | pub fn size<R: BufRead + Seek>(reader: &mut R) -> ImageResult<ImageSize> { |
7 | let mut buffer: [u8; 4] = [0; 4]; |
8 | reader.read_exact(&mut buffer)?; |
9 | |
10 | if buffer[3] == b' ' { |
11 | webp_vp8_size(reader) |
12 | } else if buffer[3] == b'L' { |
13 | webp_vp8l_size(reader) |
14 | } else if buffer[3] == b'X' { |
15 | webp_vp8x_size(reader) |
16 | } else { |
17 | Err(std::io::Error::new(kind:std::io::ErrorKind::InvalidData, error:"Invalid VP8 Tag" ).into()) |
18 | } |
19 | } |
20 | |
21 | pub fn matches(header: &[u8]) -> bool { |
22 | header.len() >= 12 && &header[0..4] == b"RIFF" && &header[8..12] == b"WEBP" |
23 | } |
24 | |
25 | fn webp_vp8x_size<R: BufRead + Seek>(reader: &mut R) -> ImageResult<ImageSize> { |
26 | reader.seek(pos:SeekFrom::Start(0x18))?; |
27 | |
28 | Ok(ImageSize { |
29 | width: read_u24(reader, &Endian::Little)? as usize + 1, |
30 | height: read_u24(reader, &Endian::Little)? as usize + 1, |
31 | }) |
32 | } |
33 | |
34 | fn webp_vp8l_size<R: BufRead + Seek>(reader: &mut R) -> ImageResult<ImageSize> { |
35 | reader.seek(pos:SeekFrom::Start(0x15))?; |
36 | |
37 | let dims: u32 = read_u32(reader, &Endian::Little)?; |
38 | |
39 | Ok(ImageSize { |
40 | width: (dims & 0x3FFF) as usize + 1, |
41 | height: ((dims >> 14) & 0x3FFF) as usize + 1, |
42 | }) |
43 | } |
44 | |
45 | fn webp_vp8_size<R: BufRead + Seek>(reader: &mut R) -> ImageResult<ImageSize> { |
46 | reader.seek(pos:SeekFrom::Start(0x1A))?; |
47 | |
48 | Ok(ImageSize { |
49 | width: read_u16(reader, &Endian::Little)? as usize, |
50 | height: read_u16(reader, &Endian::Little)? as usize, |
51 | }) |
52 | } |
53 | |