1 | use std::ops::{Index, IndexMut}; |
2 | |
3 | use num_traits::{NumCast, ToPrimitive, Zero}; |
4 | |
5 | use crate::traits::{Enlargeable, Pixel, Primitive}; |
6 | |
7 | /// An enumeration over supported color types and bit depths |
8 | #[derive (Copy, PartialEq, Eq, Debug, Clone, Hash)] |
9 | #[non_exhaustive ] |
10 | pub enum ColorType { |
11 | /// Pixel is 8-bit luminance |
12 | L8, |
13 | /// Pixel is 8-bit luminance with an alpha channel |
14 | La8, |
15 | /// Pixel contains 8-bit R, G and B channels |
16 | Rgb8, |
17 | /// Pixel is 8-bit RGB with an alpha channel |
18 | Rgba8, |
19 | |
20 | /// Pixel is 16-bit luminance |
21 | L16, |
22 | /// Pixel is 16-bit luminance with an alpha channel |
23 | La16, |
24 | /// Pixel is 16-bit RGB |
25 | Rgb16, |
26 | /// Pixel is 16-bit RGBA |
27 | Rgba16, |
28 | |
29 | /// Pixel is 32-bit float RGB |
30 | Rgb32F, |
31 | /// Pixel is 32-bit float RGBA |
32 | Rgba32F, |
33 | } |
34 | |
35 | impl ColorType { |
36 | /// Returns the number of bytes contained in a pixel of `ColorType` ```c``` |
37 | pub fn bytes_per_pixel(self) -> u8 { |
38 | match self { |
39 | ColorType::L8 => 1, |
40 | ColorType::L16 | ColorType::La8 => 2, |
41 | ColorType::Rgb8 => 3, |
42 | ColorType::Rgba8 | ColorType::La16 => 4, |
43 | ColorType::Rgb16 => 6, |
44 | ColorType::Rgba16 => 8, |
45 | ColorType::Rgb32F => 3 * 4, |
46 | ColorType::Rgba32F => 4 * 4, |
47 | } |
48 | } |
49 | |
50 | /// Returns if there is an alpha channel. |
51 | pub fn has_alpha(self) -> bool { |
52 | use ColorType::*; |
53 | match self { |
54 | L8 | L16 | Rgb8 | Rgb16 | Rgb32F => false, |
55 | La8 | Rgba8 | La16 | Rgba16 | Rgba32F => true, |
56 | } |
57 | } |
58 | |
59 | /// Returns false if the color scheme is grayscale, true otherwise. |
60 | pub fn has_color(self) -> bool { |
61 | use ColorType::*; |
62 | match self { |
63 | L8 | L16 | La8 | La16 => false, |
64 | Rgb8 | Rgb16 | Rgba8 | Rgba16 | Rgb32F | Rgba32F => true, |
65 | } |
66 | } |
67 | |
68 | /// Returns the number of bits contained in a pixel of `ColorType` ```c``` (which will always be |
69 | /// a multiple of 8). |
70 | pub fn bits_per_pixel(self) -> u16 { |
71 | <u16 as From<u8>>::from(self.bytes_per_pixel()) * 8 |
72 | } |
73 | |
74 | /// Returns the number of color channels that make up this pixel |
75 | pub fn channel_count(self) -> u8 { |
76 | let e: ExtendedColorType = self.into(); |
77 | e.channel_count() |
78 | } |
79 | } |
80 | |
81 | /// An enumeration of color types encountered in image formats. |
82 | /// |
83 | /// This is not exhaustive over all existing image formats but should be granular enough to allow |
84 | /// round tripping of decoding and encoding as much as possible. The variants will be extended as |
85 | /// necessary to enable this. |
86 | /// |
87 | /// Another purpose is to advise users of a rough estimate of the accuracy and effort of the |
88 | /// decoding from and encoding to such an image format. |
89 | #[derive (Copy, PartialEq, Eq, Debug, Clone, Hash)] |
90 | #[non_exhaustive ] |
91 | pub enum ExtendedColorType { |
92 | /// Pixel is 8-bit alpha |
93 | A8, |
94 | /// Pixel is 1-bit luminance |
95 | L1, |
96 | /// Pixel is 1-bit luminance with an alpha channel |
97 | La1, |
98 | /// Pixel contains 1-bit R, G and B channels |
99 | Rgb1, |
100 | /// Pixel is 1-bit RGB with an alpha channel |
101 | Rgba1, |
102 | /// Pixel is 2-bit luminance |
103 | L2, |
104 | /// Pixel is 2-bit luminance with an alpha channel |
105 | La2, |
106 | /// Pixel contains 2-bit R, G and B channels |
107 | Rgb2, |
108 | /// Pixel is 2-bit RGB with an alpha channel |
109 | Rgba2, |
110 | /// Pixel is 4-bit luminance |
111 | L4, |
112 | /// Pixel is 4-bit luminance with an alpha channel |
113 | La4, |
114 | /// Pixel contains 4-bit R, G and B channels |
115 | Rgb4, |
116 | /// Pixel is 4-bit RGB with an alpha channel |
117 | Rgba4, |
118 | /// Pixel is 8-bit luminance |
119 | L8, |
120 | /// Pixel is 8-bit luminance with an alpha channel |
121 | La8, |
122 | /// Pixel contains 8-bit R, G and B channels |
123 | Rgb8, |
124 | /// Pixel is 8-bit RGB with an alpha channel |
125 | Rgba8, |
126 | /// Pixel is 16-bit luminance |
127 | L16, |
128 | /// Pixel is 16-bit luminance with an alpha channel |
129 | La16, |
130 | /// Pixel contains 16-bit R, G and B channels |
131 | Rgb16, |
132 | /// Pixel is 16-bit RGB with an alpha channel |
133 | Rgba16, |
134 | /// Pixel contains 8-bit B, G and R channels |
135 | Bgr8, |
136 | /// Pixel is 8-bit BGR with an alpha channel |
137 | Bgra8, |
138 | |
139 | // TODO f16 types? |
140 | /// Pixel is 32-bit float RGB |
141 | Rgb32F, |
142 | /// Pixel is 32-bit float RGBA |
143 | Rgba32F, |
144 | |
145 | /// Pixel is 8-bit CMYK |
146 | Cmyk8, |
147 | |
148 | /// Pixel is of unknown color type with the specified bits per pixel. This can apply to pixels |
149 | /// which are associated with an external palette. In that case, the pixel value is an index |
150 | /// into the palette. |
151 | Unknown(u8), |
152 | } |
153 | |
154 | impl ExtendedColorType { |
155 | /// Get the number of channels for colors of this type. |
156 | /// |
157 | /// Note that the `Unknown` variant returns a value of `1` since pixels can only be treated as |
158 | /// an opaque datum by the library. |
159 | pub fn channel_count(self) -> u8 { |
160 | match self { |
161 | ExtendedColorType::A8 |
162 | | ExtendedColorType::L1 |
163 | | ExtendedColorType::L2 |
164 | | ExtendedColorType::L4 |
165 | | ExtendedColorType::L8 |
166 | | ExtendedColorType::L16 |
167 | | ExtendedColorType::Unknown(_) => 1, |
168 | ExtendedColorType::La1 |
169 | | ExtendedColorType::La2 |
170 | | ExtendedColorType::La4 |
171 | | ExtendedColorType::La8 |
172 | | ExtendedColorType::La16 => 2, |
173 | ExtendedColorType::Rgb1 |
174 | | ExtendedColorType::Rgb2 |
175 | | ExtendedColorType::Rgb4 |
176 | | ExtendedColorType::Rgb8 |
177 | | ExtendedColorType::Rgb16 |
178 | | ExtendedColorType::Rgb32F |
179 | | ExtendedColorType::Bgr8 => 3, |
180 | ExtendedColorType::Rgba1 |
181 | | ExtendedColorType::Rgba2 |
182 | | ExtendedColorType::Rgba4 |
183 | | ExtendedColorType::Rgba8 |
184 | | ExtendedColorType::Rgba16 |
185 | | ExtendedColorType::Rgba32F |
186 | | ExtendedColorType::Bgra8 |
187 | | ExtendedColorType::Cmyk8 => 4, |
188 | } |
189 | } |
190 | } |
191 | impl From<ColorType> for ExtendedColorType { |
192 | fn from(c: ColorType) -> Self { |
193 | match c { |
194 | ColorType::L8 => ExtendedColorType::L8, |
195 | ColorType::La8 => ExtendedColorType::La8, |
196 | ColorType::Rgb8 => ExtendedColorType::Rgb8, |
197 | ColorType::Rgba8 => ExtendedColorType::Rgba8, |
198 | ColorType::L16 => ExtendedColorType::L16, |
199 | ColorType::La16 => ExtendedColorType::La16, |
200 | ColorType::Rgb16 => ExtendedColorType::Rgb16, |
201 | ColorType::Rgba16 => ExtendedColorType::Rgba16, |
202 | ColorType::Rgb32F => ExtendedColorType::Rgb32F, |
203 | ColorType::Rgba32F => ExtendedColorType::Rgba32F, |
204 | } |
205 | } |
206 | } |
207 | |
208 | macro_rules! define_colors { |
209 | {$( |
210 | $(#[$doc:meta])* |
211 | pub struct $ident:ident<T: $($bound:ident)*>([T; $channels:expr, $alphas:expr]) |
212 | = $interpretation:literal; |
213 | )*} => { |
214 | |
215 | $( // START Structure definitions |
216 | |
217 | $(#[$doc])* |
218 | #[derive(PartialEq, Eq, Clone, Debug, Copy, Hash)] |
219 | #[repr(C)] |
220 | #[allow(missing_docs)] |
221 | pub struct $ident<T> (pub [T; $channels]); |
222 | |
223 | impl<T: $($bound+)*> Pixel for $ident<T> { |
224 | type Subpixel = T; |
225 | |
226 | const CHANNEL_COUNT: u8 = $channels; |
227 | |
228 | #[inline(always)] |
229 | fn channels(&self) -> &[T] { |
230 | &self.0 |
231 | } |
232 | |
233 | #[inline(always)] |
234 | fn channels_mut(&mut self) -> &mut [T] { |
235 | &mut self.0 |
236 | } |
237 | |
238 | const COLOR_MODEL: &'static str = $interpretation; |
239 | |
240 | fn channels4(&self) -> (T, T, T, T) { |
241 | const CHANNELS: usize = $channels; |
242 | let mut channels = [T::DEFAULT_MAX_VALUE; 4]; |
243 | channels[0..CHANNELS].copy_from_slice(&self.0); |
244 | (channels[0], channels[1], channels[2], channels[3]) |
245 | } |
246 | |
247 | fn from_channels(a: T, b: T, c: T, d: T,) -> $ident<T> { |
248 | const CHANNELS: usize = $channels; |
249 | *<$ident<T> as Pixel>::from_slice(&[a, b, c, d][..CHANNELS]) |
250 | } |
251 | |
252 | fn from_slice(slice: &[T]) -> &$ident<T> { |
253 | assert_eq!(slice.len(), $channels); |
254 | unsafe { &*(slice.as_ptr() as *const $ident<T>) } |
255 | } |
256 | fn from_slice_mut(slice: &mut [T]) -> &mut $ident<T> { |
257 | assert_eq!(slice.len(), $channels); |
258 | unsafe { &mut *(slice.as_mut_ptr() as *mut $ident<T>) } |
259 | } |
260 | |
261 | fn to_rgb(&self) -> Rgb<T> { |
262 | let mut pix = Rgb([Zero::zero(), Zero::zero(), Zero::zero()]); |
263 | pix.from_color(self); |
264 | pix |
265 | } |
266 | |
267 | fn to_rgba(&self) -> Rgba<T> { |
268 | let mut pix = Rgba([Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero()]); |
269 | pix.from_color(self); |
270 | pix |
271 | } |
272 | |
273 | fn to_luma(&self) -> Luma<T> { |
274 | let mut pix = Luma([Zero::zero()]); |
275 | pix.from_color(self); |
276 | pix |
277 | } |
278 | |
279 | fn to_luma_alpha(&self) -> LumaA<T> { |
280 | let mut pix = LumaA([Zero::zero(), Zero::zero()]); |
281 | pix.from_color(self); |
282 | pix |
283 | } |
284 | |
285 | fn map<F>(& self, f: F) -> $ident<T> where F: FnMut(T) -> T { |
286 | let mut this = (*self).clone(); |
287 | this.apply(f); |
288 | this |
289 | } |
290 | |
291 | fn apply<F>(&mut self, mut f: F) where F: FnMut(T) -> T { |
292 | for v in &mut self.0 { |
293 | *v = f(*v) |
294 | } |
295 | } |
296 | |
297 | fn map_with_alpha<F, G>(&self, f: F, g: G) -> $ident<T> where F: FnMut(T) -> T, G: FnMut(T) -> T { |
298 | let mut this = (*self).clone(); |
299 | this.apply_with_alpha(f, g); |
300 | this |
301 | } |
302 | |
303 | fn apply_with_alpha<F, G>(&mut self, mut f: F, mut g: G) where F: FnMut(T) -> T, G: FnMut(T) -> T { |
304 | const ALPHA: usize = $channels - $alphas; |
305 | for v in self.0[..ALPHA].iter_mut() { |
306 | *v = f(*v) |
307 | } |
308 | // The branch of this match is `const`. This way ensures that no subexpression fails the |
309 | // `const_err` lint (the expression `self.0[ALPHA]` would). |
310 | if let Some(v) = self.0.get_mut(ALPHA) { |
311 | *v = g(*v) |
312 | } |
313 | } |
314 | |
315 | fn map2<F>(&self, other: &Self, f: F) -> $ident<T> where F: FnMut(T, T) -> T { |
316 | let mut this = (*self).clone(); |
317 | this.apply2(other, f); |
318 | this |
319 | } |
320 | |
321 | fn apply2<F>(&mut self, other: &$ident<T>, mut f: F) where F: FnMut(T, T) -> T { |
322 | for (a, &b) in self.0.iter_mut().zip(other.0.iter()) { |
323 | *a = f(*a, b) |
324 | } |
325 | } |
326 | |
327 | fn invert(&mut self) { |
328 | Invert::invert(self) |
329 | } |
330 | |
331 | fn blend(&mut self, other: &$ident<T>) { |
332 | Blend::blend(self, other) |
333 | } |
334 | } |
335 | |
336 | impl<T> Index<usize> for $ident<T> { |
337 | type Output = T; |
338 | #[inline(always)] |
339 | fn index(&self, _index: usize) -> &T { |
340 | &self.0[_index] |
341 | } |
342 | } |
343 | |
344 | impl<T> IndexMut<usize> for $ident<T> { |
345 | #[inline(always)] |
346 | fn index_mut(&mut self, _index: usize) -> &mut T { |
347 | &mut self.0[_index] |
348 | } |
349 | } |
350 | |
351 | impl<T> From<[T; $channels]> for $ident<T> { |
352 | fn from(c: [T; $channels]) -> Self { |
353 | Self(c) |
354 | } |
355 | } |
356 | |
357 | )* // END Structure definitions |
358 | |
359 | } |
360 | } |
361 | |
362 | define_colors! { |
363 | /// RGB colors. |
364 | /// |
365 | /// For the purpose of color conversion, as well as blending, the implementation of `Pixel` |
366 | /// assumes an `sRGB` color space of its data. |
367 | pub struct Rgb<T: Primitive Enlargeable>([T; 3, 0]) = "RGB" ; |
368 | /// Grayscale colors. |
369 | pub struct Luma<T: Primitive>([T; 1, 0]) = "Y" ; |
370 | /// RGB colors + alpha channel |
371 | pub struct Rgba<T: Primitive Enlargeable>([T; 4, 1]) = "RGBA" ; |
372 | /// Grayscale colors + alpha channel |
373 | pub struct LumaA<T: Primitive>([T; 2, 1]) = "YA" ; |
374 | } |
375 | |
376 | /// Convert from one pixel component type to another. For example, convert from `u8` to `f32` pixel values. |
377 | pub trait FromPrimitive<Component> { |
378 | /// Converts from any pixel component type to this type. |
379 | fn from_primitive(component: Component) -> Self; |
380 | } |
381 | |
382 | impl<T: Primitive> FromPrimitive<T> for T { |
383 | fn from_primitive(sample: T) -> Self { |
384 | sample |
385 | } |
386 | } |
387 | |
388 | // from f32: |
389 | // Note that in to-integer-conversion we are performing rounding but NumCast::from is implemented |
390 | // as truncate towards zero. We emulate rounding by adding a bias. |
391 | |
392 | impl FromPrimitive<f32> for u8 { |
393 | fn from_primitive(float: f32) -> Self { |
394 | let inner: f32 = (float.clamp(min:0.0, max:1.0) * u8::MAX as f32).round(); |
395 | NumCast::from(inner).unwrap() |
396 | } |
397 | } |
398 | |
399 | impl FromPrimitive<f32> for u16 { |
400 | fn from_primitive(float: f32) -> Self { |
401 | let inner: f32 = (float.clamp(min:0.0, max:1.0) * u16::MAX as f32).round(); |
402 | NumCast::from(inner).unwrap() |
403 | } |
404 | } |
405 | |
406 | // from u16: |
407 | |
408 | impl FromPrimitive<u16> for u8 { |
409 | fn from_primitive(c16: u16) -> Self { |
410 | fn from(c: impl Into<u32>) -> u32 { |
411 | c.into() |
412 | } |
413 | // The input c is the numerator of `c / u16::MAX`. |
414 | // Derive numerator of `num / u8::MAX`, with rounding. |
415 | // |
416 | // This method is based on the inverse (see FromPrimitive<u8> for u16) and was tested |
417 | // exhaustively in Python. It's the same as the reference function: |
418 | // round(c * (2**8 - 1) / (2**16 - 1)) |
419 | NumCast::from((from(c16) + 128) / 257).unwrap() |
420 | } |
421 | } |
422 | |
423 | impl FromPrimitive<u16> for f32 { |
424 | fn from_primitive(int: u16) -> Self { |
425 | (int as f32 / u16::MAX as f32).clamp(min:0.0, max:1.0) |
426 | } |
427 | } |
428 | |
429 | // from u8: |
430 | |
431 | impl FromPrimitive<u8> for f32 { |
432 | fn from_primitive(int: u8) -> Self { |
433 | (int as f32 / u8::MAX as f32).clamp(min:0.0, max:1.0) |
434 | } |
435 | } |
436 | |
437 | impl FromPrimitive<u8> for u16 { |
438 | fn from_primitive(c8: u8) -> Self { |
439 | let x: u64 = c8.to_u64().unwrap(); |
440 | NumCast::from((x << 8) | x).unwrap() |
441 | } |
442 | } |
443 | |
444 | /// Provides color conversions for the different pixel types. |
445 | pub trait FromColor<Other> { |
446 | /// Changes `self` to represent `Other` in the color space of `Self` |
447 | fn from_color(&mut self, _: &Other); |
448 | } |
449 | |
450 | /// Copy-based conversions to target pixel types using `FromColor`. |
451 | // FIXME: this trait should be removed and replaced with real color space models |
452 | // rather than assuming sRGB. |
453 | pub(crate) trait IntoColor<Other> { |
454 | /// Constructs a pixel of the target type and converts this pixel into it. |
455 | fn into_color(&self) -> Other; |
456 | } |
457 | |
458 | impl<O, S> IntoColor<O> for S |
459 | where |
460 | O: Pixel + FromColor<S>, |
461 | { |
462 | fn into_color(&self) -> O { |
463 | // Note we cannot use Pixel::CHANNELS_COUNT here to directly construct |
464 | // the pixel due to a current bug/limitation of consts. |
465 | #[allow (deprecated)] |
466 | let mut pix: O = O::from_channels(a:Zero::zero(), b:Zero::zero(), c:Zero::zero(), d:Zero::zero()); |
467 | pix.from_color(self); |
468 | pix |
469 | } |
470 | } |
471 | |
472 | /// Coefficients to transform from sRGB to a CIE Y (luminance) value. |
473 | const SRGB_LUMA: [u32; 3] = [2126, 7152, 722]; |
474 | const SRGB_LUMA_DIV: u32 = 10000; |
475 | |
476 | #[inline ] |
477 | fn rgb_to_luma<T: Primitive + Enlargeable>(rgb: &[T]) -> T { |
478 | let l: ::Larger = <T::Larger as NumCast>::from(SRGB_LUMA[0]).unwrap() * rgb[0].to_larger() |
479 | + <T::Larger as NumCast>::from(SRGB_LUMA[1]).unwrap() * rgb[1].to_larger() |
480 | + <T::Larger as NumCast>::from(SRGB_LUMA[2]).unwrap() * rgb[2].to_larger(); |
481 | T::clamp_from(l / <T::Larger as NumCast>::from(SRGB_LUMA_DIV).unwrap()) |
482 | } |
483 | |
484 | // `FromColor` for Luma |
485 | impl<S: Primitive, T: Primitive> FromColor<Luma<S>> for Luma<T> |
486 | where |
487 | T: FromPrimitive<S>, |
488 | { |
489 | fn from_color(&mut self, other: &Luma<S>) { |
490 | let own: &mut [T] = self.channels_mut(); |
491 | let other: &[S] = other.channels(); |
492 | own[0] = T::from_primitive(component:other[0]); |
493 | } |
494 | } |
495 | |
496 | impl<S: Primitive, T: Primitive> FromColor<LumaA<S>> for Luma<T> |
497 | where |
498 | T: FromPrimitive<S>, |
499 | { |
500 | fn from_color(&mut self, other: &LumaA<S>) { |
501 | self.channels_mut()[0] = T::from_primitive(component:other.channels()[0]) |
502 | } |
503 | } |
504 | |
505 | impl<S: Primitive + Enlargeable, T: Primitive> FromColor<Rgb<S>> for Luma<T> |
506 | where |
507 | T: FromPrimitive<S>, |
508 | { |
509 | fn from_color(&mut self, other: &Rgb<S>) { |
510 | let gray: &mut [T] = self.channels_mut(); |
511 | let rgb: &[S] = other.channels(); |
512 | gray[0] = T::from_primitive(component:rgb_to_luma(rgb)); |
513 | } |
514 | } |
515 | |
516 | impl<S: Primitive + Enlargeable, T: Primitive> FromColor<Rgba<S>> for Luma<T> |
517 | where |
518 | T: FromPrimitive<S>, |
519 | { |
520 | fn from_color(&mut self, other: &Rgba<S>) { |
521 | let gray: &mut [T] = self.channels_mut(); |
522 | let rgb: &[S] = other.channels(); |
523 | let l: S = rgb_to_luma(rgb); |
524 | gray[0] = T::from_primitive(component:l); |
525 | } |
526 | } |
527 | |
528 | // `FromColor` for LumaA |
529 | |
530 | impl<S: Primitive, T: Primitive> FromColor<LumaA<S>> for LumaA<T> |
531 | where |
532 | T: FromPrimitive<S>, |
533 | { |
534 | fn from_color(&mut self, other: &LumaA<S>) { |
535 | let own: &mut [T] = self.channels_mut(); |
536 | let other: &[S] = other.channels(); |
537 | own[0] = T::from_primitive(component:other[0]); |
538 | own[1] = T::from_primitive(component:other[1]); |
539 | } |
540 | } |
541 | |
542 | impl<S: Primitive + Enlargeable, T: Primitive> FromColor<Rgb<S>> for LumaA<T> |
543 | where |
544 | T: FromPrimitive<S>, |
545 | { |
546 | fn from_color(&mut self, other: &Rgb<S>) { |
547 | let gray_a: &mut [T] = self.channels_mut(); |
548 | let rgb: &[S] = other.channels(); |
549 | gray_a[0] = T::from_primitive(component:rgb_to_luma(rgb)); |
550 | gray_a[1] = T::DEFAULT_MAX_VALUE; |
551 | } |
552 | } |
553 | |
554 | impl<S: Primitive + Enlargeable, T: Primitive> FromColor<Rgba<S>> for LumaA<T> |
555 | where |
556 | T: FromPrimitive<S>, |
557 | { |
558 | fn from_color(&mut self, other: &Rgba<S>) { |
559 | let gray_a: &mut [T] = self.channels_mut(); |
560 | let rgba: &[S] = other.channels(); |
561 | gray_a[0] = T::from_primitive(component:rgb_to_luma(rgb:rgba)); |
562 | gray_a[1] = T::from_primitive(component:rgba[3]); |
563 | } |
564 | } |
565 | |
566 | impl<S: Primitive, T: Primitive> FromColor<Luma<S>> for LumaA<T> |
567 | where |
568 | T: FromPrimitive<S>, |
569 | { |
570 | fn from_color(&mut self, other: &Luma<S>) { |
571 | let gray_a: &mut [T] = self.channels_mut(); |
572 | gray_a[0] = T::from_primitive(component:other.channels()[0]); |
573 | gray_a[1] = T::DEFAULT_MAX_VALUE; |
574 | } |
575 | } |
576 | |
577 | // `FromColor` for RGBA |
578 | |
579 | impl<S: Primitive, T: Primitive> FromColor<Rgba<S>> for Rgba<T> |
580 | where |
581 | T: FromPrimitive<S>, |
582 | { |
583 | fn from_color(&mut self, other: &Rgba<S>) { |
584 | let own: &mut [T; 4] = &mut self.0; |
585 | let other: &[S; 4] = &other.0; |
586 | own[0] = T::from_primitive(component:other[0]); |
587 | own[1] = T::from_primitive(component:other[1]); |
588 | own[2] = T::from_primitive(component:other[2]); |
589 | own[3] = T::from_primitive(component:other[3]); |
590 | } |
591 | } |
592 | |
593 | impl<S: Primitive, T: Primitive> FromColor<Rgb<S>> for Rgba<T> |
594 | where |
595 | T: FromPrimitive<S>, |
596 | { |
597 | fn from_color(&mut self, other: &Rgb<S>) { |
598 | let rgba: &mut [T; 4] = &mut self.0; |
599 | let rgb: &[S; 3] = &other.0; |
600 | rgba[0] = T::from_primitive(component:rgb[0]); |
601 | rgba[1] = T::from_primitive(component:rgb[1]); |
602 | rgba[2] = T::from_primitive(component:rgb[2]); |
603 | rgba[3] = T::DEFAULT_MAX_VALUE; |
604 | } |
605 | } |
606 | |
607 | impl<S: Primitive, T: Primitive> FromColor<LumaA<S>> for Rgba<T> |
608 | where |
609 | T: FromPrimitive<S>, |
610 | { |
611 | fn from_color(&mut self, gray: &LumaA<S>) { |
612 | let rgba: &mut [T; 4] = &mut self.0; |
613 | let gray: &[S; 2] = &gray.0; |
614 | rgba[0] = T::from_primitive(component:gray[0]); |
615 | rgba[1] = T::from_primitive(component:gray[0]); |
616 | rgba[2] = T::from_primitive(component:gray[0]); |
617 | rgba[3] = T::from_primitive(component:gray[1]); |
618 | } |
619 | } |
620 | |
621 | impl<S: Primitive, T: Primitive> FromColor<Luma<S>> for Rgba<T> |
622 | where |
623 | T: FromPrimitive<S>, |
624 | { |
625 | fn from_color(&mut self, gray: &Luma<S>) { |
626 | let rgba: &mut [T; 4] = &mut self.0; |
627 | let gray: S = gray.0[0]; |
628 | rgba[0] = T::from_primitive(component:gray); |
629 | rgba[1] = T::from_primitive(component:gray); |
630 | rgba[2] = T::from_primitive(component:gray); |
631 | rgba[3] = T::DEFAULT_MAX_VALUE; |
632 | } |
633 | } |
634 | |
635 | // `FromColor` for RGB |
636 | |
637 | impl<S: Primitive, T: Primitive> FromColor<Rgb<S>> for Rgb<T> |
638 | where |
639 | T: FromPrimitive<S>, |
640 | { |
641 | fn from_color(&mut self, other: &Rgb<S>) { |
642 | let own: &mut [T; 3] = &mut self.0; |
643 | let other: &[S; 3] = &other.0; |
644 | own[0] = T::from_primitive(component:other[0]); |
645 | own[1] = T::from_primitive(component:other[1]); |
646 | own[2] = T::from_primitive(component:other[2]); |
647 | } |
648 | } |
649 | |
650 | impl<S: Primitive, T: Primitive> FromColor<Rgba<S>> for Rgb<T> |
651 | where |
652 | T: FromPrimitive<S>, |
653 | { |
654 | fn from_color(&mut self, other: &Rgba<S>) { |
655 | let rgb: &mut [T; 3] = &mut self.0; |
656 | let rgba: &[S; 4] = &other.0; |
657 | rgb[0] = T::from_primitive(component:rgba[0]); |
658 | rgb[1] = T::from_primitive(component:rgba[1]); |
659 | rgb[2] = T::from_primitive(component:rgba[2]); |
660 | } |
661 | } |
662 | |
663 | impl<S: Primitive, T: Primitive> FromColor<LumaA<S>> for Rgb<T> |
664 | where |
665 | T: FromPrimitive<S>, |
666 | { |
667 | fn from_color(&mut self, other: &LumaA<S>) { |
668 | let rgb: &mut [T; 3] = &mut self.0; |
669 | let gray: S = other.0[0]; |
670 | rgb[0] = T::from_primitive(component:gray); |
671 | rgb[1] = T::from_primitive(component:gray); |
672 | rgb[2] = T::from_primitive(component:gray); |
673 | } |
674 | } |
675 | |
676 | impl<S: Primitive, T: Primitive> FromColor<Luma<S>> for Rgb<T> |
677 | where |
678 | T: FromPrimitive<S>, |
679 | { |
680 | fn from_color(&mut self, other: &Luma<S>) { |
681 | let rgb: &mut [T; 3] = &mut self.0; |
682 | let gray: S = other.0[0]; |
683 | rgb[0] = T::from_primitive(component:gray); |
684 | rgb[1] = T::from_primitive(component:gray); |
685 | rgb[2] = T::from_primitive(component:gray); |
686 | } |
687 | } |
688 | |
689 | /// Blends a color inter another one |
690 | pub(crate) trait Blend { |
691 | /// Blends a color in-place. |
692 | fn blend(&mut self, other: &Self); |
693 | } |
694 | |
695 | impl<T: Primitive> Blend for LumaA<T> { |
696 | fn blend(&mut self, other: &LumaA<T>) { |
697 | let max_t = T::DEFAULT_MAX_VALUE; |
698 | let max_t = max_t.to_f32().unwrap(); |
699 | let (bg_luma, bg_a) = (self.0[0], self.0[1]); |
700 | let (fg_luma, fg_a) = (other.0[0], other.0[1]); |
701 | |
702 | let (bg_luma, bg_a) = ( |
703 | bg_luma.to_f32().unwrap() / max_t, |
704 | bg_a.to_f32().unwrap() / max_t, |
705 | ); |
706 | let (fg_luma, fg_a) = ( |
707 | fg_luma.to_f32().unwrap() / max_t, |
708 | fg_a.to_f32().unwrap() / max_t, |
709 | ); |
710 | |
711 | let alpha_final = bg_a + fg_a - bg_a * fg_a; |
712 | if alpha_final == 0.0 { |
713 | return; |
714 | }; |
715 | let bg_luma_a = bg_luma * bg_a; |
716 | let fg_luma_a = fg_luma * fg_a; |
717 | |
718 | let out_luma_a = fg_luma_a + bg_luma_a * (1.0 - fg_a); |
719 | let out_luma = out_luma_a / alpha_final; |
720 | |
721 | *self = LumaA([ |
722 | NumCast::from(max_t * out_luma).unwrap(), |
723 | NumCast::from(max_t * alpha_final).unwrap(), |
724 | ]) |
725 | } |
726 | } |
727 | |
728 | impl<T: Primitive> Blend for Luma<T> { |
729 | fn blend(&mut self, other: &Luma<T>) { |
730 | *self = *other |
731 | } |
732 | } |
733 | |
734 | impl<T: Primitive> Blend for Rgba<T> { |
735 | fn blend(&mut self, other: &Rgba<T>) { |
736 | // http://stackoverflow.com/questions/7438263/alpha-compositing-algorithm-blend-modes#answer-11163848 |
737 | |
738 | if other.0[3].is_zero() { |
739 | return; |
740 | } |
741 | if other.0[3] == T::DEFAULT_MAX_VALUE { |
742 | *self = *other; |
743 | return; |
744 | } |
745 | |
746 | // First, as we don't know what type our pixel is, we have to convert to floats between 0.0 and 1.0 |
747 | let max_t = T::DEFAULT_MAX_VALUE; |
748 | let max_t = max_t.to_f32().unwrap(); |
749 | let (bg_r, bg_g, bg_b, bg_a) = (self.0[0], self.0[1], self.0[2], self.0[3]); |
750 | let (fg_r, fg_g, fg_b, fg_a) = (other.0[0], other.0[1], other.0[2], other.0[3]); |
751 | let (bg_r, bg_g, bg_b, bg_a) = ( |
752 | bg_r.to_f32().unwrap() / max_t, |
753 | bg_g.to_f32().unwrap() / max_t, |
754 | bg_b.to_f32().unwrap() / max_t, |
755 | bg_a.to_f32().unwrap() / max_t, |
756 | ); |
757 | let (fg_r, fg_g, fg_b, fg_a) = ( |
758 | fg_r.to_f32().unwrap() / max_t, |
759 | fg_g.to_f32().unwrap() / max_t, |
760 | fg_b.to_f32().unwrap() / max_t, |
761 | fg_a.to_f32().unwrap() / max_t, |
762 | ); |
763 | |
764 | // Work out what the final alpha level will be |
765 | let alpha_final = bg_a + fg_a - bg_a * fg_a; |
766 | if alpha_final == 0.0 { |
767 | return; |
768 | }; |
769 | |
770 | // We premultiply our channels by their alpha, as this makes it easier to calculate |
771 | let (bg_r_a, bg_g_a, bg_b_a) = (bg_r * bg_a, bg_g * bg_a, bg_b * bg_a); |
772 | let (fg_r_a, fg_g_a, fg_b_a) = (fg_r * fg_a, fg_g * fg_a, fg_b * fg_a); |
773 | |
774 | // Standard formula for src-over alpha compositing |
775 | let (out_r_a, out_g_a, out_b_a) = ( |
776 | fg_r_a + bg_r_a * (1.0 - fg_a), |
777 | fg_g_a + bg_g_a * (1.0 - fg_a), |
778 | fg_b_a + bg_b_a * (1.0 - fg_a), |
779 | ); |
780 | |
781 | // Unmultiply the channels by our resultant alpha channel |
782 | let (out_r, out_g, out_b) = ( |
783 | out_r_a / alpha_final, |
784 | out_g_a / alpha_final, |
785 | out_b_a / alpha_final, |
786 | ); |
787 | |
788 | // Cast back to our initial type on return |
789 | *self = Rgba([ |
790 | NumCast::from(max_t * out_r).unwrap(), |
791 | NumCast::from(max_t * out_g).unwrap(), |
792 | NumCast::from(max_t * out_b).unwrap(), |
793 | NumCast::from(max_t * alpha_final).unwrap(), |
794 | ]) |
795 | } |
796 | } |
797 | |
798 | impl<T: Primitive> Blend for Rgb<T> { |
799 | fn blend(&mut self, other: &Rgb<T>) { |
800 | *self = *other |
801 | } |
802 | } |
803 | |
804 | /// Invert a color |
805 | pub(crate) trait Invert { |
806 | /// Inverts a color in-place. |
807 | fn invert(&mut self); |
808 | } |
809 | |
810 | impl<T: Primitive> Invert for LumaA<T> { |
811 | fn invert(&mut self) { |
812 | let l: [T; 2] = self.0; |
813 | let max: T = T::DEFAULT_MAX_VALUE; |
814 | |
815 | *self = LumaA([max - l[0], l[1]]) |
816 | } |
817 | } |
818 | |
819 | impl<T: Primitive> Invert for Luma<T> { |
820 | fn invert(&mut self) { |
821 | let l: [T; 1] = self.0; |
822 | |
823 | let max: T = T::DEFAULT_MAX_VALUE; |
824 | let l1: T = max - l[0]; |
825 | |
826 | *self = Luma([l1]) |
827 | } |
828 | } |
829 | |
830 | impl<T: Primitive> Invert for Rgba<T> { |
831 | fn invert(&mut self) { |
832 | let rgba: [T; 4] = self.0; |
833 | |
834 | let max: T = T::DEFAULT_MAX_VALUE; |
835 | |
836 | *self = Rgba([max - rgba[0], max - rgba[1], max - rgba[2], rgba[3]]) |
837 | } |
838 | } |
839 | |
840 | impl<T: Primitive> Invert for Rgb<T> { |
841 | fn invert(&mut self) { |
842 | let rgb: [T; 3] = self.0; |
843 | |
844 | let max: T = T::DEFAULT_MAX_VALUE; |
845 | |
846 | let r1: T = max - rgb[0]; |
847 | let g1: T = max - rgb[1]; |
848 | let b1: T = max - rgb[2]; |
849 | |
850 | *self = Rgb([r1, g1, b1]) |
851 | } |
852 | } |
853 | |
854 | #[cfg (test)] |
855 | mod tests { |
856 | use super::{Luma, LumaA, Pixel, Rgb, Rgba}; |
857 | |
858 | #[test ] |
859 | fn test_apply_with_alpha_rgba() { |
860 | let mut rgba = Rgba([0, 0, 0, 0]); |
861 | rgba.apply_with_alpha(|s| s, |_| 0xFF); |
862 | assert_eq!(rgba, Rgba([0, 0, 0, 0xFF])); |
863 | } |
864 | |
865 | #[test ] |
866 | fn test_apply_with_alpha_rgb() { |
867 | let mut rgb = Rgb([0, 0, 0]); |
868 | rgb.apply_with_alpha(|s| s, |_| panic!("bug" )); |
869 | assert_eq!(rgb, Rgb([0, 0, 0])); |
870 | } |
871 | |
872 | #[test ] |
873 | fn test_map_with_alpha_rgba() { |
874 | let rgba = Rgba([0, 0, 0, 0]).map_with_alpha(|s| s, |_| 0xFF); |
875 | assert_eq!(rgba, Rgba([0, 0, 0, 0xFF])); |
876 | } |
877 | |
878 | #[test ] |
879 | fn test_map_with_alpha_rgb() { |
880 | let rgb = Rgb([0, 0, 0]).map_with_alpha(|s| s, |_| panic!("bug" )); |
881 | assert_eq!(rgb, Rgb([0, 0, 0])); |
882 | } |
883 | |
884 | #[test ] |
885 | fn test_blend_luma_alpha() { |
886 | let a = &mut LumaA([255_u8, 255]); |
887 | let b = LumaA([255_u8, 255]); |
888 | a.blend(&b); |
889 | assert_eq!(a.0[0], 255); |
890 | assert_eq!(a.0[1], 255); |
891 | |
892 | let a = &mut LumaA([255_u8, 0]); |
893 | let b = LumaA([255_u8, 255]); |
894 | a.blend(&b); |
895 | assert_eq!(a.0[0], 255); |
896 | assert_eq!(a.0[1], 255); |
897 | |
898 | let a = &mut LumaA([255_u8, 255]); |
899 | let b = LumaA([255_u8, 0]); |
900 | a.blend(&b); |
901 | assert_eq!(a.0[0], 255); |
902 | assert_eq!(a.0[1], 255); |
903 | |
904 | let a = &mut LumaA([255_u8, 0]); |
905 | let b = LumaA([255_u8, 0]); |
906 | a.blend(&b); |
907 | assert_eq!(a.0[0], 255); |
908 | assert_eq!(a.0[1], 0); |
909 | } |
910 | |
911 | #[test ] |
912 | fn test_blend_rgba() { |
913 | let a = &mut Rgba([255_u8, 255, 255, 255]); |
914 | let b = Rgba([255_u8, 255, 255, 255]); |
915 | a.blend(&b); |
916 | assert_eq!(a.0, [255, 255, 255, 255]); |
917 | |
918 | let a = &mut Rgba([255_u8, 255, 255, 0]); |
919 | let b = Rgba([255_u8, 255, 255, 255]); |
920 | a.blend(&b); |
921 | assert_eq!(a.0, [255, 255, 255, 255]); |
922 | |
923 | let a = &mut Rgba([255_u8, 255, 255, 255]); |
924 | let b = Rgba([255_u8, 255, 255, 0]); |
925 | a.blend(&b); |
926 | assert_eq!(a.0, [255, 255, 255, 255]); |
927 | |
928 | let a = &mut Rgba([255_u8, 255, 255, 0]); |
929 | let b = Rgba([255_u8, 255, 255, 0]); |
930 | a.blend(&b); |
931 | assert_eq!(a.0, [255, 255, 255, 0]); |
932 | } |
933 | |
934 | #[test ] |
935 | fn test_apply_without_alpha_rgba() { |
936 | let mut rgba = Rgba([0, 0, 0, 0]); |
937 | rgba.apply_without_alpha(|s| s + 1); |
938 | assert_eq!(rgba, Rgba([1, 1, 1, 0])); |
939 | } |
940 | |
941 | #[test ] |
942 | fn test_apply_without_alpha_rgb() { |
943 | let mut rgb = Rgb([0, 0, 0]); |
944 | rgb.apply_without_alpha(|s| s + 1); |
945 | assert_eq!(rgb, Rgb([1, 1, 1])); |
946 | } |
947 | |
948 | #[test ] |
949 | fn test_map_without_alpha_rgba() { |
950 | let rgba = Rgba([0, 0, 0, 0]).map_without_alpha(|s| s + 1); |
951 | assert_eq!(rgba, Rgba([1, 1, 1, 0])); |
952 | } |
953 | |
954 | #[test ] |
955 | fn test_map_without_alpha_rgb() { |
956 | let rgb = Rgb([0, 0, 0]).map_without_alpha(|s| s + 1); |
957 | assert_eq!(rgb, Rgb([1, 1, 1])); |
958 | } |
959 | |
960 | macro_rules! test_lossless_conversion { |
961 | ($a:ty, $b:ty, $c:ty) => { |
962 | let a: $a = [<$a as Pixel>::Subpixel::DEFAULT_MAX_VALUE >> 2; |
963 | <$a as Pixel>::CHANNEL_COUNT as usize] |
964 | .into(); |
965 | let b: $b = a.into_color(); |
966 | let c: $c = b.into_color(); |
967 | assert_eq!(a.channels(), c.channels()); |
968 | }; |
969 | } |
970 | |
971 | #[test ] |
972 | fn test_lossless_conversions() { |
973 | use super::IntoColor; |
974 | use crate::traits::Primitive; |
975 | |
976 | test_lossless_conversion!(Luma<u8>, Luma<u16>, Luma<u8>); |
977 | test_lossless_conversion!(LumaA<u8>, LumaA<u16>, LumaA<u8>); |
978 | test_lossless_conversion!(Rgb<u8>, Rgb<u16>, Rgb<u8>); |
979 | test_lossless_conversion!(Rgba<u8>, Rgba<u16>, Rgba<u8>); |
980 | } |
981 | |
982 | #[test ] |
983 | fn accuracy_conversion() { |
984 | use super::{Luma, Pixel, Rgb}; |
985 | let pixel = Rgb::from([13, 13, 13]); |
986 | let Luma([luma]) = pixel.to_luma(); |
987 | assert_eq!(luma, 13); |
988 | } |
989 | } |
990 | |