1 // Aseprite
2 // Copyright (C) 2001-2018 David Capello
3 //
4 // This program is distributed under the terms of
5 // the End-User License Agreement for Aseprite.
6
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10
11 #include "app/color.h"
12
13 #include "app/color_utils.h"
14 #include "app/modules/palettes.h"
15 #include "doc/image.h"
16 #include "doc/palette.h"
17 #include "doc/primitives.h"
18 #include "gfx/hsl.h"
19 #include "gfx/hsv.h"
20 #include "gfx/rgb.h"
21
22 #include <cmath>
23 #include <cstdlib>
24 #include <iomanip>
25 #include <sstream>
26 #include <string>
27
28 namespace app {
29
30 using namespace gfx;
31
32 // static
fromMask()33 Color Color::fromMask()
34 {
35 return Color(Color::MaskType);
36 }
37
38 // static
fromRgb(int r,int g,int b,int a)39 Color Color::fromRgb(int r, int g, int b, int a)
40 {
41 Color color(Color::RgbType);
42 color.m_value.rgb.r = r;
43 color.m_value.rgb.g = g;
44 color.m_value.rgb.b = b;
45 color.m_value.rgb.a = a;
46 return color;
47 }
48
49 // static
fromHsv(double h,double s,double v,int a)50 Color Color::fromHsv(double h, double s, double v, int a)
51 {
52 Color color(Color::HsvType);
53 color.m_value.hsv.h = h;
54 color.m_value.hsv.s = s;
55 color.m_value.hsv.v = v;
56 color.m_value.hsv.a = a;
57 return color;
58 }
59
60 // static
fromHsl(double h,double s,double l,int a)61 Color Color::fromHsl(double h, double s, double l, int a)
62 {
63 Color color(Color::HslType);
64 color.m_value.hsl.h = h;
65 color.m_value.hsl.s = s;
66 color.m_value.hsl.l = l;
67 color.m_value.hsl.a = a;
68 return color;
69 }
70
71 // static
fromGray(int g,int a)72 Color Color::fromGray(int g, int a)
73 {
74 Color color(Color::GrayType);
75 color.m_value.gray.g = g;
76 color.m_value.gray.a = a;
77 return color;
78 }
79
80 // static
fromIndex(int index)81 Color Color::fromIndex(int index)
82 {
83 assert(index >= 0);
84
85 Color color(Color::IndexType);
86 color.m_value.index = index;
87 return color;
88 }
89
90 // static
fromImage(PixelFormat pixelFormat,color_t c)91 Color Color::fromImage(PixelFormat pixelFormat, color_t c)
92 {
93 Color color = app::Color::fromMask();
94
95 switch (pixelFormat) {
96
97 case IMAGE_RGB:
98 if (rgba_geta(c) > 0) {
99 color = Color::fromRgb(rgba_getr(c),
100 rgba_getg(c),
101 rgba_getb(c),
102 rgba_geta(c));
103 }
104 break;
105
106 case IMAGE_GRAYSCALE:
107 if (graya_geta(c) > 0) {
108 color = Color::fromGray(graya_getv(c),
109 graya_geta(c));
110 }
111 break;
112
113 case IMAGE_INDEXED:
114 color = Color::fromIndex(c);
115 break;
116 }
117
118 return color;
119 }
120
121 // static
fromImageGetPixel(Image * image,int x,int y)122 Color Color::fromImageGetPixel(Image *image, int x, int y)
123 {
124 if ((x >= 0) && (y >= 0) && (x < image->width()) && (y < image->height()))
125 return Color::fromImage(image->pixelFormat(), doc::get_pixel(image, x, y));
126 else
127 return Color::fromMask();
128 }
129
130 // static
fromString(const std::string & str)131 Color Color::fromString(const std::string& str)
132 {
133 Color color = app::Color::fromMask();
134
135 if (str != "mask") {
136 if (str.find("rgb{") == 0 ||
137 str.find("hsv{") == 0 ||
138 str.find("hsl{") == 0 ||
139 str.find("gray{") == 0) {
140 int c = 0;
141 double table[4] = { 0.0, 0.0, 0.0, 255.0 };
142 std::string::size_type i = str.find_first_of('{')+1, j;
143
144 while ((j = str.find_first_of(",}", i)) != std::string::npos) {
145 std::string element = str.substr(i, j - i);
146 if (c < 4)
147 table[c++] = std::strtod(element.c_str(), NULL);
148 if (c >= 4)
149 break;
150 i = j+1;
151 }
152
153 if (str[0] == 'r')
154 color = Color::fromRgb(int(table[0]), int(table[1]), int(table[2]), int(table[3]));
155 else if (str[0] == 'h' && str[1] == 's' && str[2] == 'v')
156 color = Color::fromHsv(table[0],
157 table[1] / 100.0,
158 table[2] / 100.0,
159 int(table[3]));
160 else if (str[0] == 'h' && str[1] == 's' && str[2] == 'l')
161 color = Color::fromHsl(table[0],
162 table[1] / 100.0,
163 table[2] / 100.0,
164 int(table[3]));
165 else if (str[0] == 'g')
166 color = Color::fromGray(int(table[0]), (c >= 2 ? int(table[1]): 255));
167 }
168 else if (str.find("index{") == 0) {
169 color = Color::fromIndex(std::strtol(str.c_str()+6, NULL, 10));
170 }
171 }
172
173 return color;
174 }
175
toRgb() const176 Color Color::toRgb() const
177 {
178 return Color::fromRgb(getRed(), getGreen(), getBlue(), getAlpha());
179 }
180
toString() const181 std::string Color::toString() const
182 {
183 std::stringstream result;
184
185 switch (getType()) {
186
187 case Color::MaskType:
188 result << "mask";
189 break;
190
191 case Color::RgbType:
192 result << "rgb{"
193 << m_value.rgb.r << ","
194 << m_value.rgb.g << ","
195 << m_value.rgb.b << ","
196 << m_value.rgb.a << "}";
197 break;
198
199 case Color::HsvType:
200 result << "hsv{"
201 << std::setprecision(2)
202 << std::fixed
203 << m_value.hsv.h << ","
204 << MID(0.0, m_value.hsv.s*100.0, 100.0) << ","
205 << MID(0.0, m_value.hsv.v*100.0, 100.0) << ","
206 << m_value.hsv.a << "}";
207 break;
208
209 case Color::HslType:
210 result << "hsl{"
211 << std::setprecision(2)
212 << std::fixed
213 << m_value.hsl.h << ","
214 << MID(0.0, m_value.hsl.s*100.0, 100.0) << ","
215 << MID(0.0, m_value.hsl.l*100.0, 100.0) << ","
216 << m_value.hsl.a << "}";
217 break;
218
219 case Color::GrayType:
220 result << "gray{"
221 << m_value.gray.g << ","
222 << m_value.gray.a << "}";
223 break;
224
225 case Color::IndexType:
226 result << "index{" << m_value.index << "}";
227 break;
228
229 }
230
231 return result.str();
232 }
233
toHumanReadableString(PixelFormat pixelFormat,HumanReadableString humanReadable) const234 std::string Color::toHumanReadableString(PixelFormat pixelFormat, HumanReadableString humanReadable) const
235 {
236 std::stringstream result;
237
238 if (humanReadable == LongHumanReadableString) {
239 switch (getType()) {
240
241 case Color::MaskType:
242 result << "Mask";
243 break;
244
245 case Color::RgbType:
246 if (pixelFormat == IMAGE_GRAYSCALE) {
247 result << "Gray " << getGray();
248 }
249 else {
250 result << "RGB "
251 << m_value.rgb.r << " "
252 << m_value.rgb.g << " "
253 << m_value.rgb.b;
254
255 if (pixelFormat == IMAGE_INDEXED)
256 result << " Index "
257 << color_utils::color_for_image(*this, pixelFormat);
258 }
259 break;
260
261 case Color::HsvType:
262 if (pixelFormat == IMAGE_GRAYSCALE) {
263 result << "Gray " << getGray();
264 }
265 else {
266 result << "HSV "
267 << int(m_value.hsv.h) << "\xc2\xb0 "
268 << MID(0, int(m_value.hsv.s*100.0), 100) << "% "
269 << MID(0, int(m_value.hsv.v*100.0), 100) << "%";
270
271 if (pixelFormat == IMAGE_INDEXED)
272 result << " Index " << color_utils::color_for_image(*this, pixelFormat);
273
274 result << " (RGB "
275 << getRed() << " "
276 << getGreen() << " "
277 << getBlue() << ")";
278 }
279 break;
280
281 case Color::HslType:
282 if (pixelFormat == IMAGE_GRAYSCALE) {
283 result << "Gray " << getGray();
284 }
285 else {
286 result << "HSL "
287 << int(m_value.hsl.h) << "\xc2\xb0 "
288 << MID(0, int(m_value.hsl.s*100.0), 100) << "% "
289 << MID(0, int(m_value.hsl.l*100.0), 100) << "%";
290
291 if (pixelFormat == IMAGE_INDEXED)
292 result << " Index " << color_utils::color_for_image(*this, pixelFormat);
293
294 result << " (RGB "
295 << getRed() << " "
296 << getGreen() << " "
297 << getBlue() << ")";
298 }
299 break;
300
301 case Color::GrayType:
302 result << "Gray " << m_value.gray.g;
303 break;
304
305 case Color::IndexType: {
306 int i = m_value.index;
307 if (i >= 0 && i < (int)get_current_palette()->size()) {
308 uint32_t _c = get_current_palette()->getEntry(i);
309 result << "Index " << i
310 << " (RGB "
311 << (int)rgba_getr(_c) << " "
312 << (int)rgba_getg(_c) << " "
313 << (int)rgba_getb(_c) << ")";
314 }
315 else {
316 result << "Index "
317 << i
318 << " (out of range)";
319 }
320 break;
321 }
322
323 default:
324 ASSERT(false);
325 break;
326 }
327
328 result << " #" << std::hex << std::setfill('0')
329 << std::setw(2) << getRed()
330 << std::setw(2) << getGreen()
331 << std::setw(2) << getBlue();
332 }
333 else if (humanReadable == ShortHumanReadableString) {
334 switch (getType()) {
335
336 case Color::MaskType:
337 result << "Mask";
338 break;
339
340 case Color::RgbType:
341 if (pixelFormat == IMAGE_GRAYSCALE) {
342 result << "Gry-" << getGray();
343 }
344 else {
345 result << "#" << std::hex << std::setfill('0')
346 << std::setw(2) << m_value.rgb.r
347 << std::setw(2) << m_value.rgb.g
348 << std::setw(2) << m_value.rgb.b;
349 }
350 break;
351
352 case Color::HsvType:
353 if (pixelFormat == IMAGE_GRAYSCALE) {
354 result << "Gry-" << getGray();
355 }
356 else {
357 result << int(m_value.hsv.h) << "\xc2\xb0"
358 << MID(0, int(m_value.hsv.s*100.0), 100) << ","
359 << MID(0, int(m_value.hsv.v*100.0), 100);
360 }
361 break;
362
363 case Color::HslType:
364 if (pixelFormat == IMAGE_GRAYSCALE) {
365 result << "Gry-" << getGray();
366 }
367 else {
368 result << int(m_value.hsl.h) << "\xc2\xb0"
369 << MID(0, int(m_value.hsl.s*100.0), 100) << ","
370 << MID(0, int(m_value.hsl.l*100.0), 100);
371 }
372 break;
373
374 case Color::GrayType:
375 result << "Gry-" << m_value.gray.g;
376 break;
377
378 case Color::IndexType:
379 result << "Idx-" << m_value.index;
380 break;
381
382 default:
383 ASSERT(false);
384 break;
385 }
386 }
387
388 return result.str();
389 }
390
operator ==(const Color & other) const391 bool Color::operator==(const Color& other) const
392 {
393 if (getType() != other.getType())
394 return false;
395
396 switch (getType()) {
397
398 case Color::MaskType:
399 return true;
400
401 case Color::RgbType:
402 return
403 m_value.rgb.r == other.m_value.rgb.r &&
404 m_value.rgb.g == other.m_value.rgb.g &&
405 m_value.rgb.b == other.m_value.rgb.b &&
406 m_value.rgb.a == other.m_value.rgb.a;
407
408 case Color::HsvType:
409 return
410 (std::fabs(m_value.hsv.h - other.m_value.hsv.h) < 0.001) &&
411 (std::fabs(m_value.hsv.s - other.m_value.hsv.s) < 0.00001) &&
412 (std::fabs(m_value.hsv.v - other.m_value.hsv.v) < 0.00001) &&
413 (m_value.hsv.a == other.m_value.hsv.a);
414
415 case Color::HslType:
416 return
417 (std::fabs(m_value.hsl.h - other.m_value.hsl.h) < 0.001) &&
418 (std::fabs(m_value.hsl.s - other.m_value.hsl.s) < 0.00001) &&
419 (std::fabs(m_value.hsl.l - other.m_value.hsl.l) < 0.00001) &&
420 (m_value.hsl.a == other.m_value.hsl.a);
421
422 case Color::GrayType:
423 return
424 m_value.gray.g == other.m_value.gray.g &&
425 m_value.gray.a == other.m_value.gray.a;
426
427 case Color::IndexType:
428 return m_value.index == other.m_value.index;
429
430 default:
431 ASSERT(false);
432 return false;
433 }
434 }
435
436 // Returns false only if the color is a index and it is outside the
437 // valid range (outside the maximum number of colors in the current
438 // palette)
isValid() const439 bool Color::isValid() const
440 {
441 switch (getType()) {
442
443 case Color::IndexType: {
444 int i = m_value.index;
445 return (i >= 0 && i < get_current_palette()->size());
446 }
447
448 }
449 return true;
450 }
451
getRed() const452 int Color::getRed() const
453 {
454 switch (getType()) {
455
456 case Color::MaskType:
457 return 0;
458
459 case Color::RgbType:
460 return m_value.rgb.r;
461
462 case Color::HsvType:
463 return Rgb(Hsv(m_value.hsv.h,
464 m_value.hsv.s,
465 m_value.hsv.v)).red();
466
467 case Color::HslType:
468 return Rgb(Hsl(m_value.hsl.h,
469 m_value.hsl.s,
470 m_value.hsl.l)).red();
471
472 case Color::GrayType:
473 return m_value.gray.g;
474
475 case Color::IndexType: {
476 int i = m_value.index;
477 if (i >= 0 && i < get_current_palette()->size())
478 return rgba_getr(get_current_palette()->getEntry(i));
479 else
480 return 0;
481 }
482
483 }
484
485 ASSERT(false);
486 return -1;
487 }
488
getGreen() const489 int Color::getGreen() const
490 {
491 switch (getType()) {
492
493 case Color::MaskType:
494 return 0;
495
496 case Color::RgbType:
497 return m_value.rgb.g;
498
499 case Color::HsvType:
500 return Rgb(Hsv(m_value.hsv.h,
501 m_value.hsv.s,
502 m_value.hsv.v)).green();
503
504 case Color::HslType:
505 return Rgb(Hsl(m_value.hsl.h,
506 m_value.hsl.s,
507 m_value.hsl.l)).green();
508
509 case Color::GrayType:
510 return m_value.gray.g;
511
512 case Color::IndexType: {
513 int i = m_value.index;
514 if (i >= 0 && i < get_current_palette()->size())
515 return rgba_getg(get_current_palette()->getEntry(i));
516 else
517 return 0;
518 }
519
520 }
521
522 ASSERT(false);
523 return -1;
524 }
525
getBlue() const526 int Color::getBlue() const
527 {
528 switch (getType()) {
529
530 case Color::MaskType:
531 return 0;
532
533 case Color::RgbType:
534 return m_value.rgb.b;
535
536 case Color::HsvType:
537 return Rgb(Hsv(m_value.hsv.h,
538 m_value.hsv.s,
539 m_value.hsv.v)).blue();
540
541 case Color::HslType:
542 return Rgb(Hsl(m_value.hsl.h,
543 m_value.hsl.s,
544 m_value.hsl.l)).blue();
545
546 case Color::GrayType:
547 return m_value.gray.g;
548
549 case Color::IndexType: {
550 int i = m_value.index;
551 if (i >= 0 && i < get_current_palette()->size())
552 return rgba_getb(get_current_palette()->getEntry(i));
553 else
554 return 0;
555 }
556
557 }
558
559 ASSERT(false);
560 return -1;
561 }
562
getHsvHue() const563 double Color::getHsvHue() const
564 {
565 switch (getType()) {
566
567 case Color::MaskType:
568 return 0.0;
569
570 case Color::RgbType:
571 return Hsv(Rgb(m_value.rgb.r,
572 m_value.rgb.g,
573 m_value.rgb.b)).hue();
574
575 case Color::HsvType:
576 return m_value.hsv.h;
577
578 case Color::HslType:
579 return m_value.hsl.h;
580
581 case Color::GrayType:
582 return 0.0;
583
584 case Color::IndexType: {
585 int i = m_value.index;
586 if (i >= 0 && i < get_current_palette()->size()) {
587 uint32_t c = get_current_palette()->getEntry(i);
588 return Hsv(Rgb(rgba_getr(c),
589 rgba_getg(c),
590 rgba_getb(c))).hue();
591 }
592 else
593 return 0.0;
594 }
595
596 }
597
598 ASSERT(false);
599 return -1.0;
600 }
601
getHsvSaturation() const602 double Color::getHsvSaturation() const
603 {
604 switch (getType()) {
605
606 case Color::MaskType:
607 return 0;
608
609 case Color::RgbType:
610 return Hsv(Rgb(m_value.rgb.r,
611 m_value.rgb.g,
612 m_value.rgb.b)).saturation();
613
614 case Color::HsvType:
615 return m_value.hsv.s;
616
617 case Color::HslType:
618 return Hsv(Rgb(getRed(),
619 getGreen(),
620 getBlue())).saturation();
621
622 case Color::GrayType:
623 return 0;
624
625 case Color::IndexType: {
626 int i = m_value.index;
627 if (i >= 0 && i < get_current_palette()->size()) {
628 uint32_t c = get_current_palette()->getEntry(i);
629 return Hsv(Rgb(rgba_getr(c),
630 rgba_getg(c),
631 rgba_getb(c))).saturation();
632 }
633 else
634 return 0.0;
635 }
636
637 }
638
639 ASSERT(false);
640 return -1.0;
641 }
642
getHsvValue() const643 double Color::getHsvValue() const
644 {
645 switch (getType()) {
646
647 case Color::MaskType:
648 return 0.0;
649
650 case Color::RgbType:
651 return Hsv(Rgb(m_value.rgb.r,
652 m_value.rgb.g,
653 m_value.rgb.b)).value();
654
655 case Color::HsvType:
656 return m_value.hsv.v;
657
658 case Color::HslType:
659 return Hsv(Rgb(getRed(),
660 getGreen(),
661 getBlue())).value();
662
663 case Color::GrayType:
664 return m_value.gray.g / 255.0;
665
666 case Color::IndexType: {
667 int i = m_value.index;
668 if (i >= 0 && i < get_current_palette()->size()) {
669 uint32_t c = get_current_palette()->getEntry(i);
670 return Hsv(Rgb(rgba_getr(c),
671 rgba_getg(c),
672 rgba_getb(c))).value();
673 }
674 else
675 return 0.0;
676 }
677
678 }
679
680 ASSERT(false);
681 return -1.0;
682 }
683
getHslHue() const684 double Color::getHslHue() const
685 {
686 switch (getType()) {
687
688 case Color::MaskType:
689 return 0.0;
690
691 case Color::RgbType:
692 return Hsl(Rgb(m_value.rgb.r,
693 m_value.rgb.g,
694 m_value.rgb.b)).hue();
695
696 case Color::HsvType:
697 return m_value.hsv.h;
698
699 case Color::HslType:
700 return m_value.hsl.h;
701
702 case Color::GrayType:
703 return 0.0;
704
705 case Color::IndexType: {
706 int i = m_value.index;
707 if (i >= 0 && i < get_current_palette()->size()) {
708 uint32_t c = get_current_palette()->getEntry(i);
709 return Hsl(Rgb(rgba_getr(c),
710 rgba_getg(c),
711 rgba_getb(c))).hue();
712 }
713 else
714 return 0.0;
715 }
716
717 }
718
719 ASSERT(false);
720 return -1.0;
721 }
722
getHslSaturation() const723 double Color::getHslSaturation() const
724 {
725 switch (getType()) {
726
727 case Color::MaskType:
728 return 0;
729
730 case Color::RgbType:
731 return Hsl(Rgb(m_value.rgb.r,
732 m_value.rgb.g,
733 m_value.rgb.b)).saturation();
734
735 case Color::HsvType:
736 return Hsl(Rgb(getRed(),
737 getGreen(),
738 getBlue())).saturation();
739
740 case Color::HslType:
741 return m_value.hsl.s;
742
743 case Color::GrayType:
744 return 0;
745
746 case Color::IndexType: {
747 int i = m_value.index;
748 if (i >= 0 && i < get_current_palette()->size()) {
749 uint32_t c = get_current_palette()->getEntry(i);
750 return Hsl(Rgb(rgba_getr(c),
751 rgba_getg(c),
752 rgba_getb(c))).saturation();
753 }
754 else
755 return 0.0;
756 }
757
758 }
759
760 ASSERT(false);
761 return -1.0;
762 }
763
getHslLightness() const764 double Color::getHslLightness() const
765 {
766 switch (getType()) {
767
768 case Color::MaskType:
769 return 0.0;
770
771 case Color::RgbType:
772 return Hsl(Rgb(m_value.rgb.r,
773 m_value.rgb.g,
774 m_value.rgb.b)).lightness();
775
776 case Color::HsvType:
777 return Hsl(Rgb(getRed(),
778 getGreen(),
779 getBlue())).lightness();
780
781 case Color::HslType:
782 return m_value.hsl.l;
783
784 case Color::GrayType:
785 return m_value.gray.g / 255.0;
786
787 case Color::IndexType: {
788 int i = m_value.index;
789 if (i >= 0 && i < get_current_palette()->size()) {
790 uint32_t c = get_current_palette()->getEntry(i);
791 return Hsl(Rgb(rgba_getr(c),
792 rgba_getg(c),
793 rgba_getb(c))).lightness();
794 }
795 else
796 return 0.0;
797 }
798
799 }
800
801 ASSERT(false);
802 return -1.0;
803 }
804
getGray() const805 int Color::getGray() const
806 {
807 switch (getType()) {
808
809 case Color::MaskType:
810 return 0;
811
812 case Color::RgbType:
813 return int(255.0 * Hsl(Rgb(m_value.rgb.r,
814 m_value.rgb.g,
815 m_value.rgb.b)).lightness());
816
817 case Color::HsvType:
818 return int(255.0 * Hsl(Rgb(getRed(),
819 getGreen(),
820 getBlue())).lightness());
821
822 case Color::HslType:
823 return int(255.0 * m_value.hsl.l);
824
825 case Color::GrayType:
826 return m_value.gray.g;
827
828 case Color::IndexType: {
829 int i = m_value.index;
830 if (i >= 0 && i < get_current_palette()->size()) {
831 uint32_t c = get_current_palette()->getEntry(i);
832 return int(255.0 * Hsl(Rgb(rgba_getr(c),
833 rgba_getg(c),
834 rgba_getb(c))).lightness());
835 }
836 else
837 return 0;
838 }
839
840 }
841
842 ASSERT(false);
843 return -1;
844 }
845
getIndex() const846 int Color::getIndex() const
847 {
848 switch (getType()) {
849
850 case Color::MaskType:
851 return 0;
852
853 case Color::RgbType:
854 case Color::HsvType:
855 case Color::HslType:
856 case Color::GrayType: {
857 int i = get_current_palette()->findExactMatch(getRed(), getGreen(), getBlue(), getAlpha(), -1);
858 if (i >= 0)
859 return i;
860 else
861 return get_current_palette()->findBestfit(getRed(), getGreen(), getBlue(), getAlpha(), 0);
862 }
863
864 case Color::IndexType:
865 return m_value.index;
866
867 }
868
869 ASSERT(false);
870 return -1;
871 }
872
getAlpha() const873 int Color::getAlpha() const
874 {
875 switch (getType()) {
876
877 case Color::MaskType:
878 return 0;
879
880 case Color::RgbType:
881 return m_value.rgb.a;
882
883 case Color::HsvType:
884 return m_value.hsv.a;
885
886 case Color::HslType:
887 return m_value.hsl.a;
888
889 case Color::GrayType:
890 return m_value.gray.a;
891
892 case Color::IndexType: {
893 int i = m_value.index;
894 if (i >= 0 && i < get_current_palette()->size())
895 return rgba_geta(get_current_palette()->getEntry(i));
896 else
897 return 0;
898 }
899
900 }
901
902 ASSERT(false);
903 return -1;
904 }
905
setAlpha(int alpha)906 void Color::setAlpha(int alpha)
907 {
908 alpha = MID(0, alpha, 255);
909
910 switch (getType()) {
911
912 case Color::MaskType:
913 break;
914
915 case Color::RgbType:
916 m_value.rgb.a = alpha;
917 break;
918
919 case Color::HsvType:
920 m_value.hsv.a = alpha;
921 break;
922
923 case Color::HslType:
924 m_value.hsl.a = alpha;
925 break;
926
927 case Color::GrayType:
928 m_value.gray.a = alpha;
929 break;
930
931 case Color::IndexType:
932 *this = Color::fromRgb(getRed(),
933 getGreen(),
934 getBlue(), alpha);
935 break;
936 }
937 }
938
939 } // namespace app
940