8000 Merge remote-tracking branch 'origin/main' into create-sd-placeholder · rsbohn/circuitpython@62aa88f · GitHub
[go: up one dir, main page]

Skip to content

Commit 62aa88f

Browse files
committed
Merge remote-tracking branch 'origin/main' into create-sd-placeholder
2 parents 96ef9c0 + 96be941 commit 62aa88f

File tree

10 files changed

+395
-9
lines changed

10 files changed

+395
-9
lines changed

docs/shared_bindings_matrix.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@ def get_settings_from_makefile(port_dir, board_name):
173173
174174
This list must explicitly include any setting queried by tools/ci_set_matrix.py.
175175
"""
176+
if os.getenv('NO_BINDINGS_MATRIX'):
177+
return {
178+
'CIRCUITPY_BUILD_EXTENSIONS': '.bin'
179+
}
180+
176181
contents = subprocess.run(
177182
["make", "-C", port_dir, "-f", "Makefile", f"BOARD={board_name}", "print-CFLAGS", "print-CIRCUITPY_BUILD_EXTENSIONS", "print-FROZEN_MPY_DIRS", "print-SRC_PATTERNS", "print-SRC_SUPERVISOR"],
178183
encoding="utf-8",

py/circuitpy_mpconfig.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ extern void common_hal_mcu_enable_interrupts(void);
8787
#define MICROPY_TRACKED_ALLOC (CIRCUITPY_SSL_MBEDTLS)
8888
#define MICROPY_ENABLE_SOURCE_LINE (1)
8989
#define MICROPY_EPOCH_IS_1970 (1)
90-
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL)
90+
#define MICROPY_ERROR_REPORTING (CIRCUITPY_FULL_BUILD ? MICROPY_ERROR_REPORTING_NORMAL : MICROPY_ERROR_REPORTING_TERSE)
9191
#define MICROPY_FLOAT_HIGH_QUALITY_HASH (0)
9292
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
9393
#define MICROPY_GC_ALLOC_THRESHOLD (0)

py/objdict.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,7 @@ typedef struct _mp_obj_dict_view_t {
536536
STATIC mp_obj_t dict_view_it_iternext(mp_obj_t self_in) {
537537
mp_check_self(mp_obj_is_type(self_in, &mp_type_dict_view_it));
538538
mp_obj_dict_view_it_t *self = MP_OBJ_TO_PTR(self_in);
539-
mp_map_elem_t *next = dict_iter_next(MP_OBJ_TO_PTR(self->dict), &self->cur);
539+
mp_map_elem_t *next = dict_iter_next(native_dict(self->dict), &self->cur);
540540

541541
if (next == NULL) {
542542
return MP_OBJ_STOP_ITERATION;

shared-bindings/bitmapfilter/__init__.c

Lines changed: 127 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ STATIC mp_obj_t bitmapfilter_morph(size_t n_args, const mp_obj_t *pos_args, mp_m
134134
mp_obj_t weights = args[ARG_weights].u_obj;
135135
mp_obj_t obj_len = mp_obj_len(weights);
136136
if (obj_len == MP_OBJ_NULL || !mp_obj_is_small_int(obj_len)) {
137-
mp_raise_ValueError_varg(MP_ERROR_TEXT("%q must be of type %q, not %q"), MP_QSTR_weights, MP_QSTR_Sequence, mp_obj_get_type(weights)->name);
137+
mp_raise_ValueError_varg(MP_ERROR_TEXT("%q must be of type %q, not %q"), MP_QSTR_weights, MP_QSTR_Sequence, mp_obj_get_type_qstr(weights));
138138
}
139139

140140
size_t n_weights = MP_OBJ_SMALL_INT_VALUE(obj_len);
@@ -608,8 +608,131 @@ STATIC mp_obj_t bitmapfilter_false_color(size_t n_args, const mp_obj_t *pos_args
608608
shared_module_bitmapfilter_false_color(bitmap, mask, palette->colors);
609609
return args[ARG_bitmap].u_obj;
610610
}
611-
612611
MP_DEFINE_CONST_FUN_OBJ_KW(bitmapfilter_false_color_obj, 0, bitmapfilter_false_color);
612+
613+
#define BLEND_TABLE_SIZE (4096)
614+
STATIC uint8_t *get_blend_table(mp_obj_t lookup, int mode) {
615+
mp_buffer_info_t lookup_buf;
616+
if (!mp_get_buffer(lookup, &lookup_buf, mode) || lookup_buf.len != BLEND_TABLE_SIZE) {
617+
return NULL;
618+
}
619+
return lookup_buf.buf;
620+
}
621+
//|
622+
//| BlendFunction = Callable[[float, floa F438 t], float]
623+
//| """A function used to blend two images"""
624+
//|
625+
//| BlendTable = bytearray
626+
//| """A precomputed blend table
627+
//|
628+
//| There is not actually a BlendTable type. The real type is actually any
629+
//| buffer 4096 bytes in length."""
630+
//|
631+
//| def blend_precompute(lookup: BlendFunction, table: BlendTable | None = None) -> BlendTable:
632+
//| """Precompute a BlendTable from a BlendFunction
633+
//|
634+
//| If the optional ``table`` argument is provided, an existing `BlendTable` is updated
635+
//| with the new function values.
636+
//|
637+
//| The function's two arguments will range from 0 to 1. The returned value should also range from 0 to 1.
638+
//|
639+
//| A function to do a 33% blend of each source image could look like this:
640+
//|
641+
//| .. code-block:: python
642+
//|
643+
//| def blend_one_third(a, b):
644+
//| return a * .33 + b * .67
645+
//| """
646+
//|
647+
STATIC mp_obj_t blend_precompute(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
648+
enum { ARG_lookup, ARG_table };
649+
static const mp_arg_t allowed_args[] = {
650+
{ MP_QSTR_lookup, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } },
651+
{ MP_QSTR_table, MP_ARG_OBJ, { .u_obj = MP_ROM_NONE } },
652+
};
653+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
654+
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
655+
656+
mp_obj_t table = args[ARG_table].u_obj;
657+
if (table == mp_const_none) {
658+
table = mp_obj_new_bytearray_of_zeros(BLEND_TABLE_SIZE);
659+
}
660+
uint8_t *buf = get_blend_table(table, MP_BUFFER_WRITE);
661+
if (!buf) {
662+
mp_raise_TypeError_varg(MP_ERROR_TEXT("%q must be of type %q or %q, not %q"),
663+
MP_QSTR_table, MP_QSTR_NoneType, MP_QSTR_WritableBuffer,
664+
mp_obj_get_type_qs 10000 tr(table));
665+
}
666+
shared_module_bitmapfilter_blend_precompute(args[ARG_lookup].u_obj, buf);
667+
return table;
668+
}
669+
MP_DEFINE_CONST_FUN_OBJ_KW(bitmapfilter_blend_precompute_obj, 0, blend_precompute);
670+
671+
//|
672+
//| def blend(
673+
//| dest: displayio.Bitmap,
674+
//| src1: displayio.Bitmap,
675+
//| src2: displayio.Bitmap,
676+
//| lookup: BlendFunction | BlendTable,
677+
//| mask: displayio.Bitmap | None = None,
678+
//| ) -> displayio.Bitmap:
679+
//| """Blend the 'src1' and 'src2' images according to lookup function or table 'lookup'
680+
//|
681+
//| If ``lookup`` is a function, it is converted to a `BlendTable` by
682+
//| internally calling blend_precompute. If a blend function is used repeatedly
683+
//| it can be more efficient to compute it once with `blend_precompute`.
684+
//|
685+
//| If the mask is supplied, pixels from ``src1`` are taken unchanged in masked areas.
686+
//|
687+
//| The source and destination bitmaps may be the same bitmap.
688+
//|
689+
//| The destination bitmap is returned.
690+
//| """
691+
//|
692+
693+
STATIC mp_obj_t bitmapfilter_blend(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
694+
enum { ARG_dest, ARG_src1, ARG_src2, ARG_lookup, ARG_mask };
695+
static const mp_arg_t allowed_args[] = {
696+
{ MP_QSTR_dest, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } },
697+
{ MP_QSTR_src1, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } },
698+
{ MP_QSTR_src2, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } },
699+
{ MP_QSTR_lookup, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } },
700+
{ MP_QSTR_mask, MP_ARG_OBJ, { .u_obj = MP_ROM_NONE } },
701+
};
702+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
703+
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
704+
705+
mp_arg_validate_type(args[ARG_dest].u_obj, &displayio_bitmap_type, MP_QSTR_dest);
706+
displayio_bitmap_t *dest = MP_OBJ_TO_PTR(args[ARG_dest].u_obj);
707+
708+
mp_arg_validate_type(args[ARG_src1].u_obj, &displayio_bitmap_type, MP_QSTR_src1);
709+
displayio_bitmap_t *src1 = MP_OBJ_TO_PTR(args[ARG_src1].u_obj);
710+
711+
mp_arg_validate_type(args[ARG_src2].u_obj, &displayio_bitmap_type, MP_QSTR_src2);
712+
displayio_bitmap_t *src2 = MP_OBJ_TO_PTR(args[ARG_src2].u_obj);
713+
714+
mp_obj_t lookup = args[ARG_lookup].u_obj;
715+
if (mp_obj_is_callable(lookup)) {
716+
lookup = mp_call_function_1(MP_OBJ_FROM_PTR(&bitmapfilter_blend_precompute_obj), lookup);
717+
}
718+
uint8_t *lookup_buf = get_blend_table(lookup, MP_BUFFER_READ);
719+
if (!lookup_buf) {
720+
mp_raise_TypeError_varg(MP_ERROR_TEXT("%q must be of type %q or %q, not %q"),
721+
MP_QSTR_lookup, MP_QSTR_callable, MP_QSTR_ReadableBuffer,
722+
mp_obj_get_type_qstr(lookup));
723+
}
724+
725+
displayio_bitmap_t *mask = NULL;
726+
if (args[ARG_mask].u_obj != mp_const_none) {
727+
mp_arg_validate_type(args[ARG_mask].u_obj, &displayio_bitmap_type, MP_QSTR_mask);
728+
mask = MP_OBJ_TO_PTR(args[ARG_mask].u_obj);
729+
}
730+
731+
shared_module_bitmapfilter_blend(dest, src1, src2, mask, lookup_buf);
732+
return args[ARG_dest].u_obj;
733+
}
734+
MP_DEFINE_CONST_FUN_OBJ_KW(bitmapfilter_blend_obj, 0, bitmapfilter_blend);
735+
613736
STATIC const mp_rom_map_elem_t bitmapfilter_module_globals_table[] = {
614737
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bitmapfilter) },
615738
{ MP_ROM_QSTR(MP_QSTR_morph), MP_ROM_PTR(&bitmapfilter_morph_obj) },
@@ -621,6 +744,8 @@ STATIC const mp_rom_map_elem_t bitmapfilter_module_globals_table[] = {
621744
{ MP_ROM_QSTR(MP_QSTR_ChannelScaleOffset), MP_ROM_PTR(&bitmapfilter_channel_scale_offset_type) },
622745
{ MP_ROM_QSTR(MP_QSTR_ChannelMixer), MP_ROM_PTR(&bitmapfilter_channel_mixer_type) },
623746
{ MP_ROM_QSTR(MP_QSTR_ChannelMixerOffset), MP_ROM_PTR(&bitmapfilter_channel_mixer_offset_type) },
747+
{ MP_ROM_QSTR(MP_QSTR_blend), MP_ROM_PTR(&bitmapfilter_blend_obj) },
748+
{ MP_ROM_QSTR(MP_QSTR_blend_precompute), MP_ROM_PTR(&bitmapfilter_blend_precompute_obj) },
624749
};
625750
STATIC MP_DEFINE_CONST_DICT(bitmapfilter_module_globals, bitmapfilter_module_globals_table);
626751

shared-bindings/bitmapfilter/__init__.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,12 @@ void shared_module_bitmapfilter_false_color(
7373
displayio_bitmap_t *bitmap,
7474
displayio_bitmap_t *mask,
7575
_displayio_color_t palette[256]);
76+
77+
void shared_module_bitmapfilter_blend_precompute(mp_obj_t fun, uint8_t lookup[4096]);
78+
79+
void shared_module_bitmapfilter_blend(
80+
displayio_bitmap_t *dest,
81+
displayio_bitmap_t *src1,
82+
displayio_bitmap_t *src2,
83+
displayio_bitmap_t *mask,
84+
const uint8_t lookup[4096]);

shared-module/bitmapfilter/__init__.c

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
#pragma GCC diagnostic ignored "-Wshadow"
3131

3232
static void check_matching_details(displayio_bitmap_t *b1, displayio_bitmap_t *b2) {
33-
if (b1->width != b2->width || b1->height != b2->height) {
33+
if (b1->width != b2->width || b1->height != b2->height || b1->bits_per_value != b2->bits_per_value) {
3434
mp_raise_ValueError(MP_ERROR_TEXT("bitmap size and depth must match"));
3535
}
3636
}
@@ -193,8 +193,6 @@ void shared_module_bitmapfilter_morph(
193193
const int32_t m_int = (int32_t)MICROPY_FLOAT_C_FUN(round)(65536 * m);
194194
const int32_t b_int = (int32_t)MICROPY_FLOAT_C_FUN(round)(65536 * COLOR_G6_MAX * b);
195195

196-
check_matching_details(bitmap, bitmap);
197-
198196
switch (bitmap->bits_per_value) {
199197
default:
200198
mp_raise_ValueError(MP_ERROR_TEXT("unsupported bitmap depth"));
@@ -308,8 +306,6 @@ void shared_module_bitmapfilter_mix(
308306
wt[i] = (int32_t)MICROPY_FLOAT_C_FUN(round)(scale * weights[i]);
309307
}
310308

311-
check_matching_details(bitmap, bitmap);
312-
313309
switch (bitmap->bits_per_value) {
314310
default:
315311
mp_raise_ValueError(MP_ERROR_TEXT("unsupported bitmap depth"));
@@ -456,3 +452,64 @@ void shared_module_bitmapfilter_false_color(
456452
}
457453
}
458454
}
455+
456+
void shared_module_bitmapfilter_blend_precompute(mp_obj_t fun, uint8_t lookup[4096]) {
457+
uint8_t *ptr = lookup;
458+
for (int i = 0; i < 64; i++) {
459+
mp_obj_t fi = mp_obj_new_float(i * (1 / MICROPY_FLOAT_CONST(63.)));
460+
for (int j = 0; j < 64; j++) {
461+
mp_obj_t fj = mp_obj_new_float(j * (1 / MICROPY_FLOAT_CONST(63.)));
462+
mp_float_t res = mp_obj_get_float(mp_call_function_2(fun, fi, fj));
463+
*ptr++ = res < 0 ? 0 : res > 1 ? 1 : (uint8_t)MICROPY_FLOAT_C_FUN(round)(63 * res);
464+
}
465+
}
466+
}
467+
468+
#define FIVE_TO_SIX(x) ({ int tmp = (x); (tmp << 1) | (tmp & 1); })
469+
#define SIX_TO_FIVE(x) ((x) >> 1)
470+
471+
void shared_module_bitmapfilter_blend(
472+
displayio_bitmap_t *bitmap,
473+
displayio_bitmap_t *src1,
474+
displayio_bitmap_t *src2,
475+
displayio_bitmap_t *mask,
476+
const uint8_t lookup[4096]) {
477+
478+
check_matching_details(bitmap, src1);
479+
check_matching_details(bitmap, src2);
480+
481+
switch (bitmap->bits_per_value) {
482+
default:
483+
mp_raise_ValueError(MP_ERROR_TEXT("unsupported bitmap depth"));
484+
case 16: {
485+
for (int y = 0, yy = bitmap->height; y < yy; y++) {
486+
uint16_t *dest_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(bitmap, y);
487+
uint16_t *src1_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(src1, y);
488+
uint16_t *src2_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(src2, y);
489+
for (int x = 0, xx = bitmap->width; x < xx; x++) {
490+
int pixel1 = IMAGE_GET_RGB565_PIXEL_FAST(src1_ptr, x);
491+
if (mask && common_hal_displayio_bitmap_get_pixel(mask, x, y)) {
492+
IMAGE_PUT_RGB565_PIXEL_FAST(dest_ptr, x, pixel1);
493+
continue; // Short circuit.
494+
}
495+
int pixel2 = IMAGE_GET_RGB565_PIXEL_FAST(src2_ptr, x);
496+
497+
int r1 = FIVE_TO_SIX(COLOR_RGB565_TO_R5(pixel1));
498+
int r2 = FIVE_TO_SIX(COLOR_RGB565_TO_R5(pixel2));
499+
int r = SIX_TO_FIVE(lookup[r1 * 64 + r2]);
500+
501+
int g1 = COLOR_RGB565_TO_G6(pixel1);
502+
int g2 = COLOR_RGB565_TO_G6(pixel2);
503+
int g = lookup[g1 * 64 + g2];
504+
505+
int b1 = FIVE_TO_SIX(COLOR_RGB565_TO_B5(pixel1));
506+
int b2 = FIVE_TO_SIX(COLOR_RGB565_TO_B5(pixel2));
507+
int b = SIX_TO_FIVE(lookup[b1 * 64 + b2]);
508+
509+
int pixel = COLOR_R5_G6_B5_TO_RGB565(r, g, b);
510+
IMAGE_PUT_RGB565_PIXEL_FAST(dest_ptr, x, pixel);
511+
}
512+
}
513+
}
514+
}
515+
}

tests/basics/subclass_native_dict.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ def __setitem__(self, k, v):
2626
d = mydict()
2727
d[3] = 4
2828
print(d[3])
29+
print(d.keys())
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
from displayio import Bitmap
2+
import bitmapfilter
3+
from dump_bitmap import dump_bitmap_rgb_swapped
4+
from blinka_image import decode_resource
5+
6+
7+
def test_pattern():
8+
return decode_resource("testpattern", 2)
9+
10+
11+
def blinka():
12+
return decode_resource("blinka_32x32", 0)
13+
14+
15+
def blendfunc(frac):
16+
nfrac = 1 - frac
17+
18+
def inner(x, y):
19+
return x * frac + y * nfrac
20+
21+
return inner
22+
23+
24+
def make_quadrant_bitmap():
25+
b = Bitmap(17, 17, 1)
26+
for i in range(b.height):
27+
for j in range(b.width):
28+
b[i, j] = (i < 8) ^ (j < 8)
29+
return b
30+
31+
32+
b = Bitmap(32, 32, 65535)
33+
print(test_pattern().width)
34+
print(blinka().width)
35+
print(b.width)
36+
print(test_pattern().height)
37+
print(blinka().height)
38+
print(b.height)
39+
40+
mask = make_quadrant_bitmap()
41+
blend_table = bitmapfilter.blend_precompute(blendfunc(0.1))
42+
bitmapfilter.blend(b, test_pattern(), blinka(), blend_table, mask)
43+
dump_bitmap_rgb_swapped(b)
44+
45+
bitmapfilter.blend(b, test_pattern(), blinka(), blendfunc(0.5), mask)
46+
dump_bitmap_rgb_swapped(b)
47+
48+
bitmapfilter.blend(b, test_pattern(), blinka(), max, mask)
49+
dump_bitmap_rgb_swapped(b)
50+
bitmapfilter.blend(b, test_pattern(), blinka(), min)
51+
dump_bitmap_rgb_swapped(b)

0 commit comments

Comments
 (0)
0