Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow usage of ColorConverter with Bitmap saving #34

Merged
merged 2 commits into from
Feb 20, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 41 additions & 6 deletions adafruit_bitmapsaver.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
import gc
import struct
import board
from displayio import Bitmap, Palette, Display
from displayio import Bitmap, Palette, Display, ColorConverter

try:
from typing import Tuple, Optional, Union
Expand Down Expand Up @@ -81,11 +81,38 @@ def _rgb565_to_bgr_tuple(color: int) -> Tuple[int, int, int]:
return blue, green, red


def rgb565_to_rgb888(rgb565):
"""
Convert from an integer representing rgb565 color into an integer
representing rgb888 color.
:param rgb565: Color to convert
:return int: rgb888 color value
"""
# Shift the red value to the right by 11 bits.
red5 = rgb565 >> 11
# Shift the green value to the right by 5 bits and extract the lower 6 bits.
green6 = (rgb565 >> 5) & 0b111111
# Extract the lower 5 bits for blue.
blue5 = rgb565 & 0b11111

# Convert 5-bit red to 8-bit red.
red8 = round(red5 / 31 * 255)
# Convert 6-bit green to 8-bit green.
green8 = round(green6 / 63 * 255)
# Convert 5-bit blue to 8-bit blue.
blue8 = round(blue5 / 31 * 255)

# Combine the RGB888 values into a single integer
rgb888_value = (red8 << 16) | (green8 << 8) | blue8

return rgb888_value


# pylint:disable=too-many-locals
def _write_pixels(
output_file: BufferedWriter,
pixel_source: Union[Bitmap, Display],
palette: Optional[Palette],
palette: Optional[Union[Palette, ColorConverter]],
) -> None:
saving_bitmap = isinstance(pixel_source, Bitmap)
width, height = _rotated_height_and_width(pixel_source)
Expand All @@ -97,7 +124,13 @@ def _write_pixels(
# pixel_source: Bitmap
for x in range(width):
pixel = pixel_source[x, y - 1]
color = palette[pixel] # handled by save_pixel's guardians
if isinstance(palette, Palette):
color = palette[pixel] # handled by save_pixel's guardians
elif isinstance(palette, ColorConverter):
converted = palette.convert(pixel)
converted_888 = rgb565_to_rgb888(converted)
color = converted_888

for _ in range(3):
row_buffer[buffer_index] = color & 0xFF
color >>= 8
Expand All @@ -124,7 +157,7 @@ def _write_pixels(
def save_pixels(
file_or_filename: Union[str, BufferedWriter],
pixel_source: Union[Display, Bitmap] = None,
palette: Optional[Palette] = None,
palette: Optional[Union[Palette, ColorConverter]] = None,
) -> None:
"""Save pixels to a 24 bit per pixel BMP file.
If pixel_source if a displayio.Bitmap, save it's pixels through palette.
Expand All @@ -140,8 +173,10 @@ def save_pixels(
pixel_source = board.DISPLAY

if isinstance(pixel_source, Bitmap):
if not isinstance(palette, Palette):
raise ValueError("Third argument must be a Palette for a Bitmap save")
if not isinstance(palette, Palette) and not isinstance(palette, ColorConverter):
raise ValueError(
"Third argument must be a Palette or ColorConverter for a Bitmap save"
)
elif not isinstance(pixel_source, Display):
raise ValueError("Second argument must be a Bitmap or Display")
try:
Expand Down
Loading