28
28
#include "py/builtin.h"
29
29
#include "py/runtime.h"
30
30
31
+ #include "shared-bindings/bitmaptools/__init__.h"
31
32
#include "shared-bindings/displayio/Bitmap.h"
32
33
#include "shared-bindings/jpegio/JpegDecoder.h"
33
34
#include "shared-module/jpegio/JpegDecoder.h"
@@ -106,6 +107,15 @@ MP_DEFINE_CONST_FUN_OBJ_2(jpegio_jpegdecoder_open_obj, jpegio_jpegdecoder_open);
106
107
//| self,
107
108
//| bitmap: displayio.Bitmap,
108
109
//| 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,
109
119
//| ) -> None:
110
120
//| """Decode JPEG data
111
121
//|
@@ -115,21 +125,45 @@ MP_DEFINE_CONST_FUN_OBJ_2(jpegio_jpegdecoder_open_obj, jpegio_jpegdecoder_open);
115
125
//| The image is optionally downscaled by a factor of ``2**scale``.
116
126
//| Scaling by a factor of 8 (scale=3) is particularly efficient in terms of decoding time.
117
127
//|
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
+ //|
118
135
//| After a call to ``decode``, you must ``open`` a new JPEG. It is not
119
136
//| possible to repeatedly ``decode`` the same jpeg data, even if it is to
120
137
//| select different scales or crop regions from it.
121
138
//|
122
139
//| :param Bitmap bitmap: Optional output buffer
123
140
//| :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
124
153
//| """
125
154
//|
126
155
STATIC mp_obj_t jpegio_jpegdecoder_decode (mp_uint_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
127
156
jpegio_jpegdecoder_obj_t * self = MP_OBJ_TO_PTR (pos_args [0 ]);
128
157
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 };
130
159
static const mp_arg_t allowed_args [] = {
131
160
{ MP_QSTR_bitmap , MP_ARG_OBJ | MP_ARG_REQUIRED , {.u_obj = mp_const_none } },
132
161
{ 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 } },
133
167
};
134
168
mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
135
169
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_
141
175
int scale = args [ARG_scale ].u_int ;
142
176
mp_arg_validate_int_range (scale , 0 , 3 , MP_QSTR_scale );
143
177
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
+
145
205
return mp_const_none ;
146
206
}
147
207
STATIC MP_DEFINE_CONST_FUN_OBJ_KW (jpegio_jpegdecoder_decode_obj , 1 , jpegio_jpegdecoder_decode );
0 commit comments