+ input_pixel = {
+ "pixel": color,
+ "x": 0,
+ "y": 0,
+ "tile": 0,
+ "tile_x": 0,
+ "tile_y": 0,
+ }
+
+ output_pixel = {"pixel": 0, "opaque": False}
+
+ if input_pixel["pixel"] == self._transparent_color:
+ return output_pixel["pixel"]
+
+ if (
+ not self._dither
+ and self._cached_colorspace == self._output_colorspace
+ and self._cached_input_pixel == input_pixel["pixel"]
+ ):
+ return self._cached_output_color
+
+ rgb888_pixel = input_pixel
+ rgb888_pixel["pixel"] = self._convert_pixel(
+ self._input_colorspace, input_pixel["pixel"]
+ )
+ self._convert_color(
+ self._output_colorspace, self._dither, rgb888_pixel, output_pixel
+ )
+
+ if not self._dither:
+ self._cached_colorspace = self._output_colorspace
+ self._cached_input_pixel = input_pixel["pixel"]
+ self._cached_output_color = output_pixel["pixel"]
+
+ return output_pixel["pixel"]
+
+ def _convert_pixel(self, colorspace: Colorspace, pixel: int) -> int:
+ pixel = self._clamp(pixel, 0, 0xFFFFFFFF)
+ if colorspace in (
+ Colorspace.RGB565_SWAPPED,
+ Colorspace.RGB555_SWAPPED,
+ Colorspace.BGR565_SWAPPED,
+ Colorspace.BGR555_SWAPPED,
+ ):
+ pixel = self._bswap16(pixel)
+ if colorspace in (Colorspace.RGB565, Colorspace.RGB565_SWAPPED):
+ red8 = (pixel >> 11) << 3
+ grn8 = ((pixel >> 5) << 2) & 0xFF
+ blu8 = (pixel << 3) & 0xFF
+ return (red8 << 16) | (grn8 << 8) | blu8
+ if colorspace in (Colorspace.RGB555, Colorspace.RGB555_SWAPPED):
+ red8 = (pixel >> 10) << 3
+ grn8 = ((pixel >> 5) << 3) & 0xFF
+ blu8 = (pixel << 3) & 0xFF
+ return (red8 << 16) | (grn8 << 8) | blu8
+ if colorspace in (Colorspace.BGR565, Colorspace.BGR565_SWAPPED):
+ blu8 = (pixel >> 11) << 3
+ grn8 = ((pixel >> 5) << 2) & 0xFF
+ red8 = (pixel << 3) & 0xFF
+ return (red8 << 16) | (grn8 << 8) | blu8
+ if colorspace in (Colorspace.BGR555, Colorspace.BGR555_SWAPPED):
+ blu8 = (pixel >> 10) << 3
+ grn8 = ((pixel >> 5) << 3) & 0xFF
+ red8 = (pixel << 3) & 0xFF
+ return (red8 << 16) | (grn8 << 8) | blu8
+ if colorspace == Colorspace.L8:
+ return (pixel & 0xFF) & 0x01010101
+ return pixel
+
+ def _convert_color(
+ self,
+ colorspace: ColorspaceStruct,
+ dither: bool,
+ input_pixel: dict,
+ output_color: dict,
+ ) -> None:
+ # pylint: disable=too-many-return-statements, too-many-branches, too-many-statements
+ pixel = input_pixel["pixel"]
+ if dither:
+ rand_red = self._dither_noise_2(input_pixel["x"], input_pixel["y"])
+ rand_grn = self._dither_noise_2(input_pixel["x"] + 33, input_pixel["y"])
+ rand_blu = self._dither_noise_2(input_pixel["x"], input_pixel["y"] + 33)
+
+ red8 = pixel >> 16
+ grn8 = (pixel >> 8) & 0xFF
+ blu8 = pixel & 0xFF
+
+ if colorspace.depth == 16:
+ blu8 = min(255, blu8 + (rand_blu & 0x07))
+ red8 = min(255, red8 + (rand_red & 0x07))
+ grn8 = min(255, grn8 + (rand_grn & 0x03))
+ else:
+ bitmask = 0xFF >> colorspace.depth
+ blu8 = min(255, blu8 + (rand_blu & bitmask))
+ red8 = min(255, red8 + (rand_red & bitmask))
+ grn8 = min(255, grn8 + (rand_grn & bitmask))
+ pixel = (red8 << 16) | (grn8 << 8) | blu8
+
+ if colorspace.depth == 16:
+ packed = self._compute_rgb565(pixel)
+ if colorspace.reverse_bytes_in_word:
+ packed = self._bswap16(packed)
+ output_color["pixel"] = packed
+ output_color["opaque"] = True
+ return
+ if colorspace.tricolor:
+ output_color["pixel"] = self._compute_luma(pixel) >> (8 - colorspace.depth)
+ if self._compute_chroma(pixel) <= 16:
+ if not colorspace.grayscale:
+ output_color["pixel"] = 0
+ output_color["opaque"] = True
+ return
+ pixel_hue = self._compute_hue(pixel)
+ output_color["pixel"] = self._compute_tricolor(
+ colorspace, pixel_hue, output_color["pixel"]
+ )
+ return
+ if colorspace.grayscale and colorspace.depth <= 8:
+ bitmask = (1 << colorspace.depth) - 1
+ output_color["pixel"] = (
+ self._compute_luma(pixel) >> colorspace.grayscale_bit
+ ) & bitmask
+ output_color["opaque"] = True
+ return
+ if colorspace.depth == 32:
+ output_color["pixel"] = pixel
+ output_color["opaque"] = True
+ return
+ if colorspace.depth == 8 and colorspace.grayscale:
+ packed = self._compute_rgb332(pixel)
+ output_color["pixel"] = packed
+ output_color["opaque"] = True
+ return
+ if colorspace.depth == 4:
+ if colorspace.sevencolor:
+ packed = self._compute_sevencolor(pixel)
+ else:
+ packed = self._compute_rgbd(pixel)
+ output_color["pixel"] = packed
+ output_color["opaque"] = True
+ return
+ output_color["opaque"] = False