|
31 | 31 | #include "py/runtime.h"
|
32 | 32 | #include "shared-bindings/_pixelbuf/PixelBuf.h"
|
33 | 33 | #include <string.h>
|
| 34 | +#include <math.h> |
34 | 35 |
|
35 | 36 | // Helper to ensure we have the native super class instead of a subclass.
|
36 | 37 | static pixelbuf_pixelbuf_obj_t* native_pixelbuf(mp_obj_t pixelbuf_obj) {
|
@@ -69,6 +70,7 @@ void common_hal__pixelbuf_pixelbuf_construct(pixelbuf_pixelbuf_obj_t *self, size
|
69 | 70 | }
|
70 | 71 | // Call set_brightness so that it can allocate a second buffer if needed.
|
71 | 72 | self->brightness = 1.0;
|
| 73 | + self->scaled_brightness = 0x100; |
72 | 74 | common_hal__pixelbuf_pixelbuf_set_brightness(MP_OBJ_FROM_PTR(self), brightness);
|
73 | 75 |
|
74 | 76 | // Turn on auto_write. We don't want to do it with the above brightness call.
|
@@ -109,26 +111,31 @@ void common_hal__pixelbuf_pixelbuf_set_brightness(mp_obj_t self_in, mp_float_t b
|
109 | 111 | pixelbuf_pixelbuf_obj_t* self = native_pixelbuf(self_in);
|
110 | 112 | // Skip out if the brightness is already set. The default of self->brightness is 1.0. So, this
|
111 | 113 | // also prevents the pre_brightness_buffer allocation when brightness is set to 1.0 again.
|
112 |
| - mp_float_t change = brightness - self->brightness; |
113 |
| - if (-0.001 < change && change < 0.001) { |
| 114 | + self->brightness = brightness; |
| 115 | + uint16_t new_scaled_brightness = (int)roundf(brightness * 256); |
| 116 | + if (new_scaled_brightness == self->scaled_brightness) { |
114 | 117 | return;
|
115 | 118 | }
|
116 |
| - self->brightness = brightness; |
| 119 | + self->scaled_brightness = new_scaled_brightness; |
117 | 120 | size_t pixel_len = self->pixel_count * self->bytes_per_pixel;
|
118 |
| - if (self->pre_brightness_buffer == NULL) { |
119 |
| - self->pre_brightness_buffer = m_malloc(pixel_len, false); |
120 |
| - memcpy(self->pre_brightness_buffer, self->post_brightness_buffer, pixel_len); |
121 |
| - } |
122 |
| - for (size_t i = 0; i < pixel_len; i++) { |
123 |
| - // Don't adjust per-pixel luminance bytes in dotstar mode |
124 |
| - if (self->byteorder.is_dotstar && i % 4 == 0) { |
125 |
| - continue; |
| 121 | + if (self->scaled_brightness == 0x100 && !self->pre_brightness_buffer) { |
| 122 | + return; |
| 123 | + } else { |
| 124 | + if (self->pre_brightness_buffer == NULL) { |
| 125 | + self->pre_brightness_buffer = m_malloc(pixel_len, false); |
| 126 | + memcpy(self->pre_brightness_buffer, self->post_brightness_buffer, pixel_len); |
| 127 | + } |
| 128 | + for (size_t i = 0; i < pixel_len; i++) { |
| 129 | + // Don't adjust per-pixel luminance bytes in dotstar mode |
| 130 | + if (self->byteorder.is_dotstar && i % 4 == 0) { |
| 131 | + continue; |
| 132 | + } |
| 133 | + self->post_brightness_buffer[i] = (self->pre_brightness_buffer[i] * self->scaled_brightness) >> 8; |
126 | 134 | }
|
127 |
| - self->post_brightness_buffer[i] = self->pre_brightness_buffer[i] * self->brightness; |
128 |
| - } |
129 | 135 |
|
130 |
| - if (self->auto_write) { |
131 |
| - common_hal__pixelbuf_pixelbuf_show(self_in); |
| 136 | + if (self->auto_write) { |
| 137 | + common_hal__pixelbuf_pixelbuf_show(self_in); |
| 138 | + } |
132 | 139 | }
|
133 | 140 | }
|
134 | 141 |
|
@@ -197,28 +204,34 @@ void _pixelbuf_set_pixel_color(pixelbuf_pixelbuf_obj_t* self, size_t index, uint
|
197 | 204 | }
|
198 | 205 | pixelbuf_rgbw_t *rgbw_order = &self->byteorder.byteorder;
|
199 | 206 | size_t offset = index * self->bytes_per_pixel;
|
200 |
| - if (self->pre_brightness_buffer != NULL) { |
201 |
| - uint8_t* pre_brightness_buffer = self->pre_brightness_buffer + offset; |
202 |
| - if (self->bytes_per_pixel == 4) { |
203 |
| - pre_brightness_buffer[rgbw_order->w] = w; |
204 |
| - } |
205 |
| - |
206 |
| - pre_brightness_buffer[rgbw_order->r] = r; |
207 |
| - pre_brightness_buffer[rgbw_order->g] = g; |
208 |
| - pre_brightness_buffer[rgbw_order->b] = b; |
| 207 | + uint8_t *scaled_buffer, *unscaled_buffer; |
| 208 | + if (self->pre_brightness_buffer) { |
| 209 | + scaled_buffer = self->post_brightness_buffer + offset; |
| 210 | + unscaled_buffer = self->pre_brightness_buffer + offset; |
| 211 | + } else { |
| 212 | + scaled_buffer = NULL; |
| 213 | + unscaled_buffer = self->post_brightness_buffer + offset; |
209 | 214 | }
|
210 | 215 |
|
211 |
| - uint8_t* post_brightness_buffer = self->post_brightness_buffer + offset; |
212 | 216 | if (self->bytes_per_pixel == 4) {
|
213 |
| - // Only apply brightness if w is actually white (aka not DotStar.) |
214 |
| - if (!self->byteorder.is_dotstar) { |
215 |
| - w *= self->brightness; |
| 217 | + unscaled_buffer[rgbw_order->w] = w; |
| 218 | + } |
| 219 | + |
| 220 | + unscaled_buffer[rgbw_order->r] = r; |
| 221 | + unscaled_buffer[rgbw_order->g] = g; |
| 222 | + unscaled_buffer[rgbw_order->b] = b; |
| 223 | + |
| 224 | + if (scaled_buffer) { |
| 225 | + if (self->bytes_per_pixel == 4) { |
| 226 | + if (!self->byteorder.is_dotstar) { |
| 227 | + w = (w * self->scaled_brightness) >> 8; |
| 228 | + } |
| 229 | + scaled_buffer[rgbw_order->w] = w; |
216 | 230 | }
|
217 |
| - post_brightness_buffer[rgbw_order->w] = w; |
| 231 | + scaled_buffer[rgbw_order->r] = (r * self->scaled_brightness) >> 8; |
| 232 | + scaled_buffer[rgbw_order->g] = (g * self->scaled_brightness) >> 8; |
| 233 | + scaled_buffer[rgbw_order->b] = (b * self->scaled_brightness) >> 8; |
218 | 234 | }
|
219 |
| - post_brightness_buffer[rgbw_order->r] = r * self->brightness; |
220 |
| - post_brightness_buffer[rgbw_order->g] = g * self->brightness; |
221 |
| - post_brightness_buffer[rgbw_order->b] = b * self->brightness; |
222 | 235 | }
|
223 | 236 |
|
224 | 237 | void _pixelbuf_set_pixel(pixelbuf_pixelbuf_obj_t* self, size_t index, mp_obj_t value) {
|
@@ -318,3 +331,23 @@ void common_hal__pixelbuf_pixelbuf_fill(mp_obj_t self_in, mp_obj_t fill_color) {
|
318 | 331 | common_hal__pixelbuf_pixelbuf_show(self_in);
|
319 | 332 | }
|
320 | 333 | }
|
| 334 | + |
| 335 | +mp_int_t common_hal__pixelbuf_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { |
| 336 | + pixelbuf_pixelbuf_obj_t *self = native_pixelbuf(self_in); |
| 337 | + bufinfo->buf = self->pre_brightness_buffer; |
| 338 | + if (self->pre_brightness_buffer) { |
| 339 | + // If we have a brightness setting, we must treat the buffer as |
| 340 | + // read-only (because we have no way to "fire" the |
| 341 | + // brightness-converting code as a side effect of mutation via the |
| 342 | + // buffer) |
| 343 | + if ((flags & MP_BUFFER_WRITE)) { |
| 344 | + return 1; |
| 345 | + } |
| 346 | + bufinfo->buf = self->pre_brightness_buffer; |
| 347 | + } else { |
| 348 | + bufinfo->buf = self->post_brightness_buffer; |
| 349 | + } |
| 350 | + bufinfo->typecode = 'B'; |
| 351 | + bufinfo->len = self->bytes_per_pixel * common_hal__pixelbuf_pixelbuf_get_len(self_in); |
| 352 | + return 0; |
| 353 | +} |
0 commit comments