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
77
78
79
80
81
82
83
84
85
86
87
88
use std::{num::NonZeroUsize, str::FromStr};
use anyhow::Error;
use image::{imageops::FilterType, DynamicImage};
use crate::{builtins::Arguments, ElementType, Tensor};
pub fn image(args: &Arguments, img: &DynamicImage) -> Result<Tensor, Error> {
let width: u32 = args.parse("width")?;
let height: u32 = args.parse("height")?;
let pixel_format: PixelFormat =
args.parse_or_default("pixel_format", PixelFormat::RGB8)?;
Ok(transform(img, width, height, pixel_format))
}
fn transform(
img: &DynamicImage,
width: u32,
height: u32,
pixel_format: PixelFormat,
) -> Tensor {
let resized = img.resize_exact(width, height, FilterType::CatmullRom);
let image = match pixel_format {
PixelFormat::RGB8 => DynamicImage::ImageRgb8(resized.to_rgb8()),
PixelFormat::BGR8 => DynamicImage::ImageBgr8(resized.to_bgr8()),
PixelFormat::GrayScale => DynamicImage::ImageLuma8(resized.to_luma8()),
};
let dimensions = [
NonZeroUsize::new(1).unwrap(),
NonZeroUsize::new(width as usize).unwrap(),
NonZeroUsize::new(height as usize).unwrap(),
NonZeroUsize::new(pixel_format.channels()).unwrap(),
];
let buffer = image.as_bytes().to_vec();
Tensor::new_raw(pixel_format.element_type(), dimensions.to_vec(), buffer)
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum PixelFormat {
RGB8,
BGR8,
GrayScale,
}
impl PixelFormat {
pub fn channels(self) -> usize {
match self {
PixelFormat::RGB8 | PixelFormat::BGR8 => 3,
PixelFormat::GrayScale => 1,
}
}
fn element_type(&self) -> ElementType {
match self {
PixelFormat::RGB8 | PixelFormat::BGR8 | PixelFormat::GrayScale => {
ElementType::U8
},
}
}
}
impl FromStr for PixelFormat {
type Err = UnknownPixelFormat;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"RGB8" => Ok(PixelFormat::RGB8),
"@PixelFormat::RGB" | "0" => Ok(PixelFormat::RGB8),
"@PixelFormat::BGR" | "1" => Ok(PixelFormat::BGR8),
"@PixelFormat::GrayScale" | "2" => Ok(PixelFormat::GrayScale),
_ => Err(UnknownPixelFormat),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, thiserror::Error)]
#[error("Unknown pixel format")]
pub struct UnknownPixelFormat;