2828#include "py/builtin.h"
2929#include "py/runtime.h"
3030
31+ #include "shared-bindings/bitmaptools/__init__.h"
3132#include "shared-bindings/displayio/Bitmap.h"
3233#include "shared-bindings/jpegio/JpegDecoder.h"
3334#include "shared-module/jpegio/JpegDecoder.h"
@@ -106,6 +107,15 @@ MP_DEFINE_CONST_FUN_OBJ_2(jpegio_jpegdecoder_open_obj, jpegio_jpegdecoder_open);
106107//| self,
107108//| bitmap: displayio.Bitmap,
108109//| scale: int = 0,
110+ //| x: int = 0,
111+ //| y: int = 0,
112+ //| *,
113+ //| x1: int,
114+ //| y1: int,
115+ //| x2: int,
116+ //| y2: int,
117+ //| skip_source_index: int,
118+ //| skip_dest_index: int,
109119//| ) -> None:
110120//| """Decode JPEG data
111121//|
@@ -115,21 +125,45 @@ MP_DEFINE_CONST_FUN_OBJ_2(jpegio_jpegdecoder_open_obj, jpegio_jpegdecoder_open);
115125//| The image is optionally downscaled by a factor of ``2**scale``.
116126//| Scaling by a factor of 8 (scale=3) is particularly efficient in terms of decoding time.
117127//|
128+ //| The remaining parameters are as for `bitmaptools.blit`.
129+ //| Because JPEG is a lossy data format, chroma keying based on the "source
130+ //| index" is not reliable, because the same original RGB value might end
131+ //| up being decompressed as a similar but not equal color value. Using a
132+ //| higher JPEG encoding quality can help, but ultimately it will not be
133+ //| perfect.
134+ //|
118135//| After a call to ``decode``, you must ``open`` a new JPEG. It is not
119136//| possible to repeatedly ``decode`` the same jpeg data, even if it is to
120137//| select different scales or crop regions from it.
121138//|
122139//| :param Bitmap bitmap: Optional output buffer
123140//| :param int scale: Scale factor from 0 to 3, inclusive.
141+ //| :param int x: Horizontal pixel location in bitmap where source_bitmap upper-left
142+ //| corner will be placed
143+ //| :param int y: Vertical pixel location in bitmap where source_bitmap upper-left
144+ //| corner will be placed
145+ //| :param int x1: Minimum x-value for rectangular bounding box to be copied from the source bitmap
146+ //| :param int y1: Minimum y-value for rectangular bounding box to be copied from the source bitmap
147+ //| :param int x2: Maximum x-value (exclusive) for rectangular bounding box to be copied from the source bitmap
148+ //| :param int y2: Maximum y-value (exclusive) for rectangular bounding box to be copied from the source bitmap
149+ //| :param int skip_source_index: bitmap palette index in the source that will not be copied,
150+ //| set to None to copy all pixels
151+ //| :param int skip_dest_index: bitmap palette index in the destination bitmap that will not get overwritten
152+ //| by the pixels from the source
124153//| """
125154//|
126155STATIC mp_obj_t jpegio_jpegdecoder_decode (mp_uint_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
127156 jpegio_jpegdecoder_obj_t * self = MP_OBJ_TO_PTR (pos_args [0 ]);
128157
129- enum { ARG_bitmap , ARG_scale };
158+ enum { ARG_bitmap , ARG_scale , ARG_x , ARG_y , ARGS_X1_Y1_X2_Y2 , ARG_skip_source_index , ARG_skip_dest_index };
130159 static const mp_arg_t allowed_args [] = {
131160 { MP_QSTR_bitmap , MP_ARG_OBJ | MP_ARG_REQUIRED , {.u_obj = mp_const_none } },
132161 { MP_QSTR_scale , MP_ARG_INT , {.u_int = 0 } },
162+ { MP_QSTR_x , MP_ARG_INT , {.u_int = 0 } },
163+ { MP_QSTR_y , MP_ARG_INT , {.u_int = 0 } },
164+ ALLOWED_ARGS_X1_Y1_X2_Y2 (0 , 0 ),
165+ {MP_QSTR_skip_source_index , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = mp_const_none } },
166+ {MP_QSTR_skip_dest_index , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = mp_const_none } },
133167 };
134168 mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
135169 mp_arg_parse_all (n_args - 1 , pos_args + 1 , kw_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
@@ -141,7 +175,33 @@ STATIC mp_obj_t jpegio_jpegdecoder_decode(mp_uint_t n_args, const mp_obj_t *pos_
141175 int scale = args [ARG_scale ].u_int ;
142176 mp_arg_validate_int_range (scale , 0 , 3 , MP_QSTR_scale );
143177
144- common_hal_jpegio_jpegdecoder_decode_into (self , bitmap , scale );
178+ int x = mp_arg_validate_int_range (args [ARG_x ].u_int , 0 , bitmap -> width , MP_QSTR_x );
179+ int y = mp_arg_validate_int_range (args [ARG_x ].u_int , 0 , bitmap -> height , MP_QSTR_y );
180+ bitmaptools_rect_t lim = bitmaptools_validate_coord_range_pair (& args [ARG_x1 ], bitmap -> width , bitmap -> height );
181+
182+ uint32_t skip_source_index ;
183+ bool skip_source_index_none ; // flag whether skip_value was None
184+
185+ if (args [ARG_skip_source_index ].u_obj == mp_const_none ) {
186+ skip_source_index = 0 ;
187+ skip_source_index_none = true;
188+ } else {
189+ skip_source_index = mp_obj_get_int (args [ARG_skip_source_index ].u_obj );
190+ skip_source_index_none = false;
191+ }
192+
193+ uint32_t skip_dest_index ;
194+ bool skip_dest_index_none ; // flag whether skip_self_value was None
195+
196+ if (args [ARG_skip_dest_index ].u_obj == mp_const_none ) {
197+ skip_dest_index = 0 ;
198+ skip_dest_index_none = true;
199+ } else {
200+ skip_dest_index = mp_obj_get_int (args [ARG_skip_dest_index ].u_obj );
201+ skip_dest_index_none = false;
202+ }
203+ common_hal_jpegio_jpegdecoder_decode_into (self , bitmap , scale , x , y , & lim , skip_source_index , skip_source_index_none , skip_dest_index , skip_dest_index_none );
204+
145205 return mp_const_none ;
146206}
147207STATIC MP_DEFINE_CONST_FUN_OBJ_KW (jpegio_jpegdecoder_decode_obj , 1 , jpegio_jpegdecoder_decode );
0 commit comments