imageinfo/formats/
try_cur_ico.rs

1use crate::{ImageFormat, ImageInfo, ImageInfoError, ImageInfoResult, ImageSize, ReadInterface};
2use std::io::{BufRead, Seek};
3
4pub fn try_cur_ico<R>(ri: &mut ReadInterface<R>, length: usize) -> ImageInfoResult<ImageInfo>
5where
6    R: BufRead + Seek,
7{
8    if length < 6 {
9        return Err(ImageInfoError::UnrecognizedFormat);
10    }
11    let buffer = ri.read(0, 6)?;
12
13    let mut ret =
14        // ico type == 1
15        if buffer.cmp(0, 4, b"\x00\x00\x01\x00") {
16            ImageInfo {
17                format: ImageFormat::ICO,
18                ext: "ico",
19                full_ext: "ico",
20                mimetype: "image/ico",
21                size: ImageSize {
22                    width: 0,
23                    height: 0,
24                },
25                entry_sizes: vec![],
26            }
27        }
28        // cur type == 2
29        else if buffer.cmp(0, 4, b"\x00\x00\x02\x00") {
30            ImageInfo {
31                format: ImageFormat::CUR,
32                ext: "cur",
33                full_ext: "cur",
34                mimetype: "image/cur",
35                size: ImageSize {
36                    width: 0,
37                    height: 0,
38                },
39                entry_sizes: vec![],
40            }
41        }
42        // invalid
43        else {
44            return Err(ImageInfoError::UnrecognizedFormat);
45        };
46
47    let entry_count = buffer.read_u16_le(4) as usize;
48    if entry_count == 0 {
49        return Err(ImageInfoError::UnrecognizedFormat);
50    }
51
52    let entry_size = 16;
53    let entry_total_size = entry_count * entry_size;
54
55    let mut offset = 6usize;
56    if length < offset + entry_total_size {
57        return Err(ImageInfoError::UnrecognizedFormat);
58    }
59
60    let buffer = ri.read(offset, entry_total_size)?;
61    offset += entry_total_size;
62
63    for i in 0..entry_count {
64        let width = buffer.read_u8(i * entry_size);
65        let height = buffer.read_u8(i * entry_size + 1);
66        let width = if width == 0 { 256i64 } else { width as i64 };
67        let height = if height == 0 { 256i64 } else { height as i64 };
68        ret.entry_sizes.push(ImageSize { width, height });
69
70        let bytes = buffer.read_i32_le(i * entry_size + 8) as usize;
71        offset += bytes;
72    }
73
74    if let Some(size) = ret.entry_sizes.first() {
75        ret.size.width = size.width;
76        ret.size.height = size.height;
77    } else {
78        return Err(ImageInfoError::UnrecognizedFormat);
79    }
80
81    Ok(ret)
82}