1 # SPDX-FileCopyrightText: 2020 Melissa LeBlanc-Williams for Adafruit Industries
3 # SPDX-License-Identifier: MIT
6 `displayio.colorconverter`
7 ================================================================================
11 **Software and Dependencies:**
14 https://github.com/adafruit/Adafruit_Blinka/releases
16 * Author(s): Melissa LeBlanc-Williams
20 __version__ = "0.0.0+auto.0"
21 __repo__ = "https://github.com/adafruit/Adafruit_Blinka_displayio.git"
23 from ._colorspace import Colorspace
27 """Converts one color format to another. Color converter based on original displayio
32 self, *, input_colorspace: Colorspace = Colorspace.RGB888, dither: bool = False
34 """Create a ColorConverter object to convert color formats.
35 Only supports rgb888 to RGB565 currently.
36 :param bool dither: Adds random noise to dither the output image
40 self._transparent_color = None
42 self._input_colorspace = input_colorspace
44 def _compute_rgb565(self, color: int):
46 return (color[0] & 0xF8) << 8 | (color[1] & 0xFC) << 3 | color[2] >> 3
49 def _compute_luma(color: int):
51 green = (color >> 8) & 0xFF
53 return (red * 19) / 255 + (green * 182) / 255 + (blue + 54) / 255
56 def _compute_chroma(color: int):
58 green = (color >> 8) & 0xFF
60 return max(red, green, blue) - min(red, green, blue)
62 def _compute_hue(self, color: int):
64 green = (color >> 8) & 0xFF
66 max_color = max(red, green, blue)
67 chroma = self._compute_chroma(color)
72 hue = (((green - blue) * 40) / chroma) % 240
73 elif max_color == green:
74 hue = (((blue - red) + (2 * chroma)) * 40) / chroma
75 elif max_color == blue:
76 hue = (((red - green) + (4 * chroma)) * 40) / chroma
83 def _dither_noise_1(noise):
84 noise = (noise >> 13) ^ noise
86 noise * (noise * noise * 60493 + 19990303) + 1376312589
88 return (more_noise / (1073741824.0 * 2)) * 255
90 def _dither_noise_2(self, x, y):
91 return self._dither_noise_1(x + y * 0xFFFF)
93 def _compute_tricolor(self):
96 def convert(self, color: int) -> int:
97 "Converts the given rgb888 color to RGB565"
98 if isinstance(color, int):
99 color = ((color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF, 255)
100 elif isinstance(color, tuple):
102 color = (color[0], color[1], color[2], 255)
103 elif len(color) != 4:
104 raise ValueError("Color must be a 3 or 4 value tuple")
106 raise ValueError("Color must be an integer or 3 or 4 value tuple")
109 return color # To Do: return a dithered color
112 return self._compute_rgb565(color)
114 def make_transparent(self, color: int) -> None:
115 """Set the transparent color or index for the ColorConverter. This will
116 raise an Exception if there is already a selected transparent index.
118 self._transparent_color = color
120 def make_opaque(self, color: int) -> None:
121 # pylint: disable=unused-argument
122 """Make the ColorConverter be opaque and have no transparent pixels."""
123 self._transparent_color = None
126 def dither(self) -> bool:
127 """When true the color converter dithers the output by adding
128 random noise when truncating to display bitdepth
133 def dither(self, value: bool):
134 if not isinstance(value, bool):
135 raise ValueError("Value should be boolean")