adafruit / Adafruit_CircuitPython_Pixel_Framebuf

Neopixel and Dotstar Framebuffer Helper
MIT License
4 stars 5 forks source link

Drawing methods do not take screen rotation into account #10

Open djairjr opened 1 month ago

djairjr commented 1 month ago

From what I can understand, the drawing methods derive from the adafruit_framebuf library and do not take screen rotation into account.

I wrote a function for my games' menu system that I believe could be a way forward.

From what I can understand, the drawing methods derive from the adafruit_framebuf library and do not take screen rotation into account.

I wrote a function for my games' menu system that I believe could be a way forward. My screen is rotated 270 degrees, with this setup.

spi = board.SPI()
pixel_pin = board.D10 #board.MOSI

# Setting up the Neopixel Pannel - 16 x 16 Version
how_many = 2
panel_width = 16 # Two Pannels Wide.
panel_height = 16
num_pixels = how_many * panel_width * panel_height

pixels = neopixel.NeoPixel_SPI(
    spi,
    num_pixels, 
    brightness=0.2,
    auto_write=False,
)

# When 16x16 Using original Adafruit_Pixel_Framebuf Library
screen = PixelFramebuffer(
    pixels,
    panel_width , 
    panel_height * how_many, # What?
    rotation = 1, # Simple change rotation...
)

def display_bitmap(self,screen, tile_width, tile_height, bitmap, frame_index=0):
    '''
    Draw a bitmap or sprite_sheet taking in account the screen rotation
    '''
    self.screen = screen
    bitmap_width = bitmap.width
    bitmap_height = bitmap.height
    tiles_per_row = bitmap_width // tile_width
    tiles_per_column = bitmap_height // tile_height

    if tiles_per_row * tiles_per_column > 1:
        total_tiles = tiles_per_row * tiles_per_column
        if frame_index >= total_tiles:
            raise ValueError("Tile index out of range")
        tile_x = (frame_index % tiles_per_row) * tile_width
        tile_y = (frame_index // tiles_per_row) * tile_height
    else:
        tile_x = 0
        tile_y = 0

    for x in range(tile_width):
        for y in range(tile_height):
            pixel_color = bitmap[tile_x + x, tile_y + y]
            # Extract 16 bits RGB Components
            r = (pixel_color >> 11) & 0x1F  # RED
            g = (pixel_color >> 5) & 0x3F   # GREEN
            b = pixel_color & 0x1F          # BLUE
            # Convert  components from 16 bits to 8 bits (0-255)
            r = (r * 255) // 31
            g = (g * 255) // 63
            b = (b * 255) // 31

            # The entire magic happens here.
            # This setup will draw a pixel, with rotation corrected
            if self.screen.rotation == 0:
                self.screen.pixel(x, 31 - y, (r, g, b))
            elif self.screen.rotation == 1:
                self.screen.pixel(31 - y, 15 - x, (r, g, b))
            elif self.screen.rotation == 2:
                self.screen.pixel(15 - x, y, (r, g, b))
            elif self.screen.rotation == 3:
                self.screen.pixel(y, x, (r, g, b)) 
djairjr commented 1 month ago

Sorry I couldn't help more. If I had a little more knowledge, I would have already changed the library to include this solution. Still, I'll try to work on a fork of it and see what I can do.