8000 Add 2bit grayscale support by jedahan · Pull Request #50 · adafruit/Adafruit_CircuitPython_framebuf · GitHub
[go: up one dir, main page]

Skip to content

Add 2bit grayscale support #50

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

Merged
merged 8 commits into from
Mar 4, 2023
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
61 changes: 58 additions & 3 deletions adafruit_framebuf.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
**Hardware:**

* `Adafruit SSD1306 OLED displays <https://www.adafruit.com/?q=ssd1306>`_
* `Adafruit HT16K33 Matrix displays <https://www.adafruit.com/?q=ht16k33>`_

**Software and Dependencies:**

Expand All @@ -36,6 +37,60 @@
GS4_HMSB = 2 # Unimplemented!
MHMSB = 3 # Single bit displays like the Sharp Memory
RGB888 = 4 # Neopixels and Dotstars
GS2_HMSB = 5 # 2-bit color displays like the HT16K33 8x8 Matrix


class GS2HMSBFormat:
"""GS2HMSBFormat"""

@staticmethod
def set_pixel(framebuf, x, y, color):
"""Set a given pixel to a color."""
index = (y * framebuf.stride + x) >> 2
pixel = framebuf.buf[index]

shift = (x & 0b11) << 1
mask = 0b11 << shift
color = (color & 0b11) << shift
Comment on lines +49 to +54
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't actually understand why we right shift 2, then left shift 1 and then left shift by shift. I wonder if there is a conceptually simpler way to write this.


framebuf.buf[index] = color | (pixel & (~mask))

@staticmethod
def get_pixel(framebuf, x, y):
"""Get the color of a given pixel"""
index = (y * framebuf.stride + x) >> 2
pixel = framebuf.buf[index]

shift = (x & 0b11) << 1
return (pixel >> shift) & 0b11

@staticmethod
def fill(framebuf, color):
"""completely fill/clear the buffer with a color"""
if color:
bits = color & 0b11
fill = (bits << 6) | (bits << 4) | (bits << 2) | (bits << 0)
else:
fill = 0x00

framebuf.buf = [fill for i in range(len(framebuf.buf))]

@staticmethod
def rect(framebuf, x, y, width, height, color):
"""Draw the outline of a rectangle at the given location, size and color."""
# pylint: disable=too-many-arguments
for _x in range(x, x + width):
for _y in range(y, y + height):
if _x in [x, x + width] or _y in [y, y + height]:
GS2HMSBFormat.set_pixel(framebuf, _x, _y, color)

@staticmethod
def fill_rect(framebuf, x, y, width, height, color):
"""Draw the outline and interior of a rectangle at the given location, size and color."""
# pylint: disable=too-many-arguments
for _x in range(x, x + width):
for _y in range(y, y + height):
GS2HMSBFormat.set_pixel(framebuf, _x, _y, color)


class MHMSBFormat:
Expand Down Expand Up @@ -256,6 +311,8 @@ def __init__(self, buf, width, height, buf_format=MVLSB, stride=None):
self.format = RGB888Format()
elif buf_format == RGB565:
self.format = RGB565Format()
elif buf_format == GS2_HMSB:
self.format = GS2HMSBFormat()
else:
raise ValueError("invalid format")
self._rotation = 0
Expand Down Expand Up @@ -480,9 +537,7 @@ def image(self, img):
imwidth, imheight = img.size
if imwidth != width or imheight != height:
raise ValueError(
"Image must be same dimensions as display ({0}x{1}).".format(
width, height
)
f"Image must be same dimensions as display ({width}x{height})."
)
# Grab all the pixels from the image, faster than getpixel.
pixels = img.load()
Expand Down
0