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

Broken Badger2040.image() method #41

Open
niutech opened this issue Aug 7, 2023 · 4 comments
Open

Broken Badger2040.image() method #41

niutech opened this issue Aug 7, 2023 · 4 comments
Labels
bug Something isn't working

Comments

@niutech
Copy link

niutech commented Aug 7, 2023

In version 0.0.2, the Badger2040.image() method looked like this:

for(auto y = 0; y < dh; y++) {
  for(auto x = 0; x < dw; x++) {
    // work out byte offset in source data
    uint32_t o = ((y + sy) * (stride >> 3)) + ((x + sx) >> 3);
    // extract bitmask for this pixel
    uint32_t bm = 0b10000000 >> ((x + sx) & 0b111);
    // draw the pixel
    uc8151_legacy.pixel(dx + x, dy + y, data[o] & bm);
  }
}

However, in version 0.0.3 it looks like this:

for oy in range(h):
    row = data[oy]
    for ox in range(w):
        if row & 0b1 == 0:
            self.display.pixel(x + ox, y + oy)
        row >>= 1

So putting the same image data results in garbled pixels after upgrade to 0.0.3. Please make it compatible, like this:

for oy in range(h):
    for ox in range(w):
        o = oy * (w >> 3) + (ox >> 3)
        bm = 0b10000000 >> (ox & 0b111)
        if data[o] & bm:
            self.display.pixel(x + ox, y + oy)
@Gadgetoid
Copy link
Member

I'm not sure what happened here, but this is a slow and awful kludge that's likely to be completely deprecated in favour of PNG support in the next release.

@niutech
Copy link
Author

niutech commented Aug 8, 2023 via email

@Gadgetoid Gadgetoid added the bug Something isn't working label Aug 8, 2023
@Gadgetoid
Copy link
Member

Faster, maybe, but accessible to the vast majority of users, not especially.

The implementation currently in Badger 2040 is probably slower than PNG, it's really about the worst way to do it.

There might be a case to be made for supporting this in PicoGraphics, but there's no guarantee the bytes in the drawing surface will be in any particular order, endianess, type or size.

Anyway the best way to do this in the interim is to implement the function in your own code, and use memoryview(display.display) to access the raw buffer as quickly as possible, eg:

import io
from badger2040 import Badger2040

display = Badger2040()

display.set_pen(15)
display.clear()


def display_bitmap(o_x, o_y, width, height, data):
    WIDTH, HEIGHT = display.display.get_bounds()

    y_bytes = int(height // 8)

    if len(data) < width * height / 8:
        raise ValueError("Data undersized")

    for x in range(width):
        src = x * y_bytes
        dst = (x + o_x) * int(HEIGHT // 8) + int(o_y // 8)
        b = bytes(data[src:src + y_bytes])
        memoryview(display.display)[dst:dst + y_bytes] = b


display_bitmap(10, 10, 8, 16, [
    0b01111000, 0b11111110,
    0b10111110, 0b11111110,
    0b11011110, 0b11111110,
    0b11101111, 0b11111110,
    0b11110111, 0b11111110,
    0b11111011, 0b11111110,
    0b00111101, 0b11111110,
    0b00111110, 0b11111110,
])

display.update()

Noting that this limits you to heights and Y positions in multiples of 8 pixels, since that's how the internal data is packed, but if you want fast that's about as fast as you can get without dropping into C.

@niutech
Copy link
Author

niutech commented Aug 11, 2023

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants