1use crate::common::*;
2use crate::error::Error;
3use crate::frame::Frame;
4
5use byteorder::{ByteOrder, BigEndian, LittleEndian};
6use std::fs::File;
7use std::io::prelude::*;
8use std::path::Path;
9
10const IDENT: u32 = 0x54494d32;
11
12#[derive(Debug)]
13struct Header {
14 identifier: u32,
15 version: u16,
16 count: usize,
17}
18
19impl Header {
20 fn read(buffer: &[u8], offset: &mut usize) -> Result<Header, Error> {
21 let mut load_part = |size| { get_slice(&buffer, offset, size) };
22 let identifier = BigEndian::read_u32(load_part(4));
23 let version = LittleEndian::read_u16(load_part(2));
24 let count = LittleEndian::read_u16(load_part(2)) as usize;
25
26 load_part(8);
27 if identifier != IDENT {
28 return Err(Error::InvalidIdentifier(identifier))
29 }
30
31 Ok(Header { identifier, version, count })
32 }
33}
34
35#[derive(Debug)]
36pub struct Image {
37 header: Header,
38 frames: Vec::<Frame>,
39}
40
41impl Image {
42 fn read(buffer: &[u8], offset: &mut usize) -> Result<Image, Error> {
43 let header = Header::read(buffer, offset)?;
44 let mut frames = Vec::with_capacity(header.count);
45
46 for _ in 0..header.count {
47 frames.push(Frame::read(buffer, offset)?);
48 }
49
50 Ok(Image { header, frames })
51 }
52
53 pub fn frames(&self) -> &Vec::<Frame> {
54 &self.frames
55 }
56
57 pub fn get_frame(&self, index: usize) -> &Frame {
58 &self.frames[index]
59 }
60}
61
62pub fn from_buffer(buffer: &[u8]) -> Result<Image, Error> {
84 let mut offset = 0usize;
85
86 Image::read(&buffer, &mut offset)
87}
88
89pub fn load<P: AsRef<Path>>(path: P) -> Result<Image, Error> {
104 let mut offset = 0usize;
105 let mut buffer = Vec::new();
106 let mut file = File::open(path)?;
107
108 file.read_to_end(&mut buffer)?;
109 Image::read(&buffer, &mut offset)
110}