Skip to content

Commit 2c7b11b

Browse files
committed
displayio.Bitmap is now byte-aligned for depth < 8
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.
1 parent 87f7bc9 commit 2c7b11b

File tree

2 files changed

+50
-49
lines changed

2 files changed

+50
-49
lines changed

shared-module/displayio/Bitmap.c

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ void common_hal_displayio_bitmap_construct_from_buffer(displayio_bitmap_t *self,
4949
self->x_shift = 0; // Used to divide the index by the number of pixels per word. Its used in a
5050
// shift which effectively divides by 2 ** x_shift.
5151
uint32_t power_of_two = 1;
52-
while (power_of_two < ALIGN_BITS / bits_per_value) {
52+
while (power_of_two < 8 / bits_per_value) {
5353
self->x_shift++;
5454
power_of_two <<= 1;
5555
}
@@ -90,13 +90,14 @@ uint32_t common_hal_displayio_bitmap_get_pixel(displayio_bitmap_t *self, int16_t
9090
return 0;
9191
}
9292
int32_t row_start = y * self->stride;
93-
uint32_t bytes_per_value = self->bits_per_value / 8;
93+
uint32_t *row = self->data + row_start;
94+
uint8_t bytes_per_value = self->bits_per_value / 8;
95+
uint8_t values_per_byte = 8 / self->bits_per_value;
9496
if (bytes_per_value < 1) {
95-
uint32_t word = self->data[row_start + (x >> self->x_shift)];
96-
97-
return (word >> (sizeof(uint32_t) * 8 - ((x & self->x_mask) + 1) * self->bits_per_value)) & self->bitmask;
97+
uint8_t bits = ((uint8_t *)row)[x >> self->x_shift];
98+
uint8_t bit_position = (values_per_byte - (x & self->x_mask) - 1) * self->bits_per_value;
99+
return (bits >> bit_position) & self->bitmask;
98100
} else {
99-
uint32_t *row = self->data + row_start;
100101
if (bytes_per_value == 1) {
101102
return ((uint8_t *)row)[x];
102103
} else if (bytes_per_value == 2) {
@@ -134,16 +135,16 @@ void displayio_bitmap_write_pixel(displayio_bitmap_t *self, int16_t x, int16_t y
134135

135136
// Update one pixel of data
136137
int32_t row_start = y * self->stride;
137-
uint32_t bytes_per_value = self->bits_per_value / 8;
138+
uint32_t *row = self->data + row_start;
139+
uint8_t bytes_per_value = self->bits_per_value / 8;
140+
uint8_t values_per_byte = 8 / self->bits_per_value;
138141
if (bytes_per_value < 1) {
139-
uint32_t bit_position = (sizeof(uint32_t) * 8 - ((x & self->x_mask) + 1) * self->bits_per_value);
140-
uint32_t index = row_start + (x >> self->x_shift);
141-
uint32_t word = self->data[index];
142-
word &= ~(self->bitmask << bit_position);
143-
word |= (value & self->bitmask) << bit_position;
144-
self->data[index] = word;
142+
uint8_t bits = ((uint8_t *)row)[x >> self->x_shift];
143+
uint8_t bit_position = (values_per_byte - (x & self->x_mask) - 1) * self->bits_per_value;
144+
bits &= ~(self->bitmask << bit_position);
145+
bits |= (value & self->bitmask) << bit_position;
146+
((uint8_t *)row)[x >> self->x_shift] = bits;
145147
} else {
146-
uint32_t *row = self->data + row_start;
147148
if (bytes_per_value == 1) {
148149
((uint8_t *)row)[x] = value;
149150
} else if (bytes_per_value == 2) {

tools/gen_display_resources.py

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -122,22 +122,22 @@ def _load_row(self, y, row):
122122
c_file.write(
123123
"""\
124124
const uint32_t blinka_bitmap_data[32] = {
125-
0x00000011, 0x11000000,
126-
0x00000111, 0x53100000,
127-
0x00000111, 0x56110000,
128-
0x00000111, 0x11140000,
129-
0x00000111, 0x20002000,
130-
0x00000011, 0x13000000,
131-
0x00000001, 0x11200000,
132-
0x00000000, 0x11330000,
133-
0x00000000, 0x01122000,
134-
0x00001111, 0x44133000,
135-
0x00032323, 0x24112200,
136-
0x00111114, 0x44113300,
137-
0x00323232, 0x34112200,
138-
0x11111144, 0x44443300,
139-
0x11111111, 0x11144401,
140-
0x23232323, 0x21111110
125+
0x11000000, 0x00000011,
126+
0x11010000, 0x00001053,
127+
0x11010000, 0x00001156,
128+
0x11010000, 0x00001411,
129+
0x11010000, 0x00200020,
130+
0x11000000, 0x00000013,
131+
0x01000000, 0x00002011,
132+
0x00000000, 0x00003311,
133+
0x00000000, 0x00201201,
134+
0x11110000, 0x00301344,
135+
0x23230300, 0x00221124,
136+
0x14111100, 0x00331144,
137+
0x32323200, 0x00221134,
138+
0x44111111, 0x00334444,
139+
0x11111111, 0x01441411,
140+
0x23232323, 0x10111121
141141
};
142142
"""
143143
)
@@ -146,18 +146,18 @@ def _load_row(self, y, row):
146146
c_file.write(
147147
"""\
148148
const uint32_t blinka_bitmap_data[28] = {
149-
0x00000111, 0x00000000,
150-
0x00001153, 0x10000000,
151-
0x00001156, 0x11000000,
152-
0x00001111, 0x14000000,
153-
0x00000112, 0x00200000,
154-
0x00000011, 0x30000000,
155-
0x00000011, 0x20000000,
156-
0x00011144, 0x13000000,
157-
0x00232324, 0x12000000,
158-
0x01111444, 0x13000000,
159-
0x32323234, 0x12010000,
160-
0x11111144, 0x44100000
149+
0x11010000, 0x00000000,
150+
0x53110000, 0x00000010,
151+
0x56110000, 0x00000011,
152+
0x11110000, 0x00000014,
153+
0x12010000, 0x00002000,
154+
0x11000000, 0x00000030,
155+
0x11000000, 0x00000020,
156+
0x44110100, 0x00000013,
157+
0x24232300, 0x00000012,
158+
0x44141101, 0x00000013,
159+
0x34323232, 0x00000112,
160+
0x44111111, 0x00001044
161161
};
162162
"""
163163
)
@@ -171,9 +171,9 @@ def _load_row(self, y, row):
171171
.data = (uint32_t*) blinka_bitmap_data,
172172
.stride = 2,
173173
.bits_per_value = 4,
174-
.x_shift = 3,
175-
.x_mask = 0x7,
176-
.bitmask = 0xf,
174+
.x_shift = 1,
175+
.x_mask = 0x01,
176+
.bitmask = 0x0f,
177177
.read_only = true
178178
}};
179179
@@ -328,7 +328,7 @@ def _load_row(self, y, row):
328328
)
329329
)
330330

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

0 commit comments

Comments
 (0)