1//! Pixel color types.
2//!
3//! This module contains structs for commonly used pixel color formats and
4//! conversions between them. The [`raw` module] provides additional functions
5//! to convert colors to and from raw data for use with images and displays.
6//!
7//! # Implementing custom color types
8//!
9//! Custom color types can be added by implementing the [`PixelColor`] trait.
10//! The following example shows how to implement a new color type for a
11//! 3 color EPD display.
12//!
13//! ```
14//! use embedded_graphics::{
15//! geometry::Size, prelude::*, primitives::{Rectangle, PrimitiveStyle},
16//! };
17//!
18//! /// Color with 3 states.
19//! #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
20//! pub enum EpdColor {
21//! White,
22//! Black,
23//! Red,
24//! }
25//!
26//! /// The `Raw` can be is set to `()` because `EpdColor` doesn't need to be
27//! /// converted to raw data for the display and isn't stored in images.
28//! impl PixelColor for EpdColor {
29//! type Raw = ();
30//! }
31//!
32//! /// Mock EPD display.
33//! pub struct EpdDisplay {}
34//!
35//! impl DrawTarget for EpdDisplay {
36//! type Color = EpdColor;
37//! type Error = core::convert::Infallible;
38//!
39//! fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
40//! where
41//! I: IntoIterator<Item = Pixel<Self::Color>>,
42//! {
43//! for Pixel(point, color) in pixels.into_iter() {
44//! match color {
45//! EpdColor::White => {} // draw white pixel at `point`
46//! EpdColor::Black => {} // draw black pixel at `point`
47//! EpdColor::Red => {} // draw red pixel at `point`
48//! }
49//! }
50//!
51//! Ok(())
52//! }
53//! }
54//!
55//! impl OriginDimensions for EpdDisplay {
56//! fn size(&self) -> Size {
57//! Size::new(300, 300)
58//! }
59//! }
60//!
61//! let mut display = EpdDisplay {};
62//!
63//! Rectangle::new(Point::new(0, 0), Size::new(100, 100))
64//! .into_styled(PrimitiveStyle::with_fill(EpdColor::White))
65//! .draw(&mut display)?;
66//!
67//! Rectangle::new(Point::new(100, 0), Size::new(100, 100))
68//! .into_styled(PrimitiveStyle::with_fill(EpdColor::Black))
69//! .draw(&mut display)?;
70//!
71//! Rectangle::new(Point::new(200, 0), Size::new(100, 100))
72//! .into_styled(PrimitiveStyle::with_fill(EpdColor::Red))
73//! .draw(&mut display)?;
74//! # Ok::<(), core::convert::Infallible>(())
75//! ```
76//!
77//! The implementation of the [`DrawTarget`] trait uses a `match` statement to
78//! draw the specified color and doesn't depend on the raw data conversions,
79//! see the [`raw` module] documentation for an example that uses this feature.
80//!
81//! [`DrawTarget`]: super::draw_target::DrawTarget
82//! [`Raw`]: PixelColor::Raw
83//! [`raw` module]: raw
84
85mod binary_color;
86mod conversion;
87mod gray_color;
88pub mod raw;
89mod rgb_color;
90mod web_colors;
91
92pub use binary_color::*;
93pub use gray_color::*;
94use raw::RawData;
95pub use rgb_color::*;
96pub use web_colors::WebColors;
97
98/// Pixel color trait.
99///
100/// This trait is used to represent types that can be used in drawing methods.
101///
102/// See the [module-level documentation] for more details.
103///
104/// [module-level documentation]: self
105pub trait PixelColor: Copy + PartialEq {
106 /// Raw data type.
107 ///
108 /// Specifies the raw storage type that can be used to represent this color.
109 ///
110 /// See the [`raw` module documentation] for more details.
111 ///
112 /// [`raw` module documentation]: raw
113 type Raw: RawData;
114}
115
116/// Convert a [`PixelColor`] into its underlying storage type
117///
118/// This trait provides the `into_storage` method for implementors of [`PixelColor`]. This method
119/// exposes the underlying storage value of a pixel color type.
120///
121/// # Examples
122///
123/// ## Get the `u16` representing an `Rgb565` color
124///
125/// This example converts an [`Rgb565`] color into its underlying `u16` representation.
126///
127/// ```rust
128/// use embedded_graphics::{pixelcolor::Rgb565, prelude::*};
129///
130/// let color = Rgb565::new(0x1f, 0x00, 0x0a);
131///
132/// let raw = color.into_storage();
133///
134/// assert_eq!(raw, 0b11111_000000_01010u16);
135/// ```
136///
137pub trait IntoStorage {
138 /// The underlying storage type for the pixel color
139 type Storage;
140
141 /// Convert the `PixelColor` into its raw storage form
142 fn into_storage(self) -> Self::Storage;
143}
144
145impl<C> IntoStorage for C
146where
147 C: PixelColor,
148 C::Raw: From<C>,
149{
150 type Storage = <<C as PixelColor>::Raw as RawData>::Storage;
151
152 fn into_storage(self) -> Self::Storage {
153 C::Raw::from(self).into_inner()
154 }
155}
156