| 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 | |