2 个版本
0.1.1 | 2020 年 7 月 19 日 |
---|---|
0.1.0 | 2020 年 7 月 18 日 |
#303 在 图像
每月 353 次下载
在 4 crate 中使用
520KB
14K SLoC
Prisma - Rust 颜色库
目录
概述
Prisma 是一个 Rust 库,旨在提供一套全面的颜色表示、操作、转换和算法,易于用于各种级别的项目。Prisma 遵循“选择”复杂性的模式,这意味着如果您只想有一个库将 Rgb 转换为 Hsv 并返回,Prisma 将允许您在不了解整个颜色科学领域的情况下以最小的知识完成它。但是,如果您需要访问 CIE 空间或进行颜色空间转换,Prisma 也提供该功能,并使用包装器来使用类型系统强制执行有效性。
Prisma 致力于成为 Rust 中颜色转换和颜色科学的必备资源。它目前正在开发中,任何贡献或功能请求都受到欢迎。
颜色模型
目前 Prisma 支持以下颜色模型
设备相关
Rgb
- 显示的标准颜色模型Rgi
- 从 Rgb 构造的色度模型,将色度和亮度分离Hsv
- 色调、饱和度、值:一个更直观的极坐标 Rgb 模型Hsl
- 色调、饱和度、亮度:Hsv 的替代品,履行类似角色Hsi
- 色调、饱和度、强度:一个基于色调且无失真的模型eHsi
- 对Hsi
的扩展,重新调整饱和度以避免在 RGB 中超出色域Hwb
- 色调、白度、黑度:一个基于色调的模型,便于用户选择颜色YCbCr
- 用于显示和广播的各种 YUV 和 YIQ 模型的表示
设备无关
Xyz
- 作为其他颜色空间定义基准的“父”绝对颜色空间Lms
- 模拟人类锥体反应的颜色空间Lab
- XYZ 的均匀感知颜色空间转换Lchab
- Lab 的极坐标变换。类似于 Hsl 的均匀感知模拟Luv
- 在照明计算中有用的替代均匀感知颜色空间Lchuv
- Luv 的极坐标变换
Prisma 还通过 Alpha
类型支持带有 Alpha 通道的颜色空间。
为什么选择 Prisma?
目前,有两个主要的 Rust 颜色库
-
color --
color
是一个非常旧的库,已经几年没有更新了。虽然它可以通过几个颜色空间进行转换,并且易于使用,但它具有非常有限的功能集。 -
palette --
palette
具有更多功能,并且可以进入一些 CIE 空间,但要求所有计算都在线性编码中进行是一个严重的缺点,因为如果你只想在游戏中获得一个好看的渐变,线性 Hsv 是 不会 给你那个的。它还建立在预定义的模型之上,不支持动态配置。prisma
支持更多的颜色空间,以及多种编码和可以在运行时构建的空间。prisma
还不需要你指定颜色空间,因为大多数应用程序实际上并不关心,并且使用设备颜色空间或 sRgb。
Prisma 旨在支持上述库的所有功能,同时让用户决定他们需要多少复杂性。
示例导览
从 Rgb 转换到 Hsv,操作色调,然后再转换回来
#[macro_use] extern crate approx;
extern crate angular_units as angle;
# extern crate prisma;
use prisma::{Rgb, Hsv, FromColor};
use angle::Deg;
let rgb = Rgb::new(0.5, 0.75, 1.0);
let mut hsv = Hsv::from_color(&rgb);
hsv.set_hue(Deg(180.0));
let rgb = Rgb::from_color(&hsv);
assert_relative_eq!(rgb, Rgb::new(0.5, 1.0, 1.0), epsilon=1e-6);
在 Hsl 之间插值两种颜色。
#[macro_use] extern crate approx;
extern crate angular_units as angle;
# extern crate prisma;
use prisma::{Rgb, Hsl, FromColor, Lerp};
use angle::Deg;
let rgb1 = Rgb::new(0.8, 0.25, 0.0f32);
let rgb2 = Rgb::new(0.5, 0.66, 1.0);
// Specify the hue channel should use degrees
let hsl1: Hsl<_, Deg<f32>> = Hsl::from_color(&rgb1);
let hsl2 = Hsl::from_color(&rgb2);
// Note that hue channels will interpolate in the shortest direction. This is usually
// the expected behavior, but you can always go forward with `lerp_flat`.
let rgb_out = Rgb::from_color(&hsl1.lerp(&hsl2, 0.35));
assert_relative_eq!(rgb_out, Rgb::new(1.0, 0.045, 0.62648), epsilon=1e-4);
从 Rgb 转换到 Rgb
#[macro_use] extern crate approx;
# extern crate prisma;
use prisma::Rgb;
let rgb_in = Rgb::new(100, 200, 255u8);
let rgb_out: Rgb<f32> = rgb_in.color_cast();
assert_relative_eq!(rgb_out, Rgb::new(0.39216, 0.78431, 1.0), epsilon=1e-4);
将 sRgb 编码转换为线性编码 Rgb
#[macro_use] extern crate approx;
# extern crate prisma;
use prisma::Rgb;
use prisma::encoding::{EncodableColor, TranscodableColor, SrgbEncoding};
// This returns a `EncodedColor<Rgb<f32>, SrgbEncoding>`
// Note: no encodind is done. `srgb_encoded` says that this value is already in sRgb encoding.
let rgb_srgb = Rgb::new(0.5, 1.0, 0.25f32).srgb_encoded();
// Decode goes from an encoding to linear.
let rgb_linear = rgb_srgb.clone().decode();
assert_relative_eq!(rgb_linear, Rgb::new(0.21404, 1.0, 0.05088).linear(), epsilon=1e-4);
// We can then go back with `encode`
let rgb_out = rgb_linear.encode(SrgbEncoding);
assert_relative_eq!(rgb_out, rgb_srgb, epsilon=1e-6);
转换为 XYZ
#[macro_use] extern crate approx;
# extern crate prisma;
use prisma::{Rgb, Xyz};
use prisma::encoding::{EncodableColor, TranscodableColor};
use prisma::color_space::{ColorSpace, EncodedColorSpace, NamedColorSpace, ConvertToXyz};
use prisma::color_space::presets::sRgb;
let rgb = Rgb::new(0.25, 0.5, 0.75f32).srgb_encoded();
let color_space = sRgb::get_color_space();
// In this case, since rgb and color_space know their own encodings, the conversion to linear
// is automatic.
let xyz = color_space.convert_to_xyz(&rgb);
assert_relative_eq!(xyz, Xyz::new(0.191803, 0.201605, 0.523050), epsilon=1e-5);
依赖项
~225KB