Newer
Older
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
use anyhow::bail;
use image::{
codecs::ico::{IcoEncoder, IcoFrame},
io::Reader as ImageReader,
ImageOutputFormat,
};
use std::{
io::{Cursor, ErrorKind},
path::Path,
};
use crate::resp::Response;
pub struct Favicon {
pub responses: Vec<(&'static str, Response)>,
}
impl Favicon {
pub fn load_if_exists<P: AsRef<Path>>(path: P) -> anyhow::Result<Option<Self>> {
let original = match ImageReader::open(path) {
Ok(x) => x,
Err(e) if e.kind() == ErrorKind::NotFound => {
return Ok(None);
}
Err(e) => {
return Err(e.into());
}
}
.decode()?;
if original.width() != original.height() {
bail!("Favicon must have the same width and height");
}
// 180x180 png
let mut png_180 = vec![];
original
.thumbnail(180, 180)
.write_to(&mut Cursor::new(&mut png_180), ImageOutputFormat::Png)?;
// 32x32 png
let mut png_32 = vec![];
original
.thumbnail(32, 32)
.write_to(&mut Cursor::new(&mut png_32), ImageOutputFormat::Png)?;
// 16x16 png
let mut png_16 = vec![];
original
.thumbnail(16, 16)
.write_to(&mut Cursor::new(&mut png_16), ImageOutputFormat::Png)?;
// 48x48, 32x32, 16x16 ico
let mut png_48 = vec![];
original
.thumbnail(48, 48)
.write_to(&mut Cursor::new(&mut png_48), ImageOutputFormat::Png)?;
let ico_48 = IcoFrame::with_encoded(png_48, 48, 48, original.color())?;
let ico_32 = IcoFrame::with_encoded(&png_32, 32, 32, original.color())?;
let ico_16 = IcoFrame::with_encoded(&png_16, 16, 16, original.color())?;
let mut ico = vec![];
IcoEncoder::new(&mut ico).encode_images(&[ico_48, ico_32, ico_16])?;
let responses = vec![
("apple-touch-icon.png", Response::png(png_180)),
("favicon-32x32.png", Response::png(png_32)),
("favicon-16x16.png", Response::png(png_16)),
("favicon.ico", Response::ico(ico)),
];
Ok(Some(Self { responses }))
}
pub fn html(&self) -> &'static str {
r#"<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"><link rel="shortcut icon" href="/favicon.ico">