-
-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathmod.rs
150 lines (142 loc) · 3.91 KB
/
mod.rs
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
pub mod geometry;
pub mod padding;
pub mod settings;
use std::fmt;
use crate::image::geometry::Geometry;
use image::{ExtendedColorType, Rgba};
#[cfg(feature = "ski")]
use {
imgref::{Img, ImgVec},
rgb::RGBA8,
};
/* Coefficients for transforming sRGB to CIE Y (luminance value) */
const SRGB_LUMA: [f32; 3] = [0.2126, 0.7152, 0.0722];
/* Image data and geometric properties */
#[derive(Clone)]
pub struct Image {
data: Vec<Rgba<u8>>,
alpha_channel: bool,
pub geometry: Geometry,
}
/* Debug implementation for programmer-facing output */
impl fmt::Debug for Image {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Image")
.field("data_len", &self.data.len())
.field("alpha_channel", &self.alpha_channel)
.field("geometry", &self.geometry)
.finish()
}
}
impl Image {
/**
* Create a new Image object.
*
* @param data
* @param alpha_channel
* @param geometry
* @return Image
*/
pub fn new(
data: Vec<Rgba<u8>>,
alpha_channel: bool,
geometry: Geometry,
) -> Self {
Self {
data,
alpha_channel,
geometry,
}
}
/**
* Get image data in the given color type.
*
* @param color_type
* @return Vector of u8
*/
pub fn get_data(&self, color_type: ExtendedColorType) -> Vec<u8> {
self.data.iter().fold(Vec::<u8>::new(), |mut data, rgba| {
let alpha = if self.alpha_channel { rgba[3] } else { 255 };
data.extend(&match color_type {
ExtendedColorType::L1 | ExtendedColorType::L8 => vec![{
let y = (SRGB_LUMA[0] * rgba[0] as f32
+ SRGB_LUMA[1] * rgba[1] as f32
+ SRGB_LUMA[2] * rgba[2] as f32) as u8;
if color_type == ExtendedColorType::L1 {
(y >> 7) * 0xFF
} else {
y
}
}],
ExtendedColorType::Rgb8 => vec![rgba[0], rgba[1], rgba[2]],
ExtendedColorType::Rgba16 => vec![
rgba[0], rgba[0], rgba[1], rgba[1], rgba[2], rgba[2], alpha,
alpha,
],
ExtendedColorType::Rgba32F => {
let mut data = Vec::new();
data.extend_from_slice(&(rgba[0] as f32 / 255.).to_ne_bytes());
data.extend_from_slice(&(rgba[1] as f32 / 255.).to_ne_bytes());
data.extend_from_slice(&(rgba[2] as f32 / 255.).to_ne_bytes());
data.extend_from_slice(&(alpha as f32 / 255.).to_ne_bytes());
data
}
_ => vec![rgba[0], rgba[1], rgba[2], alpha],
});
data
})
}
/**
* Get an Img Vector from the image data.
*
* @return ImgVec
*/
#[cfg(feature = "ski")]
pub fn get_img_vec(&self) -> ImgVec<RGBA8> {
Img::new(
self.data
.iter()
.fold(Vec::<RGBA8>::new(), |mut rgba8, rgba| {
let alpha = if self.alpha_channel { rgba[3] } else { 255 };
rgba8.extend(vec![RGBA8 {
r: rgba[0],
g: rgba[1],
b: rgba[2],
a: alpha,
}]);
rgba8
}),
self.geometry.width.try_into().unwrap_or_default(),
self.geometry.height.try_into().unwrap_or_default(),
)
}
}
#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn test_image() {
let geometry = Geometry::new(0, 0, 200, 200);
let data: [Rgba<u8>; 2] = [
Rgba::from([128, 128, 128, 0]),
Rgba::from([255, 255, 255, 0]),
];
let image = Image::new(data.to_vec(), false, geometry);
assert_eq!(
format!("{image:?}"),
"Image { data_len: 2, alpha_channel: false, \
geometry: Geometry { x: 0, y: 0, width: 200, height: 200 } }"
);
assert_eq!(2, image.get_data(ExtendedColorType::L1).len());
assert_eq!(2, image.get_data(ExtendedColorType::L8).len());
assert_eq!(6, image.get_data(ExtendedColorType::Rgb8).len());
assert_eq!(8, image.get_data(ExtendedColorType::Rgba8).len());
assert_eq!(16, image.get_data(ExtendedColorType::Rgba16).len());
assert_eq!(255, image.get_data(ExtendedColorType::L1)[0]);
assert_eq!(255, image.get_data(ExtendedColorType::L8)[1]);
assert_eq!(255, image.get_data(ExtendedColorType::Rgb8)[4]);
assert_eq!(255, image.get_data(ExtendedColorType::Rgba8)[5]);
assert_eq!(128, image.get_data(ExtendedColorType::Rgba16)[5]);
}
}