1use crate::format::ImageFormat;
2
3#[must_use]
5pub fn detect_image_format_from_extension(extension: &str) -> ImageFormat {
6 match normalize_extension(extension) {
7 Some("png") => ImageFormat::Png,
8 Some("jpg") => ImageFormat::Jpeg,
9 Some("webp") => ImageFormat::Webp,
10 Some("gif") => ImageFormat::Gif,
11 Some("svg") => ImageFormat::Svg,
12 Some("ico") => ImageFormat::Ico,
13 Some("bmp") => ImageFormat::Bmp,
14 Some("tiff") => ImageFormat::Tiff,
15 Some("avif") => ImageFormat::Avif,
16 _ => ImageFormat::Unknown,
17 }
18}
19
20#[must_use]
22pub const fn image_extension(format: ImageFormat) -> Option<&'static str> {
23 match format {
24 ImageFormat::Png => Some("png"),
25 ImageFormat::Jpeg => Some("jpg"),
26 ImageFormat::Webp => Some("webp"),
27 ImageFormat::Gif => Some("gif"),
28 ImageFormat::Svg => Some("svg"),
29 ImageFormat::Ico => Some("ico"),
30 ImageFormat::Bmp => Some("bmp"),
31 ImageFormat::Tiff => Some("tiff"),
32 ImageFormat::Avif => Some("avif"),
33 ImageFormat::Unknown => None,
34 }
35}
36
37#[must_use]
39pub fn normalize_extension(extension: &str) -> Option<&'static str> {
40 let trimmed = extension.trim();
41 let stripped = trimmed.trim_start_matches('.');
42
43 if stripped.is_empty() {
44 return None;
45 }
46
47 match stripped.to_ascii_lowercase().as_str() {
48 "png" => Some("png"),
49 "jpg" | "jpeg" => Some("jpg"),
50 "webp" => Some("webp"),
51 "gif" => Some("gif"),
52 "svg" => Some("svg"),
53 "ico" => Some("ico"),
54 "bmp" => Some("bmp"),
55 "tif" | "tiff" => Some("tiff"),
56 "avif" => Some("avif"),
57 _ => None,
58 }
59}
60
61#[must_use]
63pub fn is_image_extension(extension: &str) -> bool {
64 normalize_extension(extension).is_some()
65}
66
67#[must_use]
69pub fn extension_from_filename(filename: &str) -> Option<&str> {
70 let last_segment = filename.rsplit(['/', '\\']).next()?;
71 let candidate = last_segment
72 .split(['?', '#'])
73 .next()
74 .unwrap_or(last_segment);
75 let (stem, extension) = candidate.rsplit_once('.')?;
76
77 if stem.is_empty() || extension.is_empty() {
78 return None;
79 }
80
81 Some(extension)
82}