image_renderer/
color.rs

1//! 颜色类型定义
2//! 
3//! 提供 RGBA 颜色表示和常用颜色常量
4
5use crate::error::DrawError;
6
7/// RGBA 颜色类型
8#[derive(Debug, Clone, Copy, PartialEq)]
9pub struct Color {
10    /// 红色分量 (0-255)
11    pub r: u8,
12    /// 绿色分量 (0-255)
13    pub g: u8,
14    /// 蓝色分量 (0-255)
15    pub b: u8,
16    /// 透明度分量 (0-255),255 为完全不透明
17    pub a: u8,
18}
19
20impl Color {
21    /// 创建新的 RGBA 颜色
22    pub fn new(r: u8, g: u8, b: u8, a: u8) -> Self {
23        Self { r, g, b, a }
24    }
25
26    /// 创建不透明的 RGB 颜色
27    pub fn rgb(r: u8, g: u8, b: u8) -> Self {
28        Self::new(r, g, b, 255)
29    }
30
31    /// 创建带透明度的颜色
32    pub fn rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
33        Self::new(r, g, b, a)
34    }
35
36    /// 从十六进制字符串创建颜色
37    /// 支持格式: "#RGB", "#RGBA", "#RRGGBB", "#RRGGBBAA"
38    pub fn from_hex(hex: &str) -> Result<Self, DrawError> {
39        let hex = hex.trim_start_matches('#');
40        
41        match hex.len() {
42            3 => {
43                // #RGB
44                let r = u8::from_str_radix(&hex[0..1].repeat(2), 16)
45                    .map_err(|_| DrawError::InvalidColor(format!("Invalid hex color: #{}", hex)))?;
46                let g = u8::from_str_radix(&hex[1..2].repeat(2), 16)
47                    .map_err(|_| DrawError::InvalidColor(format!("Invalid hex color: #{}", hex)))?;
48                let b = u8::from_str_radix(&hex[2..3].repeat(2), 16)
49                    .map_err(|_| DrawError::InvalidColor(format!("Invalid hex color: #{}", hex)))?;
50                Ok(Self::rgb(r, g, b))
51            }
52            4 => {
53                // #RGBA
54                let r = u8::from_str_radix(&hex[0..1].repeat(2), 16)
55                    .map_err(|_| DrawError::InvalidColor(format!("Invalid hex color: #{}", hex)))?;
56                let g = u8::from_str_radix(&hex[1..2].repeat(2), 16)
57                    .map_err(|_| DrawError::InvalidColor(format!("Invalid hex color: #{}", hex)))?;
58                let b = u8::from_str_radix(&hex[2..3].repeat(2), 16)
59                    .map_err(|_| DrawError::InvalidColor(format!("Invalid hex color: #{}", hex)))?;
60                let a = u8::from_str_radix(&hex[3..4].repeat(2), 16)
61                    .map_err(|_| DrawError::InvalidColor(format!("Invalid hex color: #{}", hex)))?;
62                Ok(Self::rgba(r, g, b, a))
63            }
64            6 => {
65                // #RRGGBB
66                let r = u8::from_str_radix(&hex[0..2], 16)
67                    .map_err(|_| DrawError::InvalidColor(format!("Invalid hex color: #{}", hex)))?;
68                let g = u8::from_str_radix(&hex[2..4], 16)
69                    .map_err(|_| DrawError::InvalidColor(format!("Invalid hex color: #{}", hex)))?;
70                let b = u8::from_str_radix(&hex[4..6], 16)
71                    .map_err(|_| DrawError::InvalidColor(format!("Invalid hex color: #{}", hex)))?;
72                Ok(Self::rgb(r, g, b))
73            }
74            8 => {
75                // #RRGGBBAA
76                let r = u8::from_str_radix(&hex[0..2], 16)
77                    .map_err(|_| DrawError::InvalidColor(format!("Invalid hex color: #{}", hex)))?;
78                let g = u8::from_str_radix(&hex[2..4], 16)
79                    .map_err(|_| DrawError::InvalidColor(format!("Invalid hex color: #{}", hex)))?;
80                let b = u8::from_str_radix(&hex[4..6], 16)
81                    .map_err(|_| DrawError::InvalidColor(format!("Invalid hex color: #{}", hex)))?;
82                let a = u8::from_str_radix(&hex[6..8], 16)
83                    .map_err(|_| DrawError::InvalidColor(format!("Invalid hex color: #{}", hex)))?;
84                Ok(Self::rgba(r, g, b, a))
85            }
86            _ => Err(DrawError::InvalidColor(format!("Invalid hex color length: #{}", hex))),
87        }
88    }
89
90    /// 转换为 image 库的 Rgba 类型
91    pub fn to_rgba(&self) -> image::Rgba<u8> {
92        image::Rgba([self.r, self.g, self.b, self.a])
93    }
94
95    /// 从 image 库的 Rgba 类型创建
96    pub fn from_rgba(rgba: image::Rgba<u8>) -> Self {
97        Self::new(rgba[0], rgba[1], rgba[2], rgba[3])
98    }
99
100    // 常用颜色常量
101    pub const WHITE: Color = Color { r: 255, g: 255, b: 255, a: 255 };
102    pub const BLACK: Color = Color { r: 0, g: 0, b: 0, a: 255 };
103    pub const RED: Color = Color { r: 255, g: 0, b: 0, a: 255 };
104    pub const GREEN: Color = Color { r: 0, g: 255, b: 0, a: 255 };
105    pub const BLUE: Color = Color { r: 0, g: 0, b: 255, a: 255 };
106    pub const YELLOW: Color = Color { r: 255, g: 255, b: 0, a: 255 };
107    pub const CYAN: Color = Color { r: 0, g: 255, b: 255, a: 255 };
108    pub const MAGENTA: Color = Color { r: 255, g: 0, b: 255, a: 255 };
109    pub const TRANSPARENT: Color = Color { r: 0, g: 0, b: 0, a: 0 };
110    pub const GRAY: Color = Color { r: 128, g: 128, b: 128, a: 255 };
111}
112
113impl Default for Color {
114    fn default() -> Self {
115        Self::BLACK
116    }
117}
118
119impl From<(u8, u8, u8)> for Color {
120    fn from((r, g, b): (u8, u8, u8)) -> Self {
121        Self::rgb(r, g, b)
122    }
123}
124
125impl From<(u8, u8, u8, u8)> for Color {
126    fn from((r, g, b, a): (u8, u8, u8, u8)) -> Self {
127        Self::rgba(r, g, b, a)
128    }
129}
130
131impl From<image::Rgba<u8>> for Color {
132    fn from(rgba: image::Rgba<u8>) -> Self {
133        Self::from_rgba(rgba)
134    }
135}
136
137impl From<Color> for image::Rgba<u8> {
138    fn from(color: Color) -> Self {
139        color.to_rgba()
140    }
141}