@@ -141,12 +141,101 @@ STATIC mp_obj_t bitmapfilter_morph(size_t n_args, const mp_obj_t *pos_args, mp_m
141141 args [ARG_threshold ].u_bool , args [ARG_offset ].u_bool , args [ARG_invert ].u_bool );
142142 return mp_const_none ;
143143}
144-
145144MP_DEFINE_CONST_FUN_OBJ_KW (bitmapfilter_morph_obj , 0 , bitmapfilter_morph );
146145
146+ static mp_float_t float_subscr (mp_obj_t o , int i ) {
147+ return mp_obj_get_float (mp_obj_subscr (o , MP_OBJ_NEW_SMALL_INT (i ), MP_OBJ_SENTINEL ));
148+
149+ }
150+ //| def mix(
151+ //| bitmap: displayio.Bitmap, weights: Sequence[int], mask: displayio.Bitmap | None = None
152+ //| ):
153+ //| """Perform a channel mixing operation on the bitmap
154+ //|
155+ //| The ``bitmap``, which must be in RGB565_SWAPPED format, is modified
156+ //| according to the ``weights``.
157+ //|
158+ //| If ``weights`` is a list of length 3, then each channel is scaled independently:
159+ //| The numbers are the red, green, and blue channel scales.
160+ //|
161+ //| If ``weights`` is a list of length 9, then channels are mixed. The first three
162+ //| numbers are the fraction of red, green and blue input channels mixed into the
163+ //| red output channel. The next 3 numbers are for green, and the final 3 are for blue.
164+ //|
165+ //| If ``weights`` is a list of length 12, then channels are mixed with an offset.
166+ //| Every fourth value is the offset value.
167+ //|
168+ //| For example, to perform a sepia conversion on an input image,
169+ //|
170+ //| .. code-block:: python
171+ //|
172+ //| sepia_weights = [
173+ //| .393, .769, .189,
174+ //| .349, .686, .168,
175+ //| .272, .534, .131]
176+ //|
177+ //| def sepia(bitmap):
178+ //| \"""Convert the bitmap to sepia\"""
179+ //| bitmapfilter.mix(bitmap, sepia_weights)
180+ //| """
181+ //|
182+ STATIC mp_obj_t bitmapfilter_mix (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
183+ enum { ARG_bitmap , ARG_weights , ARG_mask };
184+ static const mp_arg_t allowed_args [] = {
185+ { MP_QSTR_bitmap , MP_ARG_REQUIRED | MP_ARG_OBJ , { .u_obj = MP_OBJ_NULL } },
186+ { MP_QSTR_weights , MP_ARG_REQUIRED | MP_ARG_OBJ , { .u_obj = MP_OBJ_NULL } },
187+ { MP_QSTR_mask , MP_ARG_OBJ , { .u_obj = MP_ROM_NONE } },
188+ };
189+ mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
190+ mp_arg_parse_all (n_args , pos_args , kw_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
191+
192+ mp_arg_validate_type (args [ARG_bitmap ].u_obj , & displayio_bitmap_type , MP_QSTR_bitmap );
193+ displayio_bitmap_t * bitmap = MP_OBJ_TO_PTR (args [ARG_bitmap ].u_obj );
194+
195+ mp_float_t weights [12 ];
196+ memset (weights , 0 , sizeof (weights ));
197+
198+ mp_obj_t weights_obj = args [ARG_weights ].u_obj ;
199+ mp_int_t len = mp_obj_get_int (mp_obj_len (weights_obj ));
200+
201+ switch (len ) {
202+ case 3 :
203+ for (int i = 0 ; i < 3 ; i ++ ) {
204+ weights [5 * i ] = float_subscr (weights_obj , i );
205+ }
206+ break ;
207+ case 9 :
208+ for (int i = 0 ; i < 9 ; i ++ ) {
209+ weights [i + i / 3 ] = float_subscr (weights_obj , i );
210+ }
211+ break ;
212+ case 12 :
213+ for (int i = 0 ; i < 12 ; i ++ ) {
214+ weights [i ] = float_subscr (weights_obj , i );
215+ }
216+ break ;
217+ default :
218+ mp_raise_ValueError (
219+ MP_ERROR_TEXT ("weights must be a sequence of length 3, 9, or 12" ));
220+ }
221+
222+
223+ displayio_bitmap_t * mask = NULL ;
224+ if (args [ARG_mask ].u_obj != mp_const_none ) {
225+ mp_arg_validate_type (args [ARG_mask ].u_obj , & displayio_bitmap_type , MP_QSTR_mask );
226+ mask = MP_OBJ_TO_PTR (args [ARG_mask ].u_obj );
227+ }
228+
229+ shared_module_bitmapfilter_mix (bitmap , mask , weights );
230+ return mp_const_none ;
231+ }
232+
233+ MP_DEFINE_CONST_FUN_OBJ_KW (bitmapfilter_mix_obj , 0 , bitmapfilter_mix );
234+
147235STATIC const mp_rom_map_elem_t bitmapfilter_module_globals_table [] = {
148236 { MP_ROM_QSTR (MP_QSTR___name__ ), MP_ROM_QSTR (MP_QSTR_bitmapfilter ) },
149237 { MP_ROM_QSTR (MP_QSTR_morph ), MP_ROM_PTR (& bitmapfilter_morph_obj ) },
238+ { MP_ROM_QSTR (MP_QSTR_mix ), MP_ROM_PTR (& bitmapfilter_mix_obj ) },
150239};
151240STATIC MP_DEFINE_CONST_DICT (bitmapfilter_module_globals , bitmapfilter_module_globals_table );
152241
0 commit comments