1use crate::basics::{uround, CoverType, COVER_MASK};
17
18pub struct OrderRgb;
24impl OrderRgb {
25 pub const R: usize = 0;
26 pub const G: usize = 1;
27 pub const B: usize = 2;
28 pub const N: usize = 3;
29}
30
31pub struct OrderBgr;
33impl OrderBgr {
34 pub const B: usize = 0;
35 pub const G: usize = 1;
36 pub const R: usize = 2;
37 pub const N: usize = 3;
38}
39
40pub struct OrderRgba;
42impl OrderRgba {
43 pub const R: usize = 0;
44 pub const G: usize = 1;
45 pub const B: usize = 2;
46 pub const A: usize = 3;
47 pub const N: usize = 4;
48}
49
50pub struct OrderArgb;
52impl OrderArgb {
53 pub const A: usize = 0;
54 pub const R: usize = 1;
55 pub const G: usize = 2;
56 pub const B: usize = 3;
57 pub const N: usize = 4;
58}
59
60pub struct OrderAbgr;
62impl OrderAbgr {
63 pub const A: usize = 0;
64 pub const B: usize = 1;
65 pub const G: usize = 2;
66 pub const R: usize = 3;
67 pub const N: usize = 4;
68}
69
70pub struct OrderBgra;
72impl OrderBgra {
73 pub const B: usize = 0;
74 pub const G: usize = 1;
75 pub const R: usize = 2;
76 pub const A: usize = 3;
77 pub const N: usize = 4;
78}
79
80#[derive(Debug, Clone, Copy, PartialEq)]
87pub struct Rgba {
88 pub r: f64,
89 pub g: f64,
90 pub b: f64,
91 pub a: f64,
92}
93
94impl Rgba {
95 pub fn new(r: f64, g: f64, b: f64, a: f64) -> Self {
96 Self { r, g, b, a }
97 }
98
99 pub fn new_rgb(r: f64, g: f64, b: f64) -> Self {
100 Self { r, g, b, a: 1.0 }
101 }
102
103 pub fn with_opacity(c: &Rgba, a: f64) -> Self {
104 Self {
105 r: c.r,
106 g: c.g,
107 b: c.b,
108 a,
109 }
110 }
111
112 pub fn clear(&mut self) -> &mut Self {
113 self.r = 0.0;
114 self.g = 0.0;
115 self.b = 0.0;
116 self.a = 0.0;
117 self
118 }
119
120 pub fn transparent(&mut self) -> &mut Self {
121 self.a = 0.0;
122 self
123 }
124
125 pub fn set_opacity(&mut self, a: f64) -> &mut Self {
126 if a < 0.0 {
127 self.a = 0.0;
128 } else if a > 1.0 {
129 self.a = 1.0;
130 } else {
131 self.a = a;
132 }
133 self
134 }
135
136 pub fn opacity(&self) -> f64 {
137 self.a
138 }
139
140 pub fn premultiply(&mut self) -> &mut Self {
141 self.r *= self.a;
142 self.g *= self.a;
143 self.b *= self.a;
144 self
145 }
146
147 pub fn premultiply_with_alpha(&mut self, a: f64) -> &mut Self {
148 if self.a <= 0.0 || a <= 0.0 {
149 self.r = 0.0;
150 self.g = 0.0;
151 self.b = 0.0;
152 self.a = 0.0;
153 } else {
154 let scale = a / self.a;
155 self.r *= scale;
156 self.g *= scale;
157 self.b *= scale;
158 self.a = scale;
159 }
160 self
161 }
162
163 pub fn demultiply(&mut self) -> &mut Self {
164 if self.a == 0.0 {
165 self.r = 0.0;
166 self.g = 0.0;
167 self.b = 0.0;
168 } else {
169 let inv_a = 1.0 / self.a;
170 self.r *= inv_a;
171 self.g *= inv_a;
172 self.b *= inv_a;
173 }
174 self
175 }
176
177 pub fn gradient(&self, c: &Rgba, k: f64) -> Rgba {
179 Rgba {
180 r: self.r + (c.r - self.r) * k,
181 g: self.g + (c.g - self.g) * k,
182 b: self.b + (c.b - self.b) * k,
183 a: self.a + (c.a - self.a) * k,
184 }
185 }
186
187 pub fn no_color() -> Self {
188 Self {
189 r: 0.0,
190 g: 0.0,
191 b: 0.0,
192 a: 0.0,
193 }
194 }
195
196 pub fn from_wavelength(wl: f64, gamma: f64) -> Self {
198 let mut t = Rgba::new(0.0, 0.0, 0.0, 1.0);
199
200 if (380.0..=440.0).contains(&wl) {
201 t.r = -(wl - 440.0) / (440.0 - 380.0);
202 t.b = 1.0;
203 } else if (440.0..=490.0).contains(&wl) {
204 t.g = (wl - 440.0) / (490.0 - 440.0);
205 t.b = 1.0;
206 } else if (490.0..=510.0).contains(&wl) {
207 t.g = 1.0;
208 t.b = -(wl - 510.0) / (510.0 - 490.0);
209 } else if (510.0..=580.0).contains(&wl) {
210 t.r = (wl - 510.0) / (580.0 - 510.0);
211 t.g = 1.0;
212 } else if (580.0..=645.0).contains(&wl) {
213 t.r = 1.0;
214 t.g = -(wl - 645.0) / (645.0 - 580.0);
215 } else if (645.0..=780.0).contains(&wl) {
216 t.r = 1.0;
217 }
218
219 let s = if wl > 700.0 {
220 0.3 + 0.7 * (780.0 - wl) / (780.0 - 700.0)
221 } else if wl < 420.0 {
222 0.3 + 0.7 * (wl - 380.0) / (420.0 - 380.0)
223 } else {
224 1.0
225 };
226
227 t.r = (t.r * s).powf(gamma);
228 t.g = (t.g * s).powf(gamma);
229 t.b = (t.b * s).powf(gamma);
230 t
231 }
232}
233
234impl Default for Rgba {
235 fn default() -> Self {
236 Self::no_color()
237 }
238}
239
240impl core::ops::Add for Rgba {
241 type Output = Self;
242 fn add(self, rhs: Self) -> Self {
243 Self {
244 r: self.r + rhs.r,
245 g: self.g + rhs.g,
246 b: self.b + rhs.b,
247 a: self.a + rhs.a,
248 }
249 }
250}
251
252impl core::ops::AddAssign for Rgba {
253 fn add_assign(&mut self, rhs: Self) {
254 self.r += rhs.r;
255 self.g += rhs.g;
256 self.b += rhs.b;
257 self.a += rhs.a;
258 }
259}
260
261impl core::ops::Mul<f64> for Rgba {
262 type Output = Self;
263 fn mul(self, k: f64) -> Self {
264 Self {
265 r: self.r * k,
266 g: self.g * k,
267 b: self.b * k,
268 a: self.a * k,
269 }
270 }
271}
272
273impl core::ops::MulAssign<f64> for Rgba {
274 fn mul_assign(&mut self, k: f64) {
275 self.r *= k;
276 self.g *= k;
277 self.b *= k;
278 self.a *= k;
279 }
280}
281
282pub fn rgba_pre(r: f64, g: f64, b: f64, a: f64) -> Rgba {
284 let mut c = Rgba::new(r, g, b, a);
285 c.premultiply();
286 c
287}
288
289#[derive(Debug, Clone, Copy, PartialEq, Eq)]
296pub struct Rgba8 {
297 pub r: u8,
298 pub g: u8,
299 pub b: u8,
300 pub a: u8,
301}
302
303impl Rgba8 {
304 pub const BASE_SHIFT: u32 = 8;
305 pub const BASE_SCALE: u32 = 1 << Self::BASE_SHIFT;
306 pub const BASE_MASK: u32 = Self::BASE_SCALE - 1;
307 pub const BASE_MSB: u32 = 1 << (Self::BASE_SHIFT - 1);
308
309 pub fn new(r: u32, g: u32, b: u32, a: u32) -> Self {
310 Self {
311 r: r as u8,
312 g: g as u8,
313 b: b as u8,
314 a: a as u8,
315 }
316 }
317
318 pub fn new_opaque(r: u32, g: u32, b: u32) -> Self {
319 Self::new(r, g, b, Self::BASE_MASK)
320 }
321
322 pub fn with_opacity(c: &Rgba8, a: u32) -> Self {
323 Self {
324 r: c.r,
325 g: c.g,
326 b: c.b,
327 a: a as u8,
328 }
329 }
330
331 pub fn from_rgba(c: &Rgba) -> Self {
333 Self {
334 r: uround(c.r * Self::BASE_MASK as f64) as u8,
335 g: uround(c.g * Self::BASE_MASK as f64) as u8,
336 b: uround(c.b * Self::BASE_MASK as f64) as u8,
337 a: uround(c.a * Self::BASE_MASK as f64) as u8,
338 }
339 }
340
341 pub fn to_rgba(&self) -> Rgba {
343 Rgba {
344 r: self.r as f64 / 255.0,
345 g: self.g as f64 / 255.0,
346 b: self.b as f64 / 255.0,
347 a: self.a as f64 / 255.0,
348 }
349 }
350
351 #[inline]
352 pub fn to_double(a: u8) -> f64 {
353 a as f64 / Self::BASE_MASK as f64
354 }
355
356 #[inline]
357 pub fn from_double(a: f64) -> u8 {
358 uround(a * Self::BASE_MASK as f64) as u8
359 }
360
361 pub fn empty_value() -> u8 {
362 0
363 }
364
365 pub fn full_value() -> u8 {
366 Self::BASE_MASK as u8
367 }
368
369 pub fn is_transparent(&self) -> bool {
370 self.a == 0
371 }
372
373 pub fn is_opaque(&self) -> bool {
374 self.a == Self::BASE_MASK as u8
375 }
376
377 pub fn invert(x: u8) -> u8 {
378 Self::BASE_MASK as u8 - x
379 }
380
381 #[inline]
384 pub fn multiply(a: u8, b: u8) -> u8 {
385 let t: u32 = a as u32 * b as u32 + Self::BASE_MSB;
386 (((t >> Self::BASE_SHIFT) + t) >> Self::BASE_SHIFT) as u8
387 }
388
389 #[inline]
391 pub fn demultiply_value(a: u8, b: u8) -> u8 {
392 if (a as u32) * (b as u32) == 0 {
393 0
394 } else if a >= b {
395 Self::BASE_MASK as u8
396 } else {
397 (a as u32 * Self::BASE_MASK + (b as u32 >> 1)) as u8 / b
398 }
399 }
400
401 #[inline]
403 pub fn mult_cover(a: u8, b: CoverType) -> u8 {
404 Self::multiply(a, b)
405 }
406
407 #[inline]
409 pub fn scale_cover(a: CoverType, b: u8) -> CoverType {
410 Self::multiply(b, a)
411 }
412
413 #[inline]
415 pub fn prelerp(p: u8, q: u8, a: u8) -> u8 {
416 p.wrapping_add(q).wrapping_sub(Self::multiply(p, a))
417 }
418
419 #[inline]
421 pub fn lerp(p: u8, q: u8, a: u8) -> u8 {
422 let t = (q as i32 - p as i32) * a as i32 + Self::BASE_MSB as i32 - (p > q) as i32;
423 (p as i32 + (((t >> Self::BASE_SHIFT) + t) >> Self::BASE_SHIFT)) as u8
424 }
425
426 pub fn clear(&mut self) -> &mut Self {
427 self.r = 0;
428 self.g = 0;
429 self.b = 0;
430 self.a = 0;
431 self
432 }
433
434 pub fn transparent(&mut self) -> &mut Self {
435 self.a = 0;
436 self
437 }
438
439 pub fn set_opacity(&mut self, a: f64) -> &mut Self {
440 if a < 0.0 {
441 self.a = 0;
442 } else if a > 1.0 {
443 self.a = 1;
444 } else {
445 self.a = uround(a * Self::BASE_MASK as f64) as u8;
446 }
447 self
448 }
449
450 pub fn opacity(&self) -> f64 {
451 self.a as f64 / Self::BASE_MASK as f64
452 }
453
454 pub fn premultiply(&mut self) -> &mut Self {
455 if self.a != Self::BASE_MASK as u8 {
456 if self.a == 0 {
457 self.r = 0;
458 self.g = 0;
459 self.b = 0;
460 } else {
461 self.r = Self::multiply(self.r, self.a);
462 self.g = Self::multiply(self.g, self.a);
463 self.b = Self::multiply(self.b, self.a);
464 }
465 }
466 self
467 }
468
469 pub fn premultiply_with_alpha(&mut self, a_: u32) -> &mut Self {
470 if self.a as u32 != Self::BASE_MASK || a_ < Self::BASE_MASK {
471 if self.a == 0 || a_ == 0 {
472 self.r = 0;
473 self.g = 0;
474 self.b = 0;
475 self.a = 0;
476 } else {
477 let r_ = (self.r as u32 * a_) / self.a as u32;
478 let g_ = (self.g as u32 * a_) / self.a as u32;
479 let b_ = (self.b as u32 * a_) / self.a as u32;
480 self.r = if r_ > a_ { a_ as u8 } else { r_ as u8 };
481 self.g = if g_ > a_ { a_ as u8 } else { g_ as u8 };
482 self.b = if b_ > a_ { a_ as u8 } else { b_ as u8 };
483 self.a = a_ as u8;
484 }
485 }
486 self
487 }
488
489 pub fn demultiply(&mut self) -> &mut Self {
490 if (self.a as u32) < Self::BASE_MASK {
491 if self.a == 0 {
492 self.r = 0;
493 self.g = 0;
494 self.b = 0;
495 } else {
496 let r_ = (self.r as u32 * Self::BASE_MASK) / self.a as u32;
497 let g_ = (self.g as u32 * Self::BASE_MASK) / self.a as u32;
498 let b_ = (self.b as u32 * Self::BASE_MASK) / self.a as u32;
499 self.r = r_.min(Self::BASE_MASK) as u8;
500 self.g = g_.min(Self::BASE_MASK) as u8;
501 self.b = b_.min(Self::BASE_MASK) as u8;
502 }
503 }
504 self
505 }
506
507 pub fn gradient(&self, c: &Rgba8, k: f64) -> Rgba8 {
509 let ik = uround(k * Self::BASE_MASK as f64) as u8;
510 Rgba8 {
511 r: Self::lerp(self.r, c.r, ik),
512 g: Self::lerp(self.g, c.g, ik),
513 b: Self::lerp(self.b, c.b, ik),
514 a: Self::lerp(self.a, c.a, ik),
515 }
516 }
517
518 pub fn add(&mut self, c: &Rgba8, cover: u32) {
520 let cr: u32;
521 let cg: u32;
522 let cb: u32;
523 let ca: u32;
524 if cover == COVER_MASK {
525 if c.a as u32 == Self::BASE_MASK {
526 *self = *c;
527 return;
528 } else {
529 cr = self.r as u32 + c.r as u32;
530 cg = self.g as u32 + c.g as u32;
531 cb = self.b as u32 + c.b as u32;
532 ca = self.a as u32 + c.a as u32;
533 }
534 } else {
535 cr = self.r as u32 + Self::mult_cover(c.r, cover as u8) as u32;
536 cg = self.g as u32 + Self::mult_cover(c.g, cover as u8) as u32;
537 cb = self.b as u32 + Self::mult_cover(c.b, cover as u8) as u32;
538 ca = self.a as u32 + Self::mult_cover(c.a, cover as u8) as u32;
539 }
540 self.r = cr.min(Self::BASE_MASK) as u8;
541 self.g = cg.min(Self::BASE_MASK) as u8;
542 self.b = cb.min(Self::BASE_MASK) as u8;
543 self.a = ca.min(Self::BASE_MASK) as u8;
544 }
545
546 pub fn apply_gamma_dir(&mut self, gamma: &crate::gamma::GammaLut) {
548 self.r = gamma.dir(self.r);
549 self.g = gamma.dir(self.g);
550 self.b = gamma.dir(self.b);
551 }
552
553 pub fn apply_gamma_inv(&mut self, gamma: &crate::gamma::GammaLut) {
555 self.r = gamma.inv(self.r);
556 self.g = gamma.inv(self.g);
557 self.b = gamma.inv(self.b);
558 }
559
560 pub fn no_color() -> Self {
561 Self {
562 r: 0,
563 g: 0,
564 b: 0,
565 a: 0,
566 }
567 }
568
569 pub fn from_wavelength(wl: f64, gamma: f64) -> Self {
570 Self::from_rgba(&Rgba::from_wavelength(wl, gamma))
571 }
572}
573
574impl Default for Rgba8 {
575 fn default() -> Self {
576 Self::no_color()
577 }
578}
579
580pub fn rgb8_packed(v: u32) -> Rgba8 {
582 Rgba8::new((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF, 255)
583}
584
585pub fn bgr8_packed(v: u32) -> Rgba8 {
587 Rgba8::new(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF, 255)
588}
589
590pub fn argb8_packed(v: u32) -> Rgba8 {
592 Rgba8::new((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF, v >> 24)
593}
594
595#[derive(Debug, Clone, Copy, PartialEq, Eq)]
602pub struct Rgba16 {
603 pub r: u16,
604 pub g: u16,
605 pub b: u16,
606 pub a: u16,
607}
608
609impl Rgba16 {
610 pub const BASE_SHIFT: u32 = 16;
611 pub const BASE_SCALE: u32 = 1 << Self::BASE_SHIFT;
612 pub const BASE_MASK: u32 = Self::BASE_SCALE - 1;
613 pub const BASE_MSB: u32 = 1 << (Self::BASE_SHIFT - 1);
614
615 pub fn new(r: u32, g: u32, b: u32, a: u32) -> Self {
616 Self {
617 r: r as u16,
618 g: g as u16,
619 b: b as u16,
620 a: a as u16,
621 }
622 }
623
624 pub fn new_opaque(r: u32, g: u32, b: u32) -> Self {
625 Self::new(r, g, b, Self::BASE_MASK)
626 }
627
628 pub fn from_rgba(c: &Rgba) -> Self {
630 Self {
631 r: uround(c.r * Self::BASE_MASK as f64) as u16,
632 g: uround(c.g * Self::BASE_MASK as f64) as u16,
633 b: uround(c.b * Self::BASE_MASK as f64) as u16,
634 a: uround(c.a * Self::BASE_MASK as f64) as u16,
635 }
636 }
637
638 pub fn from_rgba8(c: &Rgba8) -> Self {
640 Self {
641 r: ((c.r as u16) << 8) | c.r as u16,
642 g: ((c.g as u16) << 8) | c.g as u16,
643 b: ((c.b as u16) << 8) | c.b as u16,
644 a: ((c.a as u16) << 8) | c.a as u16,
645 }
646 }
647
648 pub fn to_rgba(&self) -> Rgba {
649 Rgba {
650 r: self.r as f64 / 65535.0,
651 g: self.g as f64 / 65535.0,
652 b: self.b as f64 / 65535.0,
653 a: self.a as f64 / 65535.0,
654 }
655 }
656
657 pub fn to_rgba8(&self) -> Rgba8 {
658 Rgba8::new(
659 (self.r >> 8) as u32,
660 (self.g >> 8) as u32,
661 (self.b >> 8) as u32,
662 (self.a >> 8) as u32,
663 )
664 }
665
666 pub fn is_transparent(&self) -> bool {
667 self.a == 0
668 }
669
670 pub fn is_opaque(&self) -> bool {
671 self.a == Self::BASE_MASK as u16
672 }
673
674 pub fn invert(x: u16) -> u16 {
675 Self::BASE_MASK as u16 - x
676 }
677
678 #[inline]
680 pub fn multiply(a: u16, b: u16) -> u16 {
681 let t: u32 = a as u32 * b as u32 + Self::BASE_MSB;
682 (((t >> Self::BASE_SHIFT) + t) >> Self::BASE_SHIFT) as u16
683 }
684
685 #[inline]
687 pub fn lerp(p: u16, q: u16, a: u16) -> u16 {
688 let t = (q as i32 - p as i32) * a as i32 + Self::BASE_MSB as i32 - (p > q) as i32;
689 (p as i32 + (((t >> Self::BASE_SHIFT) + t) >> Self::BASE_SHIFT)) as u16
690 }
691
692 #[inline]
694 pub fn mult_cover(a: u16, b: CoverType) -> u16 {
695 Self::multiply(a, (b as u16) << 8 | b as u16)
696 }
697
698 pub fn clear(&mut self) -> &mut Self {
699 self.r = 0;
700 self.g = 0;
701 self.b = 0;
702 self.a = 0;
703 self
704 }
705
706 pub fn premultiply(&mut self) -> &mut Self {
707 if self.a as u32 != Self::BASE_MASK {
708 if self.a == 0 {
709 self.r = 0;
710 self.g = 0;
711 self.b = 0;
712 } else {
713 self.r = Self::multiply(self.r, self.a);
714 self.g = Self::multiply(self.g, self.a);
715 self.b = Self::multiply(self.b, self.a);
716 }
717 }
718 self
719 }
720
721 pub fn demultiply(&mut self) -> &mut Self {
722 if (self.a as u32) < Self::BASE_MASK {
723 if self.a == 0 {
724 self.r = 0;
725 self.g = 0;
726 self.b = 0;
727 } else {
728 let r_ = (self.r as u32 * Self::BASE_MASK) / self.a as u32;
729 let g_ = (self.g as u32 * Self::BASE_MASK) / self.a as u32;
730 let b_ = (self.b as u32 * Self::BASE_MASK) / self.a as u32;
731 self.r = r_.min(Self::BASE_MASK) as u16;
732 self.g = g_.min(Self::BASE_MASK) as u16;
733 self.b = b_.min(Self::BASE_MASK) as u16;
734 }
735 }
736 self
737 }
738
739 pub fn gradient(&self, c: &Rgba16, k: f64) -> Rgba16 {
740 let ik = uround(k * Self::BASE_MASK as f64) as u16;
741 Rgba16 {
742 r: Self::lerp(self.r, c.r, ik),
743 g: Self::lerp(self.g, c.g, ik),
744 b: Self::lerp(self.b, c.b, ik),
745 a: Self::lerp(self.a, c.a, ik),
746 }
747 }
748
749 pub fn no_color() -> Self {
750 Self {
751 r: 0,
752 g: 0,
753 b: 0,
754 a: 0,
755 }
756 }
757
758 pub fn from_wavelength(wl: f64, gamma: f64) -> Self {
759 Self::from_rgba(&Rgba::from_wavelength(wl, gamma))
760 }
761}
762
763impl Default for Rgba16 {
764 fn default() -> Self {
765 Self::no_color()
766 }
767}
768
769#[derive(Debug, Clone, Copy, PartialEq, Eq)]
776pub struct Gray8 {
777 pub v: u8,
778 pub a: u8,
779}
780
781impl Gray8 {
782 pub const BASE_SHIFT: u32 = 8;
783 pub const BASE_SCALE: u32 = 1 << Self::BASE_SHIFT;
784 pub const BASE_MASK: u32 = Self::BASE_SCALE - 1;
785 pub const BASE_MSB: u32 = 1 << (Self::BASE_SHIFT - 1);
786
787 pub fn new(v: u32, a: u32) -> Self {
788 Self {
789 v: v as u8,
790 a: a as u8,
791 }
792 }
793
794 pub fn new_opaque(v: u32) -> Self {
795 Self::new(v, Self::BASE_MASK)
796 }
797
798 pub fn luminance_from_rgba(c: &Rgba) -> u8 {
800 uround((0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b) * Self::BASE_MASK as f64) as u8
801 }
802
803 pub fn luminance_from_rgba8(c: &Rgba8) -> u8 {
805 ((55u32 * c.r as u32 + 184u32 * c.g as u32 + 18u32 * c.b as u32) >> 8) as u8
806 }
807
808 pub fn from_rgba(c: &Rgba) -> Self {
809 Self {
810 v: Self::luminance_from_rgba(c),
811 a: uround(c.a * Self::BASE_MASK as f64) as u8,
812 }
813 }
814
815 pub fn from_rgba8(c: &Rgba8) -> Self {
816 Self {
817 v: Self::luminance_from_rgba8(c),
818 a: c.a,
819 }
820 }
821
822 pub fn is_transparent(&self) -> bool {
823 self.a == 0
824 }
825
826 pub fn is_opaque(&self) -> bool {
827 self.a == Self::BASE_MASK as u8
828 }
829
830 #[inline]
831 pub fn multiply(a: u8, b: u8) -> u8 {
832 let t: u32 = a as u32 * b as u32 + Self::BASE_MSB;
833 (((t >> Self::BASE_SHIFT) + t) >> Self::BASE_SHIFT) as u8
834 }
835
836 #[inline]
837 pub fn lerp(p: u8, q: u8, a: u8) -> u8 {
838 let t = (q as i32 - p as i32) * a as i32 + Self::BASE_MSB as i32 - (p > q) as i32;
839 (p as i32 + (((t >> Self::BASE_SHIFT) + t) >> Self::BASE_SHIFT)) as u8
840 }
841
842 #[inline]
843 pub fn mult_cover(a: u8, b: CoverType) -> u8 {
844 Self::multiply(a, b)
845 }
846
847 pub fn clear(&mut self) -> &mut Self {
848 self.v = 0;
849 self.a = 0;
850 self
851 }
852
853 pub fn premultiply(&mut self) -> &mut Self {
854 if (self.a as u32) < Self::BASE_MASK {
855 if self.a == 0 {
856 self.v = 0;
857 } else {
858 self.v = Self::multiply(self.v, self.a);
859 }
860 }
861 self
862 }
863
864 pub fn demultiply(&mut self) -> &mut Self {
865 if (self.a as u32) < Self::BASE_MASK {
866 if self.a == 0 {
867 self.v = 0;
868 } else {
869 let v_ = (self.v as u32 * Self::BASE_MASK) / self.a as u32;
870 self.v = v_.min(Self::BASE_MASK) as u8;
871 }
872 }
873 self
874 }
875
876 pub fn gradient(&self, c: &Gray8, k: f64) -> Gray8 {
877 let ik = uround(k * Self::BASE_SCALE as f64) as u8;
878 Gray8 {
879 v: Self::lerp(self.v, c.v, ik),
880 a: Self::lerp(self.a, c.a, ik),
881 }
882 }
883
884 pub fn no_color() -> Self {
885 Self { v: 0, a: 0 }
886 }
887}
888
889impl Default for Gray8 {
890 fn default() -> Self {
891 Self::no_color()
892 }
893}
894
895#[derive(Debug, Clone, Copy, PartialEq, Eq)]
902pub struct Gray16 {
903 pub v: u16,
904 pub a: u16,
905}
906
907impl Gray16 {
908 pub const BASE_SHIFT: u32 = 16;
909 pub const BASE_SCALE: u32 = 1 << Self::BASE_SHIFT;
910 pub const BASE_MASK: u32 = Self::BASE_SCALE - 1;
911 pub const BASE_MSB: u32 = 1 << (Self::BASE_SHIFT - 1);
912
913 pub fn new(v: u32, a: u32) -> Self {
914 Self {
915 v: v as u16,
916 a: a as u16,
917 }
918 }
919
920 pub fn new_opaque(v: u32) -> Self {
921 Self::new(v, Self::BASE_MASK)
922 }
923
924 pub fn luminance_from_rgba(c: &Rgba) -> u16 {
926 uround((0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b) * Self::BASE_MASK as f64) as u16
927 }
928
929 pub fn luminance_from_rgba16(c: &Rgba16) -> u16 {
931 ((13933u32 * c.r as u32 + 46872u32 * c.g as u32 + 4732u32 * c.b as u32) >> 16) as u16
932 }
933
934 pub fn from_rgba(c: &Rgba) -> Self {
935 Self {
936 v: Self::luminance_from_rgba(c),
937 a: uround(c.a * Self::BASE_MASK as f64) as u16,
938 }
939 }
940
941 pub fn from_rgba8(c: &Rgba8) -> Self {
942 Self::from_rgba16(&Rgba16::from_rgba8(c))
943 }
944
945 pub fn from_rgba16(c: &Rgba16) -> Self {
946 Self {
947 v: Self::luminance_from_rgba16(c),
948 a: c.a,
949 }
950 }
951
952 pub fn from_gray8(c: &Gray8) -> Self {
953 Self {
954 v: ((c.v as u16) << 8) | c.v as u16,
955 a: ((c.a as u16) << 8) | c.a as u16,
956 }
957 }
958
959 pub fn is_transparent(&self) -> bool {
960 self.a == 0
961 }
962
963 pub fn is_opaque(&self) -> bool {
964 self.a == Self::BASE_MASK as u16
965 }
966
967 #[inline]
968 pub fn multiply(a: u16, b: u16) -> u16 {
969 let t: u32 = a as u32 * b as u32 + Self::BASE_MSB;
970 (((t >> Self::BASE_SHIFT) + t) >> Self::BASE_SHIFT) as u16
971 }
972
973 #[inline]
974 pub fn lerp(p: u16, q: u16, a: u16) -> u16 {
975 let t = (q as i32 - p as i32) * a as i32 + Self::BASE_MSB as i32 - (p > q) as i32;
976 (p as i32 + (((t >> Self::BASE_SHIFT) + t) >> Self::BASE_SHIFT)) as u16
977 }
978
979 pub fn clear(&mut self) -> &mut Self {
980 self.v = 0;
981 self.a = 0;
982 self
983 }
984
985 pub fn premultiply(&mut self) -> &mut Self {
986 if (self.a as u32) < Self::BASE_MASK {
987 if self.a == 0 {
988 self.v = 0;
989 } else {
990 self.v = Self::multiply(self.v, self.a);
991 }
992 }
993 self
994 }
995
996 pub fn demultiply(&mut self) -> &mut Self {
997 if (self.a as u32) < Self::BASE_MASK {
998 if self.a == 0 {
999 self.v = 0;
1000 } else {
1001 let v_ = (self.v as u32 * Self::BASE_MASK) / self.a as u32;
1002 self.v = v_.min(Self::BASE_MASK) as u16;
1003 }
1004 }
1005 self
1006 }
1007
1008 pub fn gradient(&self, c: &Gray16, k: f64) -> Gray16 {
1009 let ik = uround(k * Self::BASE_SCALE as f64) as u16;
1010 Gray16 {
1011 v: Self::lerp(self.v, c.v, ik),
1012 a: Self::lerp(self.a, c.a, ik),
1013 }
1014 }
1015
1016 pub fn no_color() -> Self {
1017 Self { v: 0, a: 0 }
1018 }
1019}
1020
1021impl Default for Gray16 {
1022 fn default() -> Self {
1023 Self::no_color()
1024 }
1025}
1026
1027#[cfg(test)]
1032mod tests {
1033 use super::*;
1034
1035 #[test]
1036 fn test_rgba_new() {
1037 let c = Rgba::new(0.5, 0.6, 0.7, 0.8);
1038 assert_eq!(c.r, 0.5);
1039 assert_eq!(c.g, 0.6);
1040 assert_eq!(c.b, 0.7);
1041 assert_eq!(c.a, 0.8);
1042 }
1043
1044 #[test]
1045 fn test_rgba_premultiply_demultiply() {
1046 let mut c = Rgba::new(1.0, 0.5, 0.25, 0.5);
1047 c.premultiply();
1048 assert!((c.r - 0.5).abs() < 1e-10);
1049 assert!((c.g - 0.25).abs() < 1e-10);
1050 assert!((c.b - 0.125).abs() < 1e-10);
1051 assert!((c.a - 0.5).abs() < 1e-10);
1052
1053 c.demultiply();
1054 assert!((c.r - 1.0).abs() < 1e-10);
1055 assert!((c.g - 0.5).abs() < 1e-10);
1056 assert!((c.b - 0.25).abs() < 1e-10);
1057 }
1058
1059 #[test]
1060 fn test_rgba_gradient() {
1061 let c1 = Rgba::new(0.0, 0.0, 0.0, 1.0);
1062 let c2 = Rgba::new(1.0, 1.0, 1.0, 1.0);
1063 let mid = c1.gradient(&c2, 0.5);
1064 assert!((mid.r - 0.5).abs() < 1e-10);
1065 assert!((mid.g - 0.5).abs() < 1e-10);
1066 assert!((mid.b - 0.5).abs() < 1e-10);
1067 }
1068
1069 #[test]
1070 fn test_rgba_from_wavelength() {
1071 let c = Rgba::from_wavelength(550.0, 1.0);
1072 assert!(c.r > 0.0);
1074 assert!(c.g > 0.0);
1075 assert!(c.b == 0.0 || c.b < 0.01);
1076 }
1077
1078 #[test]
1079 fn test_rgba_operators() {
1080 let c1 = Rgba::new(0.1, 0.2, 0.3, 0.4);
1081 let c2 = Rgba::new(0.2, 0.3, 0.4, 0.5);
1082 let sum = c1 + c2;
1083 assert!((sum.r - 0.3).abs() < 1e-10);
1084 assert!((sum.g - 0.5).abs() < 1e-10);
1085
1086 let scaled = c1 * 2.0;
1087 assert!((scaled.r - 0.2).abs() < 1e-10);
1088 }
1089
1090 #[test]
1091 fn test_rgba8_new() {
1092 let c = Rgba8::new(128, 64, 32, 255);
1093 assert_eq!(c.r, 128);
1094 assert_eq!(c.g, 64);
1095 assert_eq!(c.b, 32);
1096 assert_eq!(c.a, 255);
1097 }
1098
1099 #[test]
1100 fn test_rgba8_multiply() {
1101 assert_eq!(Rgba8::multiply(255, 255), 255);
1102 assert_eq!(Rgba8::multiply(255, 0), 0);
1103 assert_eq!(Rgba8::multiply(0, 255), 0);
1104 assert_eq!(Rgba8::multiply(128, 255), 128);
1105 }
1106
1107 #[test]
1108 fn test_rgba8_lerp() {
1109 assert_eq!(Rgba8::lerp(0, 255, 128), 128);
1110 assert_eq!(Rgba8::lerp(0, 255, 0), 0);
1111 assert_eq!(Rgba8::lerp(0, 255, 255), 255);
1112 assert_eq!(Rgba8::lerp(100, 200, 128), 150);
1113 }
1114
1115 #[test]
1116 fn test_rgba8_premultiply() {
1117 let mut c = Rgba8::new(255, 128, 64, 128);
1118 c.premultiply();
1119 assert!(c.r > 120 && c.r < 132);
1121 assert!(c.g > 60 && c.g < 68);
1122 assert!(c.b > 28 && c.b < 36);
1123 }
1124
1125 #[test]
1126 fn test_rgba8_demultiply() {
1127 let mut c = Rgba8::new(64, 32, 16, 128);
1128 c.demultiply();
1129 assert!(c.r > 124 && c.r < 132);
1131 assert!(c.g > 60 && c.g < 68);
1132 }
1133
1134 #[test]
1135 fn test_rgba8_from_rgba_roundtrip() {
1136 let orig = Rgba::new(0.5, 0.25, 0.75, 1.0);
1137 let c8 = Rgba8::from_rgba(&orig);
1138 let back = c8.to_rgba();
1139 assert!((orig.r - back.r).abs() < 0.01);
1140 assert!((orig.g - back.g).abs() < 0.01);
1141 assert!((orig.b - back.b).abs() < 0.01);
1142 }
1143
1144 #[test]
1145 fn test_rgba8_gradient() {
1146 let c1 = Rgba8::new(0, 0, 0, 255);
1147 let c2 = Rgba8::new(255, 255, 255, 255);
1148 let mid = c1.gradient(&c2, 0.5);
1149 assert!(mid.r > 125 && mid.r < 130);
1150 assert!(mid.g > 125 && mid.g < 130);
1151 }
1152
1153 #[test]
1154 fn test_rgba8_packed() {
1155 let c = rgb8_packed(0xFF8040);
1156 assert_eq!(c.r, 0xFF);
1157 assert_eq!(c.g, 0x80);
1158 assert_eq!(c.b, 0x40);
1159 assert_eq!(c.a, 255);
1160
1161 let c = bgr8_packed(0xFF8040);
1162 assert_eq!(c.r, 0x40);
1163 assert_eq!(c.g, 0x80);
1164 assert_eq!(c.b, 0xFF);
1165
1166 let c = argb8_packed(0x80FF8040);
1167 assert_eq!(c.a, 0x80);
1168 assert_eq!(c.r, 0xFF);
1169 assert_eq!(c.g, 0x80);
1170 assert_eq!(c.b, 0x40);
1171 }
1172
1173 #[test]
1174 fn test_rgba16_from_rgba8() {
1175 let c8 = Rgba8::new(128, 64, 32, 255);
1176 let c16 = Rgba16::from_rgba8(&c8);
1177 assert_eq!(c16.r, (128 << 8) | 128);
1179 assert_eq!(c16.g, (64 << 8) | 64);
1180 }
1181
1182 #[test]
1183 fn test_rgba16_multiply() {
1184 assert_eq!(Rgba16::multiply(65535, 65535), 65535);
1185 assert_eq!(Rgba16::multiply(65535, 0), 0);
1186 }
1187
1188 #[test]
1189 fn test_gray8_luminance() {
1190 let white = Rgba8::new(255, 255, 255, 255);
1191 let lum = Gray8::luminance_from_rgba8(&white);
1192 assert!(lum > 250);
1194
1195 let black = Rgba8::new(0, 0, 0, 255);
1196 let lum = Gray8::luminance_from_rgba8(&black);
1197 assert_eq!(lum, 0);
1198 }
1199
1200 #[test]
1201 fn test_gray8_premultiply() {
1202 let mut g = Gray8::new(200, 128);
1203 g.premultiply();
1204 assert!(g.v > 95 && g.v < 105);
1206 }
1207
1208 #[test]
1209 fn test_gray16_from_gray8() {
1210 let g8 = Gray8::new(128, 255);
1211 let g16 = Gray16::from_gray8(&g8);
1212 assert_eq!(g16.v, (128 << 8) | 128);
1213 assert_eq!(g16.a, (255 << 8) | 255);
1214 }
1215
1216 #[test]
1217 fn test_component_orders() {
1218 assert_eq!(OrderRgba::R, 0);
1219 assert_eq!(OrderRgba::G, 1);
1220 assert_eq!(OrderRgba::B, 2);
1221 assert_eq!(OrderRgba::A, 3);
1222 assert_eq!(OrderBgra::B, 0);
1223 assert_eq!(OrderBgra::G, 1);
1224 assert_eq!(OrderBgra::R, 2);
1225 assert_eq!(OrderBgra::A, 3);
1226 }
1227}