@@ -269,11 +269,90 @@ STATIC mp_obj_t bitmapfilter_solarize(size_t n_args, const mp_obj_t *pos_args, m
269269
270270MP_DEFINE_CONST_FUN_OBJ_KW (bitmapfilter_solarize_obj , 0 , bitmapfilter_solarize );
271271
272+
273+ //| LookupFunction = Callable[[float], float]
274+ //| ThreeLookupFunctions = Tuple[LookupFunction, LookupFunction, LookupFunction]
275+ //|
276+ //| def lookup(
277+ //| bitmap: displayio.Bitmap,
278+ //| lookup: LookupFunction | ThreeLookupFunctions,
279+ //| lookup_g: LookupFunction,
280+ //| lookup_b: LookupFunction,
281+ //| mask: displayio.Bitmap | None,
282+ //| ) -> displayio.Bitmap:
283+ //| """Modify the channels of a bitmap according to a look-up table
284+ //|
285+ //| This can be used to implement non-linear transformations of color values,
286+ //| such as gamma curves.
287+ //|
288+ //| The ``bitmap``, which must be in RGB565_SWAPPED format, is modified
289+ //| according to the values in the ``table``s.
290+ //|
291+ //| Each lookup function is called for each possible channel value from 0 to 1
292+ //| inclusive (64 times for green, 32 times for red or blue), and the return
293+ //| value (also from 0 to 1) is used whenever that color value is returned.
294+ //| """
295+ //|
296+
297+ STATIC int scaled_lut (int maxval , mp_obj_t func , int i ) {
298+ mp_obj_t obj = mp_call_function_1 (func , mp_obj_new_float (i / (mp_float_t )maxval ));
299+ mp_float_t val = mp_obj_get_float (obj );
300+ return (int )MICROPY_FLOAT_C_FUN (round )(val * maxval );
301+ }
302+
303+ STATIC mp_obj_t bitmapfilter_lookup (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
304+ enum { ARG_bitmap , ARG_lookup , ARG_mask };
305+ static const mp_arg_t allowed_args [] = {
306+ { MP_QSTR_bitmap , MP_ARG_REQUIRED | MP_ARG_OBJ , { .u_obj = MP_OBJ_NULL } },
307+ { MP_QSTR_lookup , MP_ARG_OBJ , { .u_obj = MP_OBJ_NULL } },
308+ { MP_QSTR_mask , MP_ARG_OBJ , { .u_obj = MP_ROM_NONE } },
309+ };
310+ mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
311+ mp_arg_parse_all (n_args , pos_args , kw_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
312+
313+ mp_arg_validate_type (args [ARG_bitmap ].u_obj , & displayio_bitmap_type , MP_QSTR_bitmap );
314+ displayio_bitmap_t * bitmap = MP_OBJ_TO_PTR (args [ARG_bitmap ].u_obj );
315+
316+ mp_obj_t lookup_r , lookup_g , lookup_b ;
317+
318+ if (mp_obj_is_tuple_compatible (args [ARG_lookup ].u_obj )) {
319+ mp_obj_tuple_t * lookup_tuple = MP_OBJ_TO_PTR (args [ARG_lookup ].u_obj );
320+ mp_arg_validate_length (lookup_tuple -> len , 3 , MP_QSTR_lookup );
321+ lookup_r = lookup_tuple -> items [0 ];
322+ lookup_g = lookup_tuple -> items [1 ];
323+ lookup_b = lookup_tuple -> items [2 ];
324+ } else {
325+ lookup_r = lookup_g = lookup_b = args [ARG_lookup ].u_obj ;
326+ }
327+
328+ bitmapfilter_lookup_table_t table ;
329+
330+ for (int i = 0 ; i < 32 ; i ++ ) {
331+ table .r [i ] = scaled_lut (31 , lookup_r , i );
332+ table .b [i ] = lookup_r == lookup_b ? table .r [i ] : scaled_lut (31 , lookup_b , i );
333+ }
334+ for (int i = 0 ; i < 64 ; i ++ ) {
335+ table .g [i ] = scaled_lut (63 , lookup_g , i );
336+ }
337+
338+ displayio_bitmap_t * mask = NULL ;
339+ if (args [ARG_mask ].u_obj != mp_const_none ) {
340+ mp_arg_validate_type (args [ARG_mask ].u_obj , & displayio_bitmap_type , MP_QSTR_mask );
341+ mask = MP_OBJ_TO_PTR (args [ARG_mask ].u_obj );
342+ }
343+
344+ shared_module_bitmapfilter_lookup (bitmap , mask , & table );
345+ return args [ARG_bitmap ].u_obj ;
346+ }
347+
348+ MP_DEFINE_CONST_FUN_OBJ_KW (bitmapfilter_lookup_obj , 0 , bitmapfilter_lookup );
349+
272350STATIC const mp_rom_map_elem_t bitmapfilter_module_globals_table [] = {
273351 { MP_ROM_QSTR (MP_QSTR___name__ ), MP_ROM_QSTR (MP_QSTR_bitmapfilter ) },
274352 { MP_ROM_QSTR (MP_QSTR_morph ), MP_ROM_PTR (& bitmapfilter_morph_obj ) },
275353 { MP_ROM_QSTR (MP_QSTR_mix ), MP_ROM_PTR (& bitmapfilter_mix_obj ) },
276354 { MP_ROM_QSTR (MP_QSTR_solarize ), MP_ROM_PTR (& bitmapfilter_solarize_obj ) },
355+ { MP_ROM_QSTR (MP_QSTR_lookup ), MP_ROM_PTR (& bitmapfilter_lookup_obj ) },
277356};
278357STATIC MP_DEFINE_CONST_DICT (bitmapfilter_module_globals , bitmapfilter_module_globals_table );
279358
0 commit comments