@@ -22,6 +22,8 @@ typedef struct _PNG_decode_target {
22
22
void *target;
23
23
uint8_t flags = 0 ;
24
24
Point position = {0 , 0 };
25
+ Rect source = {0 , 0 , 0 , 0 };
26
+ Point scale = {1 , 1 };
25
27
} _PNG_decode_target;
26
28
27
29
typedef struct _PNG_obj_t {
@@ -120,10 +122,15 @@ MICROPY_EVENT_POLL_HOOK
120
122
PicoGraphics *current_graphics = (PicoGraphics *)target->target ;
121
123
Point current_position = target->position ;
122
124
uint8_t current_flags = target->flags ;
125
+ Point scale = target->scale ;
123
126
// "pixel" is slow and clipped,
124
127
// guaranteeing we wont draw png data out of the framebuffer..
125
128
// Can we clip beforehand and make this faster?
126
- current_position.y += pDraw->y ;
129
+
130
+ if (pDraw->y < target->source .y || pDraw->y >= target->source .y + target->source .h ) return ;
131
+
132
+ current_position.y += pDraw->y * scale.y ;
133
+ current_position -= Point (0 , target->source .y );
127
134
128
135
// mp_printf(&mp_plat_print, "Drawing scanline at %d, %dbpp, type: %d, width: %d pitch: %d alpha: %d\n", y, pDraw->iBpp, pDraw->iPixelType, pDraw->iWidth, pDraw->iPitch, pDraw->iHasAlpha);
129
136
uint8_t *pixel = (uint8_t *)pDraw->pPixels ;
@@ -132,21 +139,23 @@ MICROPY_EVENT_POLL_HOOK
132
139
uint8_t r = *pixel++;
133
140
uint8_t g = *pixel++;
134
141
uint8_t b = *pixel++;
142
+ if (x < target->source .x || x >= target->source .x + target->source .w ) continue ;
135
143
current_graphics->set_pen (r, g, b);
136
- current_graphics->pixel ( current_position);
137
- current_position.x ++ ;
144
+ current_graphics->rectangle ({ current_position. x , current_position. y , scale. x , scale. y } );
145
+ current_position.x += scale. x ;
138
146
}
139
147
} else if (pDraw->iPixelType == PNG_PIXEL_TRUECOLOR_ALPHA) {
140
148
for (int x = 0 ; x < pDraw->iWidth ; x++) {
141
149
uint8_t r = *pixel++;
142
150
uint8_t g = *pixel++;
143
151
uint8_t b = *pixel++;
144
152
uint8_t a = *pixel++;
153
+ if (x < target->source .x || x >= target->source .x + target->source .w ) continue ;
145
154
if (a) {
146
155
current_graphics->set_pen (r, g, b);
147
- current_graphics->pixel ( current_position);
156
+ current_graphics->rectangle ({ current_position. x , current_position. y , scale. x , scale. y } );
148
157
}
149
- current_position.x ++ ;
158
+ current_position.x += scale. x ;
150
159
}
151
160
} else if (pDraw->iPixelType == PNG_PIXEL_INDEXED) {
152
161
for (int x = 0 ; x < pDraw->iWidth ; x++) {
@@ -158,6 +167,7 @@ MICROPY_EVENT_POLL_HOOK
158
167
i >>= (x & 0b1 ) ? 0 : 4 ;
159
168
i &= 0xf ;
160
169
}
170
+ if (x < target->source .x || x >= target->source .x + target->source .w ) continue ;
161
171
// grab the colour from the palette
162
172
uint8_t r = pDraw->pPalette [(i * 3 ) + 0 ];
163
173
uint8_t g = pDraw->pPalette [(i * 3 ) + 1 ];
@@ -168,10 +178,14 @@ MICROPY_EVENT_POLL_HOOK
168
178
if (current_flags & FLAG_NO_DITHER) {
169
179
// Posterized output to RGB332
170
180
current_graphics->set_pen (RGB (r, g, b).to_rgb332 ());
171
- current_graphics->pixel ( current_position);
181
+ current_graphics->rectangle ({ current_position. x , current_position. y , scale. x , scale. y } );
172
182
} else {
173
183
// Dithered output to RGB332
174
- current_graphics->set_pixel_dither (current_position, {r, g, b});
184
+ for (auto px = 0 ; px < scale.x ; px++) {
185
+ for (auto py = 0 ; py < scale.y ; py++) {
186
+ current_graphics->set_pixel_dither (current_position + Point{px, py}, {r, g, b});
187
+ }
188
+ }
175
189
}
176
190
} else if (current_graphics->pen_type == PicoGraphics::PEN_P8
177
191
|| current_graphics->pen_type == PicoGraphics::PEN_P4
@@ -184,17 +198,21 @@ MICROPY_EVENT_POLL_HOOK
184
198
closest = 0 ;
185
199
}
186
200
current_graphics->set_pen (closest);
187
- current_graphics->pixel ( current_position);
201
+ current_graphics->rectangle ({ current_position. x , current_position. y , scale. x , scale. y } );
188
202
} else {
189
- current_graphics->set_pixel_dither (current_position, {r, g, b});
190
- }
203
+ for (auto px = 0 ; px < scale.x ; px++) {
204
+ for (auto py = 0 ; py < scale.y ; py++) {
205
+ current_graphics->set_pixel_dither (current_position + Point{px, py}, {r, g, b});
206
+ }
207
+ }
208
+ }
191
209
192
210
} else {
193
211
current_graphics->set_pen (r, g, b);
194
- current_graphics->pixel ( current_position);
212
+ current_graphics->rectangle ({ current_position. x , current_position. y , scale. x , scale. y } );
195
213
}
196
214
}
197
- current_position.x ++ ;
215
+ current_position.x += scale. x ;
198
216
}
199
217
}
200
218
}
@@ -215,6 +233,8 @@ mp_obj_t _PNG_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, co
215
233
self->base .type = &PNG_type;
216
234
self->png = m_new_class (PNG);
217
235
236
+ mp_printf (&mp_plat_print, " PNG RAM %fK\n " , sizeof (PNG) / 1024 .0f );
237
+
218
238
ModPicoGraphics_obj_t *graphics = (ModPicoGraphics_obj_t *)MP_OBJ_TO_PTR (args[ARG_picographics].u_obj );
219
239
220
240
self->decode_callback = PNGDraw;
@@ -265,13 +285,21 @@ mp_obj_t _PNG_openRAM(mp_obj_t self_in, mp_obj_t buffer) {
265
285
266
286
// decode
267
287
mp_obj_t _PNG_decode (size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
268
- enum { ARG_self, ARG_x, ARG_y, ARG_scale, ARG_dither };
288
+ enum { ARG_self, ARG_x, ARG_y, ARG_scale, ARG_dither,
289
+ ARG_source_x, ARG_source_y, ARG_source_w, ARG_source_h,
290
+ ARG_scale_x, ARG_scale_y };
269
291
static const mp_arg_t allowed_args[] = {
270
292
{ MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ },
271
293
{ MP_QSTR_x, MP_ARG_INT, {.u_int = 0 } },
272
294
{ MP_QSTR_y, MP_ARG_INT, {.u_int = 0 } },
273
295
{ MP_QSTR_scale, MP_ARG_INT, {.u_int = 0 } },
274
296
{ MP_QSTR_dither, MP_ARG_OBJ, {.u_obj = mp_const_true} },
297
+ { MP_QSTR_source_x, MP_ARG_INT, {.u_int = 0 } },
298
+ { MP_QSTR_source_y, MP_ARG_INT, {.u_int = 0 } },
299
+ { MP_QSTR_source_w, MP_ARG_INT, {.u_int = -1 } },
300
+ { MP_QSTR_source_h, MP_ARG_INT, {.u_int = -1 } },
301
+ { MP_QSTR_scale_x, MP_ARG_INT, {.u_int = 1 } },
302
+ { MP_QSTR_scale_y, MP_ARG_INT, {.u_int = 1 } },
275
303
};
276
304
277
305
mp_arg_val_t args[MP_ARRAY_SIZE (allowed_args)];
@@ -293,6 +321,15 @@ mp_obj_t _PNG_decode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args)
293
321
294
322
pngdec_open_helper (self);
295
323
324
+ int source_x = args[ARG_source_x].u_int ;
325
+ int source_y = args[ARG_source_y].u_int ;
326
+ int source_w = args[ARG_source_w].u_int == -1 ? self->width : args[ARG_source_w].u_int ;
327
+ int source_h = args[ARG_source_h].u_int == -1 ? self->height : args[ARG_source_h].u_int ;
328
+
329
+ self->decode_target ->source = {source_x, source_y, source_w, source_h};
330
+
331
+ self->decode_target ->scale = {args[ARG_scale_x].u_int , args[ARG_scale_y].u_int };
332
+
296
333
result = self->png ->decode (self->decode_target , 0 );
297
334
298
335
// Close the file since we've opened it on-demand
0 commit comments