xref: /haiku/headers/libs/agg/agg_color_rgba.h (revision e39da397f5ff79f2db9f9a3ddf1852b6710578af)
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
5 // Permission to copy, use, modify, sell and distribute this software
6 // is granted provided this copyright notice appears in all copies.
7 // This software is provided "as is" without express or implied
8 // warranty, and with no claim as to its suitability for any purpose.
9 //
10 //----------------------------------------------------------------------------
11 //
12 // Adaptation for high precision colors has been sponsored by
13 // Liberty Technology Systems, Inc., visit http://lib-sys.com
14 //
15 // Liberty Technology Systems, Inc. is the provider of
16 // PostScript and PDF technology for software developers.
17 //
18 //----------------------------------------------------------------------------
19 // Contact: mcseem@antigrain.com
20 //          mcseemagg@yahoo.com
21 //          http://www.antigrain.com
22 //----------------------------------------------------------------------------
23 
24 #ifndef AGG_COLOR_RGBA_INCLUDED
25 #define AGG_COLOR_RGBA_INCLUDED
26 
27 #include <math.h>
28 #include "agg_basics.h"
29 
30 namespace agg
31 {
32     // Supported byte orders for RGB and RGBA pixel formats
33     //=======================================================================
34     struct order_rgb  { enum rgb_e  { R=0, G=1, B=2, rgb_tag }; };       //----order_rgb
35     struct order_bgr  { enum bgr_e  { B=0, G=1, R=2, rgb_tag }; };       //----order_bgr
36     struct order_rgba { enum rgba_e { R=0, G=1, B=2, A=3, rgba_tag }; }; //----order_rgba
37     struct order_argb { enum argb_e { A=0, R=1, G=2, B=3, rgba_tag }; }; //----order_argb
38     struct order_abgr { enum abgr_e { A=0, B=1, G=2, R=3, rgba_tag }; }; //----order_abgr
39     struct order_bgra { enum bgra_e { B=0, G=1, R=2, A=3, rgba_tag }; }; //----order_bgra
40 
41     //====================================================================rgba
42     struct rgba
43     {
44         typedef double value_type;
45 
46         double r;
47         double g;
48         double b;
49         double a;
50 
51         //--------------------------------------------------------------------
rgbargba52         rgba() {}
53 
54         //--------------------------------------------------------------------
55         rgba(double r_, double g_, double b_, double a_=1.0) :
rrgba56             r(r_), g(g_), b(b_), a(a_) {}
57 
58         //--------------------------------------------------------------------
rgbargba59         rgba(const rgba& c, double a_) : r(c.r), g(c.g), b(c.b), a(a_) {}
60 
61         //--------------------------------------------------------------------
clearrgba62         void clear()
63         {
64             r = g = b = a = 0;
65         }
66 
67         //--------------------------------------------------------------------
transparentrgba68         const rgba& transparent()
69         {
70             a = 0.0;
71             return *this;
72         }
73 
74         //--------------------------------------------------------------------
opacityrgba75         const rgba& opacity(double a_)
76         {
77             if(a_ < 0.0) a_ = 0.0;
78             if(a_ > 1.0) a_ = 1.0;
79             a = a_;
80             return *this;
81         }
82 
83         //--------------------------------------------------------------------
opacityrgba84         double opacity() const
85         {
86             return a;
87         }
88 
89         //--------------------------------------------------------------------
premultiplyrgba90         const rgba& premultiply()
91         {
92             r *= a;
93             g *= a;
94             b *= a;
95             return *this;
96         }
97 
98         //--------------------------------------------------------------------
premultiplyrgba99         const rgba& premultiply(double a_)
100         {
101             if(a <= 0.0 || a_ <= 0.0)
102             {
103                 r = g = b = a = 0.0;
104                 return *this;
105             }
106             a_ /= a;
107             r *= a_;
108             g *= a_;
109             b *= a_;
110             a  = a_;
111             return *this;
112         }
113 
114         //--------------------------------------------------------------------
demultiplyrgba115         const rgba& demultiply()
116         {
117             if(a == 0)
118             {
119                 r = g = b = 0;
120                 return *this;
121             }
122             double a_ = 1.0 / a;
123             r *= a_;
124             g *= a_;
125             b *= a_;
126             return *this;
127         }
128 
129 
130         //--------------------------------------------------------------------
gradientrgba131         rgba gradient(rgba c, double k) const
132         {
133             rgba ret;
134             ret.r = r + (c.r - r) * k;
135             ret.g = g + (c.g - g) * k;
136             ret.b = b + (c.b - b) * k;
137             ret.a = a + (c.a - a) * k;
138             return ret;
139         }
140 
141         //--------------------------------------------------------------------
no_colorrgba142         static rgba no_color() { return rgba(0,0,0,0); }
143 
144         //--------------------------------------------------------------------
145         static rgba from_wavelength(double wl, double gamma = 1.0);
146 
147         //--------------------------------------------------------------------
148         explicit rgba(double wavelen, double gamma=1.0)
149         {
150             *this = from_wavelength(wavelen, gamma);
151         }
152 
153     };
154 
155     //----------------------------------------------------------------rgba_pre
156     inline rgba rgba_pre(double r, double g, double b, double a=1.0)
157     {
158         return rgba(r, g, b, a).premultiply();
159     }
rgba_pre(const rgba & c)160     inline rgba rgba_pre(const rgba& c)
161     {
162         return rgba(c).premultiply();
163     }
rgba_pre(const rgba & c,double a)164     inline rgba rgba_pre(const rgba& c, double a)
165     {
166         return rgba(c, a).premultiply();
167     }
168 
169     //------------------------------------------------------------------------
from_wavelength(double wl,double gamma)170     inline rgba rgba::from_wavelength(double wl, double gamma)
171     {
172         rgba t(0.0, 0.0, 0.0);
173 
174         if(wl >= 380.0 && wl <= 440.0)
175         {
176             t.r = -1.0 * (wl - 440.0) / (440.0 - 380.0);
177             t.b = 1.0;
178         }
179         else
180         if(wl >= 440.0 && wl <= 490.0)
181         {
182             t.g = (wl - 440.0) / (490.0 - 440.0);
183             t.b = 1.0;
184         }
185         else
186         if(wl >= 490.0 && wl <= 510.0)
187         {
188             t.g = 1.0;
189             t.b = -1.0 * (wl - 510.0) / (510.0 - 490.0);
190         }
191         else
192         if(wl >= 510.0 && wl <= 580.0)
193         {
194             t.r = (wl - 510.0) / (580.0 - 510.0);
195             t.g = 1.0;
196         }
197         else
198         if(wl >= 580.0 && wl <= 645.0)
199         {
200             t.r = 1.0;
201             t.g = -1.0 * (wl - 645.0) / (645.0 - 580.0);
202         }
203         else
204         if(wl >= 645.0 && wl <= 780.0)
205         {
206             t.r = 1.0;
207         }
208 
209         double s = 1.0;
210         if(wl > 700.0)       s = 0.3 + 0.7 * (780.0 - wl) / (780.0 - 700.0);
211         else if(wl <  420.0) s = 0.3 + 0.7 * (wl - 380.0) / (420.0 - 380.0);
212 
213         t.r = pow(t.r * s, gamma);
214         t.g = pow(t.g * s, gamma);
215         t.b = pow(t.b * s, gamma);
216         return t;
217     }
218 
219 
220 
221 
222     //===================================================================rgba8
223     struct rgba8
224     {
225         typedef int8u  value_type;
226         typedef int32u calc_type;
227         typedef int32  long_type;
228         enum base_scale_e
229         {
230             base_shift = 8,
231             base_scale = 1 << base_shift,
232             base_mask  = base_scale - 1
233         };
234         typedef rgba8 self_type;
235 
236 
237         value_type r;
238         value_type g;
239         value_type b;
240         value_type a;
241 
242         //--------------------------------------------------------------------
rgba8rgba8243         rgba8() {}
244 
245         //--------------------------------------------------------------------
246         rgba8(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) :
rrgba8247             r(value_type(r_)),
248             g(value_type(g_)),
249             b(value_type(b_)),
250             a(value_type(a_)) {}
251 
252         //--------------------------------------------------------------------
rgba8rgba8253         rgba8(const rgba& c, double a_) :
254             r((value_type)uround(c.r * double(base_mask))),
255             g((value_type)uround(c.g * double(base_mask))),
256             b((value_type)uround(c.b * double(base_mask))),
257             a((value_type)uround(a_  * double(base_mask))) {}
258 
259         //--------------------------------------------------------------------
rgba8rgba8260         rgba8(const self_type& c, unsigned a_) :
261             r(c.r), g(c.g), b(c.b), a(value_type(a_)) {}
262 
263         //--------------------------------------------------------------------
rgba8rgba8264         rgba8(const rgba& c) :
265             r((value_type)uround(c.r * double(base_mask))),
266             g((value_type)uround(c.g * double(base_mask))),
267             b((value_type)uround(c.b * double(base_mask))),
268             a((value_type)uround(c.a * double(base_mask))) {}
269 
270         //--------------------------------------------------------------------
clearrgba8271         void clear()
272         {
273             r = g = b = a = 0;
274         }
275 
276         //--------------------------------------------------------------------
transparentrgba8277         const self_type& transparent()
278         {
279             a = 0;
280             return *this;
281         }
282 
283         //--------------------------------------------------------------------
opacityrgba8284         const self_type& opacity(double a_)
285         {
286             if(a_ < 0.0) a_ = 0.0;
287             if(a_ > 1.0) a_ = 1.0;
288             a = (value_type)uround(a_ * double(base_mask));
289             return *this;
290         }
291 
292         //--------------------------------------------------------------------
opacityrgba8293         double opacity() const
294         {
295             return double(a) / double(base_mask);
296         }
297 
298         //--------------------------------------------------------------------
premultiplyrgba8299         AGG_INLINE const self_type& premultiply()
300         {
301             if(a == base_mask) return *this;
302             if(a == 0)
303             {
304                 r = g = b = 0;
305                 return *this;
306             }
307             r = value_type((calc_type(r) * a) >> base_shift);
308             g = value_type((calc_type(g) * a) >> base_shift);
309             b = value_type((calc_type(b) * a) >> base_shift);
310             return *this;
311         }
312 
313         //--------------------------------------------------------------------
premultiplyrgba8314         AGG_INLINE const self_type& premultiply(unsigned a_)
315         {
316             if(a == base_mask && a_ >= base_mask) return *this;
317             if(a == 0 || a_ == 0)
318             {
319                 r = g = b = a = 0;
320                 return *this;
321             }
322             calc_type r_ = (calc_type(r) * a_) / a;
323             calc_type g_ = (calc_type(g) * a_) / a;
324             calc_type b_ = (calc_type(b) * a_) / a;
325             r = value_type((r_ > a_) ? a_ : r_);
326             g = value_type((g_ > a_) ? a_ : g_);
327             b = value_type((b_ > a_) ? a_ : b_);
328             a = value_type(a_);
329             return *this;
330         }
331 
332         //--------------------------------------------------------------------
demultiplyrgba8333         AGG_INLINE const self_type& demultiply()
334         {
335             if(a == base_mask) return *this;
336             if(a == 0)
337             {
338                 r = g = b = 0;
339                 return *this;
340             }
341             calc_type r_ = (calc_type(r) * base_mask) / a;
342             calc_type g_ = (calc_type(g) * base_mask) / a;
343             calc_type b_ = (calc_type(b) * base_mask) / a;
344             r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_);
345             g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_);
346             b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_);
347             return *this;
348         }
349 
350         //--------------------------------------------------------------------
gradientrgba8351         AGG_INLINE self_type gradient(const self_type& c, double k) const
352         {
353             self_type ret;
354             calc_type ik = uround(k * base_scale);
355             ret.r = value_type(calc_type(r) + (((calc_type(c.r) - r) * ik) >> base_shift));
356             ret.g = value_type(calc_type(g) + (((calc_type(c.g) - g) * ik) >> base_shift));
357             ret.b = value_type(calc_type(b) + (((calc_type(c.b) - b) * ik) >> base_shift));
358             ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift));
359             return ret;
360         }
361 
362         //--------------------------------------------------------------------
addrgba8363         AGG_INLINE void add(const self_type& c, unsigned cover)
364         {
365             calc_type cr, cg, cb, ca;
366             if(cover == cover_mask)
367             {
368                 if(c.a == base_mask)
369                 {
370                     *this = c;
371                 }
372                 else
373                 {
374                     cr = r + c.r; r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr;
375                     cg = g + c.g; g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg;
376                     cb = b + c.b; b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb;
377                     ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
378                 }
379             }
380             else
381             {
382                 cr = r + ((c.r * cover + cover_mask/2) >> cover_shift);
383                 cg = g + ((c.g * cover + cover_mask/2) >> cover_shift);
384                 cb = b + ((c.b * cover + cover_mask/2) >> cover_shift);
385                 ca = a + ((c.a * cover + cover_mask/2) >> cover_shift);
386                 r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr;
387                 g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg;
388                 b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb;
389                 a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
390             }
391         }
392 
393         //--------------------------------------------------------------------
394         template<class GammaLUT>
apply_gamma_dirrgba8395         AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma)
396         {
397             r = gamma.dir(r);
398             g = gamma.dir(g);
399             b = gamma.dir(b);
400         }
401 
402         //--------------------------------------------------------------------
403         template<class GammaLUT>
apply_gamma_invrgba8404         AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma)
405         {
406             r = gamma.inv(r);
407             g = gamma.inv(g);
408             b = gamma.inv(b);
409         }
410 
411         //--------------------------------------------------------------------
no_colorrgba8412         static self_type no_color() { return self_type(0,0,0,0); }
413 
414         //--------------------------------------------------------------------
415         static self_type from_wavelength(double wl, double gamma = 1.0)
416         {
417             return self_type(rgba::from_wavelength(wl, gamma));
418         }
419     };
420 
421 
422     //-------------------------------------------------------------rgba8_pre
423     inline rgba8 rgba8_pre(unsigned r, unsigned g, unsigned b,
424                            unsigned a = rgba8::base_mask)
425     {
426         return rgba8(r,g,b,a).premultiply();
427     }
rgba8_pre(const rgba8 & c)428     inline rgba8 rgba8_pre(const rgba8& c)
429     {
430         return rgba8(c).premultiply();
431     }
rgba8_pre(const rgba8 & c,unsigned a)432     inline rgba8 rgba8_pre(const rgba8& c, unsigned a)
433     {
434         return rgba8(c,a).premultiply();
435     }
rgba8_pre(const rgba & c)436     inline rgba8 rgba8_pre(const rgba& c)
437     {
438         return rgba8(c).premultiply();
439     }
rgba8_pre(const rgba & c,double a)440     inline rgba8 rgba8_pre(const rgba& c, double a)
441     {
442         return rgba8(c,a).premultiply();
443     }
444 
445 
446     //-----------------------------------------------------------rgb8_packed
rgb8_packed(unsigned v)447     inline rgba8 rgb8_packed(unsigned v)
448     {
449         return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF);
450     }
451 
452     //-----------------------------------------------------------bgr8_packed
bgr8_packed(unsigned v)453     inline rgba8 bgr8_packed(unsigned v)
454     {
455         return rgba8(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF);
456     }
457 
458     //----------------------------------------------------------argb8_packed
argb8_packed(unsigned v)459     inline rgba8 argb8_packed(unsigned v)
460     {
461         return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF, v >> 24);
462     }
463 
464 
465 
466 
467 
468 
469 
470 
471     //=================================================================rgba16
472     struct rgba16
473     {
474         typedef int16u value_type;
475         typedef int32u calc_type;
476         typedef int64  long_type;
477         enum base_scale_e
478         {
479             base_shift = 16,
480             base_scale = 1 << base_shift,
481             base_mask  = base_scale - 1
482         };
483         typedef rgba16 self_type;
484 
485         value_type r;
486         value_type g;
487         value_type b;
488         value_type a;
489 
490         //--------------------------------------------------------------------
rgba16rgba16491         rgba16() {}
492 
493         //--------------------------------------------------------------------
494         rgba16(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) :
rrgba16495             r(value_type(r_)),
496             g(value_type(g_)),
497             b(value_type(b_)),
498             a(value_type(a_)) {}
499 
500         //--------------------------------------------------------------------
rgba16rgba16501         rgba16(const self_type& c, unsigned a_) :
502             r(c.r), g(c.g), b(c.b), a(value_type(a_)) {}
503 
504         //--------------------------------------------------------------------
rgba16rgba16505         rgba16(const rgba& c) :
506             r((value_type)uround(c.r * double(base_mask))),
507             g((value_type)uround(c.g * double(base_mask))),
508             b((value_type)uround(c.b * double(base_mask))),
509             a((value_type)uround(c.a * double(base_mask))) {}
510 
511         //--------------------------------------------------------------------
rgba16rgba16512         rgba16(const rgba& c, double a_) :
513             r((value_type)uround(c.r * double(base_mask))),
514             g((value_type)uround(c.g * double(base_mask))),
515             b((value_type)uround(c.b * double(base_mask))),
516             a((value_type)uround(a_  * double(base_mask))) {}
517 
518         //--------------------------------------------------------------------
rgba16rgba16519         rgba16(const rgba8& c) :
520             r(value_type((value_type(c.r) << 8) | c.r)),
521             g(value_type((value_type(c.g) << 8) | c.g)),
522             b(value_type((value_type(c.b) << 8) | c.b)),
523             a(value_type((value_type(c.a) << 8) | c.a)) {}
524 
525         //--------------------------------------------------------------------
rgba16rgba16526         rgba16(const rgba8& c, unsigned a_) :
527             r(value_type((value_type(c.r) << 8) | c.r)),
528             g(value_type((value_type(c.g) << 8) | c.g)),
529             b(value_type((value_type(c.b) << 8) | c.b)),
530             a(value_type((             a_ << 8) | c.a)) {}
531 
532         //--------------------------------------------------------------------
clearrgba16533         void clear()
534         {
535             r = g = b = a = 0;
536         }
537 
538         //--------------------------------------------------------------------
transparentrgba16539         const self_type& transparent()
540         {
541             a = 0;
542             return *this;
543         }
544 
545         //--------------------------------------------------------------------
opacityrgba16546         AGG_INLINE const self_type& opacity(double a_)
547         {
548             if(a_ < 0.0) a_ = 0.0;
549             if(a_ > 1.0) a_ = 1.0;
550             a = (value_type)uround(a_ * double(base_mask));
551             return *this;
552         }
553 
554         //--------------------------------------------------------------------
opacityrgba16555         double opacity() const
556         {
557             return double(a) / double(base_mask);
558         }
559 
560         //--------------------------------------------------------------------
premultiplyrgba16561         AGG_INLINE const self_type& premultiply()
562         {
563             if(a == base_mask) return *this;
564             if(a == 0)
565             {
566                 r = g = b = 0;
567                 return *this;
568             }
569             r = value_type((calc_type(r) * a) >> base_shift);
570             g = value_type((calc_type(g) * a) >> base_shift);
571             b = value_type((calc_type(b) * a) >> base_shift);
572             return *this;
573         }
574 
575         //--------------------------------------------------------------------
premultiplyrgba16576         AGG_INLINE const self_type& premultiply(unsigned a_)
577         {
578             if(a == base_mask && a_ >= base_mask) return *this;
579             if(a == 0 || a_ == 0)
580             {
581                 r = g = b = a = 0;
582                 return *this;
583             }
584             calc_type r_ = (calc_type(r) * a_) / a;
585             calc_type g_ = (calc_type(g) * a_) / a;
586             calc_type b_ = (calc_type(b) * a_) / a;
587             r = value_type((r_ > a_) ? a_ : r_);
588             g = value_type((g_ > a_) ? a_ : g_);
589             b = value_type((b_ > a_) ? a_ : b_);
590             a = value_type(a_);
591             return *this;
592         }
593 
594         //--------------------------------------------------------------------
demultiplyrgba16595         AGG_INLINE const self_type& demultiply()
596         {
597             if(a == base_mask) return *this;
598             if(a == 0)
599             {
600                 r = g = b = 0;
601                 return *this;
602             }
603             calc_type r_ = (calc_type(r) * base_mask) / a;
604             calc_type g_ = (calc_type(g) * base_mask) / a;
605             calc_type b_ = (calc_type(b) * base_mask) / a;
606             r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_);
607             g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_);
608             b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_);
609             return *this;
610         }
611 
612         //--------------------------------------------------------------------
gradientrgba16613         AGG_INLINE self_type gradient(const self_type& c, double k) const
614         {
615             self_type ret;
616             calc_type ik = uround(k * base_scale);
617             ret.r = value_type(calc_type(r) + (((calc_type(c.r) - r) * ik) >> base_shift));
618             ret.g = value_type(calc_type(g) + (((calc_type(c.g) - g) * ik) >> base_shift));
619             ret.b = value_type(calc_type(b) + (((calc_type(c.b) - b) * ik) >> base_shift));
620             ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift));
621             return ret;
622         }
623 
624         //--------------------------------------------------------------------
addrgba16625         AGG_INLINE void add(const self_type& c, unsigned cover)
626         {
627             calc_type cr, cg, cb, ca;
628             if(cover == cover_mask)
629             {
630                 if(c.a == base_mask)
631                 {
632                     *this = c;
633                 }
634                 else
635                 {
636                     cr = r + c.r; r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr;
637                     cg = g + c.g; g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg;
638                     cb = b + c.b; b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb;
639                     ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
640                 }
641             }
642             else
643             {
644                 cr = r + ((c.r * cover + cover_mask) >> cover_shift);
645                 cg = g + ((c.g * cover + cover_mask) >> cover_shift);
646                 cb = b + ((c.b * cover + cover_mask) >> cover_shift);
647                 ca = a + ((c.a * cover + cover_mask) >> cover_shift);
648                 r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr;
649                 g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg;
650                 b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb;
651                 a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
652             }
653         }
654 
655         //--------------------------------------------------------------------
656         template<class GammaLUT>
apply_gamma_dirrgba16657         AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma)
658         {
659             r = gamma.dir(r);
660             g = gamma.dir(g);
661             b = gamma.dir(b);
662         }
663 
664         //--------------------------------------------------------------------
665         template<class GammaLUT>
apply_gamma_invrgba16666         AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma)
667         {
668             r = gamma.inv(r);
669             g = gamma.inv(g);
670             b = gamma.inv(b);
671         }
672 
673         //--------------------------------------------------------------------
no_colorrgba16674         static self_type no_color() { return self_type(0,0,0,0); }
675 
676         //--------------------------------------------------------------------
677         static self_type from_wavelength(double wl, double gamma = 1.0)
678         {
679             return self_type(rgba::from_wavelength(wl, gamma));
680         }
681     };
682 
683 
684 
685     //--------------------------------------------------------------rgba16_pre
686     inline rgba16 rgba16_pre(unsigned r, unsigned g, unsigned b,
687                              unsigned a = rgba16::base_mask)
688     {
689         return rgba16(r,g,b,a).premultiply();
690     }
rgba16_pre(const rgba16 & c,unsigned a)691     inline rgba16 rgba16_pre(const rgba16& c, unsigned a)
692     {
693         return rgba16(c,a).premultiply();
694     }
rgba16_pre(const rgba & c)695     inline rgba16 rgba16_pre(const rgba& c)
696     {
697         return rgba16(c).premultiply();
698     }
rgba16_pre(const rgba & c,double a)699     inline rgba16 rgba16_pre(const rgba& c, double a)
700     {
701         return rgba16(c,a).premultiply();
702     }
rgba16_pre(const rgba8 & c)703     inline rgba16 rgba16_pre(const rgba8& c)
704     {
705         return rgba16(c).premultiply();
706     }
rgba16_pre(const rgba8 & c,unsigned a)707     inline rgba16 rgba16_pre(const rgba8& c, unsigned a)
708     {
709         return rgba16(c,a).premultiply();
710     }
711 
712 }
713 
714 
715 
716 #endif
717