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 pub fn to_double(a: u8) -> f64 {
352 a as f64 / Self::BASE_MASK as f64
353 }
354
355 pub fn from_double(a: f64) -> u8 {
356 uround(a * Self::BASE_MASK as f64) as u8
357 }
358
359 pub fn empty_value() -> u8 {
360 0
361 }
362
363 pub fn full_value() -> u8 {
364 Self::BASE_MASK as u8
365 }
366
367 pub fn is_transparent(&self) -> bool {
368 self.a == 0
369 }
370
371 pub fn is_opaque(&self) -> bool {
372 self.a == Self::BASE_MASK as u8
373 }
374
375 pub fn invert(x: u8) -> u8 {
376 Self::BASE_MASK as u8 - x
377 }
378
379 #[inline]
382 pub fn multiply(a: u8, b: u8) -> u8 {
383 let t: u32 = a as u32 * b as u32 + Self::BASE_MSB;
384 (((t >> Self::BASE_SHIFT) + t) >> Self::BASE_SHIFT) as u8
385 }
386
387 #[inline]
389 pub fn demultiply_value(a: u8, b: u8) -> u8 {
390 if (a as u32) * (b as u32) == 0 {
391 0
392 } else if a >= b {
393 Self::BASE_MASK as u8
394 } else {
395 (a as u32 * Self::BASE_MASK + (b as u32 >> 1)) as u8 / b
396 }
397 }
398
399 #[inline]
401 pub fn mult_cover(a: u8, b: CoverType) -> u8 {
402 Self::multiply(a, b)
403 }
404
405 #[inline]
407 pub fn scale_cover(a: CoverType, b: u8) -> CoverType {
408 Self::multiply(b, a)
409 }
410
411 #[inline]
413 pub fn prelerp(p: u8, q: u8, a: u8) -> u8 {
414 p.wrapping_add(q).wrapping_sub(Self::multiply(p, a))
415 }
416
417 #[inline]
419 pub fn lerp(p: u8, q: u8, a: u8) -> u8 {
420 let t = (q as i32 - p as i32) * a as i32 + Self::BASE_MSB as i32 - (p > q) as i32;
421 (p as i32 + (((t >> Self::BASE_SHIFT) + t) >> Self::BASE_SHIFT)) as u8
422 }
423
424 pub fn clear(&mut self) -> &mut Self {
425 self.r = 0;
426 self.g = 0;
427 self.b = 0;
428 self.a = 0;
429 self
430 }
431
432 pub fn transparent(&mut self) -> &mut Self {
433 self.a = 0;
434 self
435 }
436
437 pub fn set_opacity(&mut self, a: f64) -> &mut Self {
438 if a < 0.0 {
439 self.a = 0;
440 } else if a > 1.0 {
441 self.a = 1;
442 } else {
443 self.a = uround(a * Self::BASE_MASK as f64) as u8;
444 }
445 self
446 }
447
448 pub fn opacity(&self) -> f64 {
449 self.a as f64 / Self::BASE_MASK as f64
450 }
451
452 pub fn premultiply(&mut self) -> &mut Self {
453 if self.a != Self::BASE_MASK as u8 {
454 if self.a == 0 {
455 self.r = 0;
456 self.g = 0;
457 self.b = 0;
458 } else {
459 self.r = Self::multiply(self.r, self.a);
460 self.g = Self::multiply(self.g, self.a);
461 self.b = Self::multiply(self.b, self.a);
462 }
463 }
464 self
465 }
466
467 pub fn premultiply_with_alpha(&mut self, a_: u32) -> &mut Self {
468 if self.a as u32 != Self::BASE_MASK || a_ < Self::BASE_MASK {
469 if self.a == 0 || a_ == 0 {
470 self.r = 0;
471 self.g = 0;
472 self.b = 0;
473 self.a = 0;
474 } else {
475 let r_ = (self.r as u32 * a_) / self.a as u32;
476 let g_ = (self.g as u32 * a_) / self.a as u32;
477 let b_ = (self.b as u32 * a_) / self.a as u32;
478 self.r = if r_ > a_ { a_ as u8 } else { r_ as u8 };
479 self.g = if g_ > a_ { a_ as u8 } else { g_ as u8 };
480 self.b = if b_ > a_ { a_ as u8 } else { b_ as u8 };
481 self.a = a_ as u8;
482 }
483 }
484 self
485 }
486
487 pub fn demultiply(&mut self) -> &mut Self {
488 if (self.a as u32) < Self::BASE_MASK {
489 if self.a == 0 {
490 self.r = 0;
491 self.g = 0;
492 self.b = 0;
493 } else {
494 let r_ = (self.r as u32 * Self::BASE_MASK) / self.a as u32;
495 let g_ = (self.g as u32 * Self::BASE_MASK) / self.a as u32;
496 let b_ = (self.b as u32 * Self::BASE_MASK) / self.a as u32;
497 self.r = r_.min(Self::BASE_MASK) as u8;
498 self.g = g_.min(Self::BASE_MASK) as u8;
499 self.b = b_.min(Self::BASE_MASK) as u8;
500 }
501 }
502 self
503 }
504
505 pub fn gradient(&self, c: &Rgba8, k: f64) -> Rgba8 {
507 let ik = uround(k * Self::BASE_MASK as f64) as u8;
508 Rgba8 {
509 r: Self::lerp(self.r, c.r, ik),
510 g: Self::lerp(self.g, c.g, ik),
511 b: Self::lerp(self.b, c.b, ik),
512 a: Self::lerp(self.a, c.a, ik),
513 }
514 }
515
516 pub fn add(&mut self, c: &Rgba8, cover: u32) {
518 let cr: u32;
519 let cg: u32;
520 let cb: u32;
521 let ca: u32;
522 if cover == COVER_MASK {
523 if c.a as u32 == Self::BASE_MASK {
524 *self = *c;
525 return;
526 } else {
527 cr = self.r as u32 + c.r as u32;
528 cg = self.g as u32 + c.g as u32;
529 cb = self.b as u32 + c.b as u32;
530 ca = self.a as u32 + c.a as u32;
531 }
532 } else {
533 cr = self.r as u32 + Self::mult_cover(c.r, cover as u8) as u32;
534 cg = self.g as u32 + Self::mult_cover(c.g, cover as u8) as u32;
535 cb = self.b as u32 + Self::mult_cover(c.b, cover as u8) as u32;
536 ca = self.a as u32 + Self::mult_cover(c.a, cover as u8) as u32;
537 }
538 self.r = cr.min(Self::BASE_MASK) as u8;
539 self.g = cg.min(Self::BASE_MASK) as u8;
540 self.b = cb.min(Self::BASE_MASK) as u8;
541 self.a = ca.min(Self::BASE_MASK) as u8;
542 }
543
544 pub fn apply_gamma_dir(&mut self, gamma: &crate::gamma::GammaLut) {
546 self.r = gamma.dir(self.r);
547 self.g = gamma.dir(self.g);
548 self.b = gamma.dir(self.b);
549 }
550
551 pub fn apply_gamma_inv(&mut self, gamma: &crate::gamma::GammaLut) {
553 self.r = gamma.inv(self.r);
554 self.g = gamma.inv(self.g);
555 self.b = gamma.inv(self.b);
556 }
557
558 pub fn no_color() -> Self {
559 Self {
560 r: 0,
561 g: 0,
562 b: 0,
563 a: 0,
564 }
565 }
566
567 pub fn from_wavelength(wl: f64, gamma: f64) -> Self {
568 Self::from_rgba(&Rgba::from_wavelength(wl, gamma))
569 }
570}
571
572impl Default for Rgba8 {
573 fn default() -> Self {
574 Self::no_color()
575 }
576}
577
578pub fn rgb8_packed(v: u32) -> Rgba8 {
580 Rgba8::new((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF, 255)
581}
582
583pub fn bgr8_packed(v: u32) -> Rgba8 {
585 Rgba8::new(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF, 255)
586}
587
588pub fn argb8_packed(v: u32) -> Rgba8 {
590 Rgba8::new((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF, v >> 24)
591}
592
593#[derive(Debug, Clone, Copy, PartialEq, Eq)]
600pub struct Rgba16 {
601 pub r: u16,
602 pub g: u16,
603 pub b: u16,
604 pub a: u16,
605}
606
607impl Rgba16 {
608 pub const BASE_SHIFT: u32 = 16;
609 pub const BASE_SCALE: u32 = 1 << Self::BASE_SHIFT;
610 pub const BASE_MASK: u32 = Self::BASE_SCALE - 1;
611 pub const BASE_MSB: u32 = 1 << (Self::BASE_SHIFT - 1);
612
613 pub fn new(r: u32, g: u32, b: u32, a: u32) -> Self {
614 Self {
615 r: r as u16,
616 g: g as u16,
617 b: b as u16,
618 a: a as u16,
619 }
620 }
621
622 pub fn new_opaque(r: u32, g: u32, b: u32) -> Self {
623 Self::new(r, g, b, Self::BASE_MASK)
624 }
625
626 pub fn from_rgba(c: &Rgba) -> Self {
628 Self {
629 r: uround(c.r * Self::BASE_MASK as f64) as u16,
630 g: uround(c.g * Self::BASE_MASK as f64) as u16,
631 b: uround(c.b * Self::BASE_MASK as f64) as u16,
632 a: uround(c.a * Self::BASE_MASK as f64) as u16,
633 }
634 }
635
636 pub fn from_rgba8(c: &Rgba8) -> Self {
638 Self {
639 r: ((c.r as u16) << 8) | c.r as u16,
640 g: ((c.g as u16) << 8) | c.g as u16,
641 b: ((c.b as u16) << 8) | c.b as u16,
642 a: ((c.a as u16) << 8) | c.a as u16,
643 }
644 }
645
646 pub fn to_rgba(&self) -> Rgba {
647 Rgba {
648 r: self.r as f64 / 65535.0,
649 g: self.g as f64 / 65535.0,
650 b: self.b as f64 / 65535.0,
651 a: self.a as f64 / 65535.0,
652 }
653 }
654
655 pub fn to_rgba8(&self) -> Rgba8 {
656 Rgba8::new(
657 (self.r >> 8) as u32,
658 (self.g >> 8) as u32,
659 (self.b >> 8) as u32,
660 (self.a >> 8) as u32,
661 )
662 }
663
664 pub fn is_transparent(&self) -> bool {
665 self.a == 0
666 }
667
668 pub fn is_opaque(&self) -> bool {
669 self.a == Self::BASE_MASK as u16
670 }
671
672 pub fn invert(x: u16) -> u16 {
673 Self::BASE_MASK as u16 - x
674 }
675
676 #[inline]
678 pub fn multiply(a: u16, b: u16) -> u16 {
679 let t: u32 = a as u32 * b as u32 + Self::BASE_MSB;
680 (((t >> Self::BASE_SHIFT) + t) >> Self::BASE_SHIFT) as u16
681 }
682
683 #[inline]
685 pub fn lerp(p: u16, q: u16, a: u16) -> u16 {
686 let t = (q as i32 - p as i32) * a as i32 + Self::BASE_MSB as i32 - (p > q) as i32;
687 (p as i32 + (((t >> Self::BASE_SHIFT) + t) >> Self::BASE_SHIFT)) as u16
688 }
689
690 #[inline]
692 pub fn mult_cover(a: u16, b: CoverType) -> u16 {
693 Self::multiply(a, (b as u16) << 8 | b as u16)
694 }
695
696 pub fn clear(&mut self) -> &mut Self {
697 self.r = 0;
698 self.g = 0;
699 self.b = 0;
700 self.a = 0;
701 self
702 }
703
704 pub fn premultiply(&mut self) -> &mut Self {
705 if self.a as u32 != Self::BASE_MASK {
706 if self.a == 0 {
707 self.r = 0;
708 self.g = 0;
709 self.b = 0;
710 } else {
711 self.r = Self::multiply(self.r, self.a);
712 self.g = Self::multiply(self.g, self.a);
713 self.b = Self::multiply(self.b, self.a);
714 }
715 }
716 self
717 }
718
719 pub fn demultiply(&mut self) -> &mut Self {
720 if (self.a as u32) < Self::BASE_MASK {
721 if self.a == 0 {
722 self.r = 0;
723 self.g = 0;
724 self.b = 0;
725 } else {
726 let r_ = (self.r as u32 * Self::BASE_MASK) / self.a as u32;
727 let g_ = (self.g as u32 * Self::BASE_MASK) / self.a as u32;
728 let b_ = (self.b as u32 * Self::BASE_MASK) / self.a as u32;
729 self.r = r_.min(Self::BASE_MASK) as u16;
730 self.g = g_.min(Self::BASE_MASK) as u16;
731 self.b = b_.min(Self::BASE_MASK) as u16;
732 }
733 }
734 self
735 }
736
737 pub fn gradient(&self, c: &Rgba16, k: f64) -> Rgba16 {
738 let ik = uround(k * Self::BASE_MASK as f64) as u16;
739 Rgba16 {
740 r: Self::lerp(self.r, c.r, ik),
741 g: Self::lerp(self.g, c.g, ik),
742 b: Self::lerp(self.b, c.b, ik),
743 a: Self::lerp(self.a, c.a, ik),
744 }
745 }
746
747 pub fn no_color() -> Self {
748 Self {
749 r: 0,
750 g: 0,
751 b: 0,
752 a: 0,
753 }
754 }
755
756 pub fn from_wavelength(wl: f64, gamma: f64) -> Self {
757 Self::from_rgba(&Rgba::from_wavelength(wl, gamma))
758 }
759}
760
761impl Default for Rgba16 {
762 fn default() -> Self {
763 Self::no_color()
764 }
765}
766
767#[derive(Debug, Clone, Copy, PartialEq, Eq)]
774pub struct Gray8 {
775 pub v: u8,
776 pub a: u8,
777}
778
779impl Gray8 {
780 pub const BASE_SHIFT: u32 = 8;
781 pub const BASE_SCALE: u32 = 1 << Self::BASE_SHIFT;
782 pub const BASE_MASK: u32 = Self::BASE_SCALE - 1;
783 pub const BASE_MSB: u32 = 1 << (Self::BASE_SHIFT - 1);
784
785 pub fn new(v: u32, a: u32) -> Self {
786 Self {
787 v: v as u8,
788 a: a as u8,
789 }
790 }
791
792 pub fn new_opaque(v: u32) -> Self {
793 Self::new(v, Self::BASE_MASK)
794 }
795
796 pub fn luminance_from_rgba(c: &Rgba) -> u8 {
798 uround((0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b) * Self::BASE_MASK as f64) as u8
799 }
800
801 pub fn luminance_from_rgba8(c: &Rgba8) -> u8 {
803 ((55u32 * c.r as u32 + 184u32 * c.g as u32 + 18u32 * c.b as u32) >> 8) as u8
804 }
805
806 pub fn from_rgba(c: &Rgba) -> Self {
807 Self {
808 v: Self::luminance_from_rgba(c),
809 a: uround(c.a * Self::BASE_MASK as f64) as u8,
810 }
811 }
812
813 pub fn from_rgba8(c: &Rgba8) -> Self {
814 Self {
815 v: Self::luminance_from_rgba8(c),
816 a: c.a,
817 }
818 }
819
820 pub fn is_transparent(&self) -> bool {
821 self.a == 0
822 }
823
824 pub fn is_opaque(&self) -> bool {
825 self.a == Self::BASE_MASK as u8
826 }
827
828 #[inline]
829 pub fn multiply(a: u8, b: u8) -> u8 {
830 let t: u32 = a as u32 * b as u32 + Self::BASE_MSB;
831 (((t >> Self::BASE_SHIFT) + t) >> Self::BASE_SHIFT) as u8
832 }
833
834 #[inline]
835 pub fn lerp(p: u8, q: u8, a: u8) -> u8 {
836 let t = (q as i32 - p as i32) * a as i32 + Self::BASE_MSB as i32 - (p > q) as i32;
837 (p as i32 + (((t >> Self::BASE_SHIFT) + t) >> Self::BASE_SHIFT)) as u8
838 }
839
840 #[inline]
841 pub fn mult_cover(a: u8, b: CoverType) -> u8 {
842 Self::multiply(a, b)
843 }
844
845 pub fn clear(&mut self) -> &mut Self {
846 self.v = 0;
847 self.a = 0;
848 self
849 }
850
851 pub fn premultiply(&mut self) -> &mut Self {
852 if (self.a as u32) < Self::BASE_MASK {
853 if self.a == 0 {
854 self.v = 0;
855 } else {
856 self.v = Self::multiply(self.v, self.a);
857 }
858 }
859 self
860 }
861
862 pub fn demultiply(&mut self) -> &mut Self {
863 if (self.a as u32) < Self::BASE_MASK {
864 if self.a == 0 {
865 self.v = 0;
866 } else {
867 let v_ = (self.v as u32 * Self::BASE_MASK) / self.a as u32;
868 self.v = v_.min(Self::BASE_MASK) as u8;
869 }
870 }
871 self
872 }
873
874 pub fn gradient(&self, c: &Gray8, k: f64) -> Gray8 {
875 let ik = uround(k * Self::BASE_SCALE as f64) as u8;
876 Gray8 {
877 v: Self::lerp(self.v, c.v, ik),
878 a: Self::lerp(self.a, c.a, ik),
879 }
880 }
881
882 pub fn no_color() -> Self {
883 Self { v: 0, a: 0 }
884 }
885}
886
887impl Default for Gray8 {
888 fn default() -> Self {
889 Self::no_color()
890 }
891}
892
893#[derive(Debug, Clone, Copy, PartialEq, Eq)]
900pub struct Gray16 {
901 pub v: u16,
902 pub a: u16,
903}
904
905impl Gray16 {
906 pub const BASE_SHIFT: u32 = 16;
907 pub const BASE_SCALE: u32 = 1 << Self::BASE_SHIFT;
908 pub const BASE_MASK: u32 = Self::BASE_SCALE - 1;
909 pub const BASE_MSB: u32 = 1 << (Self::BASE_SHIFT - 1);
910
911 pub fn new(v: u32, a: u32) -> Self {
912 Self {
913 v: v as u16,
914 a: a as u16,
915 }
916 }
917
918 pub fn new_opaque(v: u32) -> Self {
919 Self::new(v, Self::BASE_MASK)
920 }
921
922 pub fn luminance_from_rgba(c: &Rgba) -> u16 {
924 uround((0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b) * Self::BASE_MASK as f64) as u16
925 }
926
927 pub fn luminance_from_rgba16(c: &Rgba16) -> u16 {
929 ((13933u32 * c.r as u32 + 46872u32 * c.g as u32 + 4732u32 * c.b as u32) >> 16) as u16
930 }
931
932 pub fn from_rgba(c: &Rgba) -> Self {
933 Self {
934 v: Self::luminance_from_rgba(c),
935 a: uround(c.a * Self::BASE_MASK as f64) as u16,
936 }
937 }
938
939 pub fn from_rgba8(c: &Rgba8) -> Self {
940 Self::from_rgba16(&Rgba16::from_rgba8(c))
941 }
942
943 pub fn from_rgba16(c: &Rgba16) -> Self {
944 Self {
945 v: Self::luminance_from_rgba16(c),
946 a: c.a,
947 }
948 }
949
950 pub fn from_gray8(c: &Gray8) -> Self {
951 Self {
952 v: ((c.v as u16) << 8) | c.v as u16,
953 a: ((c.a as u16) << 8) | c.a as u16,
954 }
955 }
956
957 pub fn is_transparent(&self) -> bool {
958 self.a == 0
959 }
960
961 pub fn is_opaque(&self) -> bool {
962 self.a == Self::BASE_MASK as u16
963 }
964
965 #[inline]
966 pub fn multiply(a: u16, b: u16) -> u16 {
967 let t: u32 = a as u32 * b as u32 + Self::BASE_MSB;
968 (((t >> Self::BASE_SHIFT) + t) >> Self::BASE_SHIFT) as u16
969 }
970
971 #[inline]
972 pub fn lerp(p: u16, q: u16, a: u16) -> u16 {
973 let t = (q as i32 - p as i32) * a as i32 + Self::BASE_MSB as i32 - (p > q) as i32;
974 (p as i32 + (((t >> Self::BASE_SHIFT) + t) >> Self::BASE_SHIFT)) as u16
975 }
976
977 pub fn clear(&mut self) -> &mut Self {
978 self.v = 0;
979 self.a = 0;
980 self
981 }
982
983 pub fn premultiply(&mut self) -> &mut Self {
984 if (self.a as u32) < Self::BASE_MASK {
985 if self.a == 0 {
986 self.v = 0;
987 } else {
988 self.v = Self::multiply(self.v, self.a);
989 }
990 }
991 self
992 }
993
994 pub fn demultiply(&mut self) -> &mut Self {
995 if (self.a as u32) < Self::BASE_MASK {
996 if self.a == 0 {
997 self.v = 0;
998 } else {
999 let v_ = (self.v as u32 * Self::BASE_MASK) / self.a as u32;
1000 self.v = v_.min(Self::BASE_MASK) as u16;
1001 }
1002 }
1003 self
1004 }
1005
1006 pub fn gradient(&self, c: &Gray16, k: f64) -> Gray16 {
1007 let ik = uround(k * Self::BASE_SCALE as f64) as u16;
1008 Gray16 {
1009 v: Self::lerp(self.v, c.v, ik),
1010 a: Self::lerp(self.a, c.a, ik),
1011 }
1012 }
1013
1014 pub fn no_color() -> Self {
1015 Self { v: 0, a: 0 }
1016 }
1017}
1018
1019impl Default for Gray16 {
1020 fn default() -> Self {
1021 Self::no_color()
1022 }
1023}
1024
1025#[cfg(test)]
1030mod tests {
1031 use super::*;
1032
1033 #[test]
1034 fn test_rgba_new() {
1035 let c = Rgba::new(0.5, 0.6, 0.7, 0.8);
1036 assert_eq!(c.r, 0.5);
1037 assert_eq!(c.g, 0.6);
1038 assert_eq!(c.b, 0.7);
1039 assert_eq!(c.a, 0.8);
1040 }
1041
1042 #[test]
1043 fn test_rgba_premultiply_demultiply() {
1044 let mut c = Rgba::new(1.0, 0.5, 0.25, 0.5);
1045 c.premultiply();
1046 assert!((c.r - 0.5).abs() < 1e-10);
1047 assert!((c.g - 0.25).abs() < 1e-10);
1048 assert!((c.b - 0.125).abs() < 1e-10);
1049 assert!((c.a - 0.5).abs() < 1e-10);
1050
1051 c.demultiply();
1052 assert!((c.r - 1.0).abs() < 1e-10);
1053 assert!((c.g - 0.5).abs() < 1e-10);
1054 assert!((c.b - 0.25).abs() < 1e-10);
1055 }
1056
1057 #[test]
1058 fn test_rgba_gradient() {
1059 let c1 = Rgba::new(0.0, 0.0, 0.0, 1.0);
1060 let c2 = Rgba::new(1.0, 1.0, 1.0, 1.0);
1061 let mid = c1.gradient(&c2, 0.5);
1062 assert!((mid.r - 0.5).abs() < 1e-10);
1063 assert!((mid.g - 0.5).abs() < 1e-10);
1064 assert!((mid.b - 0.5).abs() < 1e-10);
1065 }
1066
1067 #[test]
1068 fn test_rgba_from_wavelength() {
1069 let c = Rgba::from_wavelength(550.0, 1.0);
1070 assert!(c.r > 0.0);
1072 assert!(c.g > 0.0);
1073 assert!(c.b == 0.0 || c.b < 0.01);
1074 }
1075
1076 #[test]
1077 fn test_rgba_operators() {
1078 let c1 = Rgba::new(0.1, 0.2, 0.3, 0.4);
1079 let c2 = Rgba::new(0.2, 0.3, 0.4, 0.5);
1080 let sum = c1 + c2;
1081 assert!((sum.r - 0.3).abs() < 1e-10);
1082 assert!((sum.g - 0.5).abs() < 1e-10);
1083
1084 let scaled = c1 * 2.0;
1085 assert!((scaled.r - 0.2).abs() < 1e-10);
1086 }
1087
1088 #[test]
1089 fn test_rgba8_new() {
1090 let c = Rgba8::new(128, 64, 32, 255);
1091 assert_eq!(c.r, 128);
1092 assert_eq!(c.g, 64);
1093 assert_eq!(c.b, 32);
1094 assert_eq!(c.a, 255);
1095 }
1096
1097 #[test]
1098 fn test_rgba8_multiply() {
1099 assert_eq!(Rgba8::multiply(255, 255), 255);
1100 assert_eq!(Rgba8::multiply(255, 0), 0);
1101 assert_eq!(Rgba8::multiply(0, 255), 0);
1102 assert_eq!(Rgba8::multiply(128, 255), 128);
1103 }
1104
1105 #[test]
1106 fn test_rgba8_lerp() {
1107 assert_eq!(Rgba8::lerp(0, 255, 128), 128);
1108 assert_eq!(Rgba8::lerp(0, 255, 0), 0);
1109 assert_eq!(Rgba8::lerp(0, 255, 255), 255);
1110 assert_eq!(Rgba8::lerp(100, 200, 128), 150);
1111 }
1112
1113 #[test]
1114 fn test_rgba8_premultiply() {
1115 let mut c = Rgba8::new(255, 128, 64, 128);
1116 c.premultiply();
1117 assert!(c.r > 120 && c.r < 132);
1119 assert!(c.g > 60 && c.g < 68);
1120 assert!(c.b > 28 && c.b < 36);
1121 }
1122
1123 #[test]
1124 fn test_rgba8_demultiply() {
1125 let mut c = Rgba8::new(64, 32, 16, 128);
1126 c.demultiply();
1127 assert!(c.r > 124 && c.r < 132);
1129 assert!(c.g > 60 && c.g < 68);
1130 }
1131
1132 #[test]
1133 fn test_rgba8_from_rgba_roundtrip() {
1134 let orig = Rgba::new(0.5, 0.25, 0.75, 1.0);
1135 let c8 = Rgba8::from_rgba(&orig);
1136 let back = c8.to_rgba();
1137 assert!((orig.r - back.r).abs() < 0.01);
1138 assert!((orig.g - back.g).abs() < 0.01);
1139 assert!((orig.b - back.b).abs() < 0.01);
1140 }
1141
1142 #[test]
1143 fn test_rgba8_gradient() {
1144 let c1 = Rgba8::new(0, 0, 0, 255);
1145 let c2 = Rgba8::new(255, 255, 255, 255);
1146 let mid = c1.gradient(&c2, 0.5);
1147 assert!(mid.r > 125 && mid.r < 130);
1148 assert!(mid.g > 125 && mid.g < 130);
1149 }
1150
1151 #[test]
1152 fn test_rgba8_packed() {
1153 let c = rgb8_packed(0xFF8040);
1154 assert_eq!(c.r, 0xFF);
1155 assert_eq!(c.g, 0x80);
1156 assert_eq!(c.b, 0x40);
1157 assert_eq!(c.a, 255);
1158
1159 let c = bgr8_packed(0xFF8040);
1160 assert_eq!(c.r, 0x40);
1161 assert_eq!(c.g, 0x80);
1162 assert_eq!(c.b, 0xFF);
1163
1164 let c = argb8_packed(0x80FF8040);
1165 assert_eq!(c.a, 0x80);
1166 assert_eq!(c.r, 0xFF);
1167 assert_eq!(c.g, 0x80);
1168 assert_eq!(c.b, 0x40);
1169 }
1170
1171 #[test]
1172 fn test_rgba16_from_rgba8() {
1173 let c8 = Rgba8::new(128, 64, 32, 255);
1174 let c16 = Rgba16::from_rgba8(&c8);
1175 assert_eq!(c16.r, (128 << 8) | 128);
1177 assert_eq!(c16.g, (64 << 8) | 64);
1178 }
1179
1180 #[test]
1181 fn test_rgba16_multiply() {
1182 assert_eq!(Rgba16::multiply(65535, 65535), 65535);
1183 assert_eq!(Rgba16::multiply(65535, 0), 0);
1184 }
1185
1186 #[test]
1187 fn test_gray8_luminance() {
1188 let white = Rgba8::new(255, 255, 255, 255);
1189 let lum = Gray8::luminance_from_rgba8(&white);
1190 assert!(lum > 250);
1192
1193 let black = Rgba8::new(0, 0, 0, 255);
1194 let lum = Gray8::luminance_from_rgba8(&black);
1195 assert_eq!(lum, 0);
1196 }
1197
1198 #[test]
1199 fn test_gray8_premultiply() {
1200 let mut g = Gray8::new(200, 128);
1201 g.premultiply();
1202 assert!(g.v > 95 && g.v < 105);
1204 }
1205
1206 #[test]
1207 fn test_gray16_from_gray8() {
1208 let g8 = Gray8::new(128, 255);
1209 let g16 = Gray16::from_gray8(&g8);
1210 assert_eq!(g16.v, (128 << 8) | 128);
1211 assert_eq!(g16.a, (255 << 8) | 255);
1212 }
1213
1214 #[test]
1215 fn test_component_orders() {
1216 assert_eq!(OrderRgba::R, 0);
1217 assert_eq!(OrderRgba::G, 1);
1218 assert_eq!(OrderRgba::B, 2);
1219 assert_eq!(OrderRgba::A, 3);
1220 assert_eq!(OrderBgra::B, 0);
1221 assert_eq!(OrderBgra::G, 1);
1222 assert_eq!(OrderBgra::R, 2);
1223 assert_eq!(OrderBgra::A, 3);
1224 }
1225}