1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.3
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
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.
10 //----------------------------------------------------------------------------
12 // Adaptation for high precision colors has been sponsored by
13 // Liberty Technology Systems, Inc., visit http://lib-sys.com
15 // Liberty Technology Systems, Inc. is the provider of
16 // PostScript and PDF technology for software developers.
18 //----------------------------------------------------------------------------
19 // Contact: mcseem@antigrain.com
20 // mcseemagg@yahoo.com
21 // http://www.antigrain.com
22 //----------------------------------------------------------------------------
24 #ifndef AGG_COLOR_RGBA_INCLUDED
25 #define AGG_COLOR_RGBA_INCLUDED
28 #include "agg_basics.h"
32 // Supported byte orders for RGB and RGBA pixel formats
33 //=======================================================================
34 struct order_rgb
{ enum { R
=0, G
=1, B
=2, rgb_tag
}; }; //----order_rgb
35 struct order_bgr
{ enum { B
=0, G
=1, R
=2, rgb_tag
}; }; //----order_bgr
36 struct order_rgba
{ enum { R
=0, G
=1, B
=2, A
=3, rgba_tag
}; }; //----order_rgba
37 struct order_argb
{ enum { A
=0, R
=1, G
=2, B
=3, rgba_tag
}; }; //----order_argb
38 struct order_abgr
{ enum { A
=0, B
=1, G
=2, R
=3, rgba_tag
}; }; //----order_abgr
39 struct order_bgra
{ enum { B
=0, G
=1, R
=2, A
=3, rgba_tag
}; }; //----order_bgra
41 //====================================================================rgba
44 typedef double value_type
;
51 //--------------------------------------------------------------------
54 //--------------------------------------------------------------------
55 rgba(double r_
, double g_
, double b_
, double a_
=1.0) :
56 r(r_
), g(g_
), b(b_
), a(a_
) {}
58 //--------------------------------------------------------------------
59 rgba(const rgba
& c
, double a_
) : r(c
.r
), g(c
.g
), b(c
.b
), a(a_
) {}
61 //--------------------------------------------------------------------
67 //--------------------------------------------------------------------
68 const rgba
& transparent()
74 //--------------------------------------------------------------------
75 const rgba
& opacity(double a_
)
77 if(a_
< 0.0) a_
= 0.0;
78 if(a_
> 1.0) a_
= 1.0;
83 //--------------------------------------------------------------------
84 double opacity() const
89 //--------------------------------------------------------------------
90 const rgba
& premultiply()
98 //--------------------------------------------------------------------
99 const rgba
& premultiply(double a_
)
101 if(a
<= 0.0 || a_
<= 0.0)
114 //--------------------------------------------------------------------
115 const rgba
& demultiply()
130 //--------------------------------------------------------------------
131 rgba
gradient(rgba c
, double k
) const
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
;
141 //--------------------------------------------------------------------
142 static rgba
no_color() { return rgba(0,0,0,0); }
144 //--------------------------------------------------------------------
145 static rgba
from_wavelength(double wl
, double gamma
= 1.0);
147 //--------------------------------------------------------------------
148 rgba(double wavelen
, double gamma
=1.0)
150 *this = from_wavelength(wavelen
, gamma
);
155 //----------------------------------------------------------------rgba_pre
156 inline rgba
rgba_pre(double r
, double g
, double b
, double a
=1.0)
158 return rgba(r
, g
, b
, a
).premultiply();
160 inline rgba
rgba_pre(const rgba
& c
)
162 return rgba(c
).premultiply();
164 inline rgba
rgba_pre(const rgba
& c
, double a
)
166 return rgba(c
, a
).premultiply();
169 //------------------------------------------------------------------------
170 inline rgba
rgba::from_wavelength(double wl
, double gamma
)
172 rgba
t(0.0, 0.0, 0.0);
174 if(wl
>= 380.0 && wl
<= 440.0)
176 t
.r
= -1.0 * (wl
- 440.0) / (440.0 - 380.0);
180 if(wl
>= 440.0 && wl
<= 490.0)
182 t
.g
= (wl
- 440.0) / (490.0 - 440.0);
186 if(wl
>= 490.0 && wl
<= 510.0)
189 t
.b
= -1.0 * (wl
- 510.0) / (510.0 - 490.0);
192 if(wl
>= 510.0 && wl
<= 580.0)
194 t
.r
= (wl
- 510.0) / (580.0 - 510.0);
198 if(wl
>= 580.0 && wl
<= 645.0)
201 t
.g
= -1.0 * (wl
- 645.0) / (645.0 - 580.0);
204 if(wl
>= 645.0 && wl
<= 780.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);
213 t
.r
= pow(t
.r
* s
, gamma
);
214 t
.g
= pow(t
.g
* s
, gamma
);
215 t
.b
= pow(t
.b
* s
, gamma
);
222 //===================================================================rgba8
225 typedef int8u value_type
;
226 typedef int32u calc_type
;
227 typedef int32 long_type
;
231 base_size
= 1 << base_shift
,
232 base_mask
= base_size
- 1
234 typedef rgba8 self_type
;
242 //--------------------------------------------------------------------
245 //--------------------------------------------------------------------
246 rgba8(unsigned r_
, unsigned g_
, unsigned b_
, unsigned a_
=base_mask
) :
252 //--------------------------------------------------------------------
253 rgba8(const rgba
& c
, double a_
) :
254 r(value_type(c
.r
* double(base_mask
) + 0.5)),
255 g(value_type(c
.g
* double(base_mask
) + 0.5)),
256 b(value_type(c
.b
* double(base_mask
) + 0.5)),
257 a(value_type(a_
* double(base_mask
) + 0.5)) {}
259 //--------------------------------------------------------------------
260 rgba8(const self_type
& c
, unsigned a_
) :
261 r(c
.r
), g(c
.g
), b(c
.b
), a(value_type(a_
)) {}
263 //--------------------------------------------------------------------
264 rgba8(const rgba
& c
) :
265 r(value_type(c
.r
* double(base_mask
) + 0.5)),
266 g(value_type(c
.g
* double(base_mask
) + 0.5)),
267 b(value_type(c
.b
* double(base_mask
) + 0.5)),
268 a(value_type(c
.a
* double(base_mask
) + 0.5)) {}
270 //--------------------------------------------------------------------
276 //--------------------------------------------------------------------
277 const self_type
& transparent()
283 //--------------------------------------------------------------------
284 const self_type
& opacity(double a_
)
286 if(a_
< 0.0) a_
= 0.0;
287 if(a_
> 1.0) a_
= 1.0;
288 a
= value_type(a_
* double(base_mask
) + 0.5);
292 //--------------------------------------------------------------------
293 double opacity() const
295 return double(a
) / double(base_mask
);
298 //--------------------------------------------------------------------
299 const self_type
& premultiply()
301 if(a
== base_mask
) return *this;
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
);
313 //--------------------------------------------------------------------
314 const self_type
& premultiply(unsigned a_
)
316 if(a
== base_mask
&& a_
>= base_mask
) return *this;
317 if(a
== 0 || a_
== 0)
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_
);
332 //--------------------------------------------------------------------
333 const self_type
& demultiply()
335 if(a
== base_mask
) return *this;
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_
> base_mask
) ? base_mask
: r_
);
345 g
= value_type((g_
> base_mask
) ? base_mask
: g_
);
346 b
= value_type((b_
> base_mask
) ? base_mask
: b_
);
350 //--------------------------------------------------------------------
351 self_type
gradient(const self_type
& c
, double k
) const
354 calc_type ik
= calc_type(k
* base_size
);
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
));
362 //--------------------------------------------------------------------
363 static self_type
no_color() { return self_type(0,0,0,0); }
365 //--------------------------------------------------------------------
366 static self_type
from_wavelength(double wl
, double gamma
= 1.0)
368 return self_type(rgba::from_wavelength(wl
, gamma
));
373 //-------------------------------------------------------------rgba8_pre
374 inline rgba8
rgba8_pre(unsigned r
, unsigned g
, unsigned b
,
375 unsigned a
= rgba8::base_mask
)
377 return rgba8(r
,g
,b
,a
).premultiply();
379 inline rgba8
rgba8_pre(const rgba8
& c
)
381 return rgba8(c
).premultiply();
383 inline rgba8
rgba8_pre(const rgba8
& c
, unsigned a
)
385 return rgba8(c
,a
).premultiply();
387 inline rgba8
rgba8_pre(const rgba
& c
)
389 return rgba8(c
).premultiply();
391 inline rgba8
rgba8_pre(const rgba
& c
, double a
)
393 return rgba8(c
,a
).premultiply();
397 //-----------------------------------------------------------rgb8_packed
398 inline rgba8
rgb8_packed(unsigned v
)
400 return rgba8((v
>> 16) & 0xFF, (v
>> 8) & 0xFF, v
& 0xFF);
403 //-----------------------------------------------------------bgr8_packed
404 inline rgba8
bgr8_packed(unsigned v
)
406 return rgba8(v
& 0xFF, (v
>> 8) & 0xFF, (v
>> 16) & 0xFF);
409 //----------------------------------------------------------argb8_packed
410 inline rgba8
argb8_packed(unsigned v
)
412 return rgba8((v
>> 16) & 0xFF, (v
>> 8) & 0xFF, v
& 0xFF, v
>> 24);
422 //=================================================================rgba16
425 typedef int16u value_type
;
426 typedef int32u calc_type
;
427 typedef int64 long_type
;
431 base_size
= 1 << base_shift
,
432 base_mask
= base_size
- 1
434 typedef rgba16 self_type
;
441 //--------------------------------------------------------------------
444 //--------------------------------------------------------------------
445 rgba16(unsigned r_
, unsigned g_
, unsigned b_
, unsigned a_
=base_mask
) :
451 //--------------------------------------------------------------------
452 rgba16(const self_type
& c
, unsigned a_
) :
453 r(c
.r
), g(c
.g
), b(c
.b
), a(value_type(a_
)) {}
455 //--------------------------------------------------------------------
456 rgba16(const rgba
& c
) :
457 r(value_type(c
.r
* double(base_mask
) + 0.5)),
458 g(value_type(c
.g
* double(base_mask
) + 0.5)),
459 b(value_type(c
.b
* double(base_mask
) + 0.5)),
460 a(value_type(c
.a
* double(base_mask
) + 0.5)) {}
462 //--------------------------------------------------------------------
463 rgba16(const rgba
& c
, double a_
) :
464 r(value_type(c
.r
* double(base_mask
) + 0.5)),
465 g(value_type(c
.g
* double(base_mask
) + 0.5)),
466 b(value_type(c
.b
* double(base_mask
) + 0.5)),
467 a(value_type(a_
* double(base_mask
) + 0.5)) {}
469 //--------------------------------------------------------------------
470 rgba16(const rgba8
& c
) :
471 r(value_type((value_type(c
.r
) << 8) | c
.r
)),
472 g(value_type((value_type(c
.g
) << 8) | c
.g
)),
473 b(value_type((value_type(c
.b
) << 8) | c
.b
)),
474 a(value_type((value_type(c
.a
) << 8) | c
.a
)) {}
476 //--------------------------------------------------------------------
477 rgba16(const rgba8
& c
, unsigned a_
) :
478 r(value_type((value_type(c
.r
) << 8) | c
.r
)),
479 g(value_type((value_type(c
.g
) << 8) | c
.g
)),
480 b(value_type((value_type(c
.b
) << 8) | c
.b
)),
481 a(value_type(( a_
<< 8) | c
.a
)) {}
483 //--------------------------------------------------------------------
489 //--------------------------------------------------------------------
490 const self_type
& transparent()
496 //--------------------------------------------------------------------
497 const self_type
& opacity(double a_
)
499 if(a_
< 0.0) a_
= 0.0;
500 if(a_
> 1.0) a_
= 1.0;
501 a
= value_type(a_
* double(base_mask
) + 0.5);
505 //--------------------------------------------------------------------
506 double opacity() const
508 return double(a
) / double(base_mask
);
511 //--------------------------------------------------------------------
512 const self_type
& premultiply()
514 if(a
== base_mask
) return *this;
520 r
= value_type((calc_type(r
) * a
) >> base_shift
);
521 g
= value_type((calc_type(g
) * a
) >> base_shift
);
522 b
= value_type((calc_type(b
) * a
) >> base_shift
);
526 //--------------------------------------------------------------------
527 const self_type
& premultiply(unsigned a_
)
529 if(a
== base_mask
&& a_
>= base_mask
) return *this;
530 if(a
== 0 || a_
== 0)
535 calc_type r_
= (calc_type(r
) * a_
) / a
;
536 calc_type g_
= (calc_type(g
) * a_
) / a
;
537 calc_type b_
= (calc_type(b
) * a_
) / a
;
538 r
= value_type((r_
> a_
) ? a_
: r_
);
539 g
= value_type((g_
> a_
) ? a_
: g_
);
540 b
= value_type((b_
> a_
) ? a_
: b_
);
545 //--------------------------------------------------------------------
546 const self_type
& demultiply()
548 if(a
== base_mask
) return *this;
554 calc_type r_
= (calc_type(r
) * base_mask
) / a
;
555 calc_type g_
= (calc_type(g
) * base_mask
) / a
;
556 calc_type b_
= (calc_type(b
) * base_mask
) / a
;
557 r
= value_type((r_
> base_mask
) ? base_mask
: r_
);
558 g
= value_type((g_
> base_mask
) ? base_mask
: g_
);
559 b
= value_type((b_
> base_mask
) ? base_mask
: b_
);
563 //--------------------------------------------------------------------
564 self_type
gradient(const self_type
& c
, double k
) const
567 calc_type ik
= calc_type(k
* base_size
);
568 ret
.r
= value_type(calc_type(r
) + (((calc_type(c
.r
) - r
) * ik
) >> base_shift
));
569 ret
.g
= value_type(calc_type(g
) + (((calc_type(c
.g
) - g
) * ik
) >> base_shift
));
570 ret
.b
= value_type(calc_type(b
) + (((calc_type(c
.b
) - b
) * ik
) >> base_shift
));
571 ret
.a
= value_type(calc_type(a
) + (((calc_type(c
.a
) - a
) * ik
) >> base_shift
));
575 //--------------------------------------------------------------------
576 static self_type
no_color() { return self_type(0,0,0,0); }
578 //--------------------------------------------------------------------
579 static self_type
from_wavelength(double wl
, double gamma
= 1.0)
581 return self_type(rgba::from_wavelength(wl
, gamma
));
587 //--------------------------------------------------------------rgba16_pre
588 inline rgba16
rgba16_pre(unsigned r
, unsigned g
, unsigned b
,
589 unsigned a
= rgba16::base_mask
)
591 return rgba16(r
,g
,b
,a
).premultiply();
593 inline rgba16
rgba16_pre(const rgba16
& c
, unsigned a
)
595 return rgba16(c
,a
).premultiply();
597 inline rgba16
rgba16_pre(const rgba
& c
)
599 return rgba16(c
).premultiply();
601 inline rgba16
rgba16_pre(const rgba
& c
, double a
)
603 return rgba16(c
,a
).premultiply();
605 inline rgba16
rgba16_pre(const rgba8
& c
)
607 return rgba16(c
).premultiply();
609 inline rgba16
rgba16_pre(const rgba8
& c
, unsigned a
)
611 return rgba16(c
,a
).premultiply();