Skip to content

Commit

Permalink
displayio.Bitmap is now byte-aligned for depth < 8
Browse files Browse the repository at this point in the history
The traditional layout of pixels in bitmaps of depth less than eight
is with the order of values in a byte reversed, but with bytes in
the same order as the pixels on the line.

Before now, displayio.Bitmap did reverse the values, but did it on a
word (four bytes) basis, not byte, which resulted in groups of four
bytes being in the order opposite to the screen order.

This patch fixes this, by making processing of pixels in bitmaps of
depth less than 8 bits based on bytes, not words. Since the internal
details are changing, any code that accessed bitmaps through the
memoryview buffer, or that created bitmaps directly from raw data,
and that used depth of less than 8 bits will be affected.

Therefore, the gen_display_resources.py script also had to be modified
to account for the changes.
  • Loading branch information
deshipu committed Aug 5, 2024
1 parent 87f7bc9 commit 2c7b11b
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 49 deletions.
29 changes: 15 additions & 14 deletions shared-module/displayio/Bitmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ void common_hal_displayio_bitmap_construct_from_buffer(displayio_bitmap_t *self,
self->x_shift = 0; // Used to divide the index by the number of pixels per word. Its used in a
// shift which effectively divides by 2 ** x_shift.
uint32_t power_of_two = 1;
while (power_of_two < ALIGN_BITS / bits_per_value) {
while (power_of_two < 8 / bits_per_value) {
self->x_shift++;
power_of_two <<= 1;
}
Expand Down Expand Up @@ -90,13 +90,14 @@ uint32_t common_hal_displayio_bitmap_get_pixel(displayio_bitmap_t *self, int16_t
return 0;
}
int32_t row_start = y * self->stride;
uint32_t bytes_per_value = self->bits_per_value / 8;
uint32_t *row = self->data + row_start;
uint8_t bytes_per_value = self->bits_per_value / 8;
uint8_t values_per_byte = 8 / self->bits_per_value;
if (bytes_per_value < 1) {
uint32_t word = self->data[row_start + (x >> self->x_shift)];

return (word >> (sizeof(uint32_t) * 8 - ((x & self->x_mask) + 1) * self->bits_per_value)) & self->bitmask;
uint8_t bits = ((uint8_t *)row)[x >> self->x_shift];
uint8_t bit_position = (values_per_byte - (x & self->x_mask) - 1) * self->bits_per_value;
return (bits >> bit_position) & self->bitmask;
} else {
uint32_t *row = self->data + row_start;
if (bytes_per_value == 1) {
return ((uint8_t *)row)[x];
} else if (bytes_per_value == 2) {
Expand Down Expand Up @@ -134,16 +135,16 @@ void displayio_bitmap_write_pixel(displayio_bitmap_t *self, int16_t x, int16_t y

// Update one pixel of data
int32_t row_start = y * self->stride;
uint32_t bytes_per_value = self->bits_per_value / 8;
uint32_t *row = self->data + row_start;
uint8_t bytes_per_value = self->bits_per_value / 8;
uint8_t values_per_byte = 8 / self->bits_per_value;
if (bytes_per_value < 1) {
uint32_t bit_position = (sizeof(uint32_t) * 8 - ((x & self->x_mask) + 1) * self->bits_per_value);
uint32_t index = row_start + (x >> self->x_shift);
uint32_t word = self->data[index];
word &= ~(self->bitmask << bit_position);
word |= (value & self->bitmask) << bit_position;
self->data[index] = word;
uint8_t bits = ((uint8_t *)row)[x >> self->x_shift];
uint8_t bit_position = (values_per_byte - (x & self->x_mask) - 1) * self->bits_per_value;
bits &= ~(self->bitmask << bit_position);
bits |= (value & self->bitmask) << bit_position;
((uint8_t *)row)[x >> self->x_shift] = bits;
} else {
uint32_t *row = self->data + row_start;
if (bytes_per_value == 1) {
((uint8_t *)row)[x] = value;
} else if (bytes_per_value == 2) {
Expand Down
70 changes: 35 additions & 35 deletions tools/gen_display_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,22 +122,22 @@ def _load_row(self, y, row):
c_file.write(
"""\
const uint32_t blinka_bitmap_data[32] = {
0x00000011, 0x11000000,
0x00000111, 0x53100000,
0x00000111, 0x56110000,
0x00000111, 0x11140000,
0x00000111, 0x20002000,
0x00000011, 0x13000000,
0x00000001, 0x11200000,
0x00000000, 0x11330000,
0x00000000, 0x01122000,
0x00001111, 0x44133000,
0x00032323, 0x24112200,
0x00111114, 0x44113300,
0x00323232, 0x34112200,
0x11111144, 0x44443300,
0x11111111, 0x11144401,
0x23232323, 0x21111110
0x11000000, 0x00000011,
0x11010000, 0x00001053,
0x11010000, 0x00001156,
0x11010000, 0x00001411,
0x11010000, 0x00200020,
0x11000000, 0x00000013,
0x01000000, 0x00002011,
0x00000000, 0x00003311,
0x00000000, 0x00201201,
0x11110000, 0x00301344,
0x23230300, 0x00221124,
0x14111100, 0x00331144,
0x32323200, 0x00221134,
0x44111111, 0x00334444,
0x11111111, 0x01441411,
0x23232323, 0x10111121
};
"""
)
Expand All @@ -146,18 +146,18 @@ def _load_row(self, y, row):
c_file.write(
"""\
const uint32_t blinka_bitmap_data[28] = {
0x00000111, 0x00000000,
0x00001153, 0x10000000,
0x00001156, 0x11000000,
0x00001111, 0x14000000,
0x00000112, 0x00200000,
0x00000011, 0x30000000,
0x00000011, 0x20000000,
0x00011144, 0x13000000,
0x00232324, 0x12000000,
0x01111444, 0x13000000,
0x32323234, 0x12010000,
0x11111144, 0x44100000
0x11010000, 0x00000000,
0x53110000, 0x00000010,
0x56110000, 0x00000011,
0x11110000, 0x00000014,
0x12010000, 0x00002000,
0x11000000, 0x00000030,
0x11000000, 0x00000020,
0x44110100, 0x00000013,
0x24232300, 0x00000012,
0x44141101, 0x00000013,
0x34323232, 0x00000112,
0x44111111, 0x00001044
};
"""
)
Expand All @@ -171,9 +171,9 @@ def _load_row(self, y, row):
.data = (uint32_t*) blinka_bitmap_data,
.stride = 2,
.bits_per_value = 4,
.x_shift = 3,
.x_mask = 0x7,
.bitmask = 0xf,
.x_shift = 1,
.x_mask = 0x01,
.bitmask = 0x0f,
.read_only = true
}};
Expand Down Expand Up @@ -328,7 +328,7 @@ def _load_row(self, y, row):
)
)

for i, word in enumerate(struct.iter_unpack(">I", b)):
for i, word in enumerate(struct.iter_unpack("<I", b)):
c_file.write("0x{:08x}, ".format(word[0]))
if (i + 1) % (bytes_per_row // 4) == 0:
c_file.write("\n")
Expand All @@ -348,9 +348,9 @@ def _load_row(self, y, row):
.data = (uint32_t*) font_bitmap_data,
.stride = {},
.bits_per_value = 1,
.x_shift = 5,
.x_mask = 0x1f,
.bitmask = 0x1,
.x_shift = 3,
.x_mask = 0x07,
.bitmask = 0x01,
.read_only = true
}};
""".format(
Expand Down

0 comments on commit 2c7b11b

Please sign in to comment.