11 个版本
0.3.3 | 2024年1月31日 |
---|---|
0.3.2 | 2022年9月20日 |
0.3.1 | 2022年6月19日 |
0.3.0 | 2022年1月3日 |
0.1.4 | 2021年4月30日 |
#152 在 图像
用于 2 crate
2MB
1.5K SLoC
包含 (ELF exe/lib, 3.5MB) gamma8, (ELF exe/lib, 3.5MB) tmp
提供 sRGB 原语和常量
该 crate 提供了在 sRGB 颜色空间中操作颜色的原语。
具体来说,它提供了在 sRGB、线性 sRGB 和 XYZ 颜色空间之间进行转换的函数;公开了 D65 标准白点的定义以及 XYZ 转换矩阵;最后提供了处理 Rec.709 组件编码的函数。
它提供了与 sRGB 标准一起工作的低级原语。这些原语可以由其他需要将 sRGB 和其他颜色空间之间进行转换或混合 sRGB 颜色的库使用。
主模块提供的函数实现了 sRGB 和 XYZ 颜色空间之间的转换。在 gamma
子模块中,提供了 gamma 压缩和扩展函数,这些函数操作单个颜色分量。最后,[xyz
] 子模块提供了在线性 sRGB 和 XYZ 颜色空间之间转换的函数以及公开这些函数使用的矩阵常量。
The crate includes highly-optimised 8-bit gamma functions both when converting from an 8-bit compressed value to a floating point linear value as well as conversion in the opposite direction. The latter is over two and a half times faster than naïve implementation of the gamma compression formula.
用法
使用此包与 Cargo 项目一起时,需要在 Cargo.toml 中添加单个依赖项
[dependencies]
srgb = "0.3"
添加依赖项后,现在可以编写将 sRGB 颜色转换为其他颜色空间的程序
#[derive(Debug)]
struct RGBColour(u8, u8, u8);
impl RGBColour {
fn parse(value: &str) -> Option<Self> {
value.strip_prefix('#')
.and_then(|v| (v.len() == 6 && !v.starts_with('+')).then(|| v))
.and_then(|v| u32::from_str_radix(v, 16).ok())
.map(|v| Self((v >> 16) as u8, (v >> 8) as u8, v as u8))
}
fn normalise(&self) -> (f32, f32, f32) {
let [r, g, b] = srgb::normalised_from_u8([self.0, self.1, self.2]);
(r, g, b)
// Alternatively divide each component by 255 manually
}
fn expand_gamma(&self) -> (f32, f32, f32) {
(
srgb::gamma::expand_u8(self.0),
srgb::gamma::expand_u8(self.1),
srgb::gamma::expand_u8(self.2),
)
// Alternatively a convenience function is provided as well:
// let [r, g, b] = srgb::gamma::linear_from_u8([self.0, self.1, self.2]);
// (r, g, b)
}
fn to_xyz(&self) -> (f32, f32, f32) {
let linear = srgb::gamma::linear_from_u8([self.0, self.1, self.2]);
let [r, g, b] = srgb::xyz::xyz_from_linear(linear);
(r, g, b)
// Alternatively, if a custom matrix multiplication is available:
// let [r, g, b] = matrix_product(
// srgb::xyz::XYZ_FROM_SRGB_MATRIX, linear);
}
}
fn main() {
for arg in std::env::args().into_iter().skip(1) {
if let Some(rgb) = RGBColour::parse(&arg[..]) {
println!("sRGB: {:?}", rgb);
println!("Normalised: {:?}", rgb.normalise());
println!("Linear: {:?}", rgb.expand_gamma());
println!("XYZ: {:?}", rgb.to_xyz());
} else {
eprintln!("expected ‘#rrggbb’ but got {}", arg);
}
}
}
rgb
crate 支持
这个crate没有显式支持rgb
crate。然而,由于所有接受(s)RGB颜色作为参数的函数都接受impl Into<[f32; 3]>
或impl Into<[u8; 3]>
,因此可以将RGB
结构体传递给它们。类似地,这些函数返回[f32; 3]
或[u8; 3]
,这些可以转换为RGB
结构体。
extern crate rgb;
use rgb::ComponentMap;
fn parse(value: &str) -> Option<rgb::RGB8> {
value.strip_prefix('#')
.and_then(|v| (v.len() == 6 && !v.starts_with('+')).then(|| v))
.and_then(|v| u32::from_str_radix(v, 16).ok())
.map(|v| (rgb::RGB::new((v >> 16) as u8, (v >> 8) as u8, v as u8)))
}
fn normalise(colour: rgb::RGB8) -> rgb::RGB<f32> {
srgb::normalised_from_u8(colour).into()
}
fn expand_gamma(colour: rgb::RGB8) -> rgb::RGB<f32> {
colour.map(srgb::gamma::expand_u8)
}
fn to_xyz(colour: rgb::RGB8) -> (f32, f32, f32) {
let linear = srgb::gamma::linear_from_u8(colour);
let [r, g, b] = srgb::xyz::xyz_from_linear(linear);
(r, g, b)
}
fn main() {
for arg in std::env::args().into_iter().skip(1) {
if let Some(colour) = parse(&arg[..]) {
println!("sRGB: {:?}", colour);
println!("Normalised: {:?}", normalise(colour));
println!("Linear: {:?}", expand_gamma(colour));
println!("XYZ: {:?}", to_xyz(colour));
} else {
eprintln!("expected ‘#rrggbb’ but got {}", arg);
}
}
}