Skip to content

Commit 403ea89

Browse files
committed
Initial paletts for OnDiskGif
1 parent 4e25a4f commit 403ea89

File tree

4 files changed

+119
-43
lines changed

4 files changed

+119
-43
lines changed

shared-bindings/gifio/OnDiskGif.c

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,16 @@
117117
//| """
118118
//| ...
119119
STATIC mp_obj_t gifio_ondiskgif_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
120-
mp_arg_check_num(n_args, n_kw, 1, 1, false);
121-
mp_obj_t arg = all_args[0];
120+
enum { ARG_filename, ARG_use_palette, NUM_ARGS };
121+
static const mp_arg_t allowed_args[] = {
122+
{ MP_QSTR_filename, MP_ARG_REQUIRED | MP_ARG_OBJ },
123+
{ MP_QSTR_use_palette, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
124+
};
125+
MP_STATIC_ASSERT(MP_ARRAY_SIZE(allowed_args) == NUM_ARGS);
126+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
127+
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
122128

129+
mp_obj_t arg = all_args[0];
123130
if (mp_obj_is_str(arg)) {
124131
arg = mp_call_function_2(MP_OBJ_FROM_PTR(&mp_builtin_open_obj), arg, MP_ROM_QSTR(MP_QSTR_rb));
125132
}
@@ -130,7 +137,7 @@ STATIC mp_obj_t gifio_ondiskgif_make_new(const mp_obj_type_t *type, size_t n_arg
130137

131138
gifio_ondiskgif_t *self = m_new_obj(gifio_ondiskgif_t);
132139
self->base.type = &gifio_ondiskgif_type;
133-
common_hal_gifio_ondiskgif_construct(self, MP_OBJ_TO_PTR(arg));
140+
common_hal_gifio_ondiskgif_construct(self, MP_OBJ_TO_PTR(arg), args[ARG_use_palette].u_bool);
134141

135142
return MP_OBJ_FROM_PTR(self);
136143
}
@@ -199,6 +206,20 @@ MP_DEFINE_CONST_FUN_OBJ_1(gifio_ondiskgif_get_bitmap_obj, gifio_ondiskgif_obj_ge
199206
MP_PROPERTY_GETTER(gifio_ondiskgif_bitmap_obj,
200207
(mp_obj_t)&gifio_ondiskgif_get_bitmap_obj);
201208

209+
//| palette: displayio.Palette
210+
//| """The palette for the current frame."""
211+
STATIC mp_obj_t gifio_ondiskgif_obj_get_palette(mp_obj_t self_in) {
212+
gifio_ondiskgif_t *self = MP_OBJ_TO_PTR(self_in);
213+
214+
check_for_deinit(self);
215+
return common_hal_gifio_ondiskgif_get_palette(self);
216+
}
217+
218+
MP_DEFINE_CONST_FUN_OBJ_1(gifio_ondiskgif_get_palette_obj, gifio_ondiskgif_obj_get_palette);
219+
220+
MP_PROPERTY_GETTER(gifio_ondiskgif_palette_obj,
221+
(mp_obj_t)&gifio_ondiskgif_get_palette_obj);
222+
202223
//| def next_frame(self) -> float:
203224
//| """Loads the next frame. Returns expected delay before the next frame in seconds."""
204225
STATIC mp_obj_t gifio_ondiskgif_obj_next_frame(mp_obj_t self_in) {
@@ -285,6 +306,7 @@ STATIC const mp_rom_map_elem_t gifio_ondiskgif_locals_dict_table[] = {
285306
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&gifio_ondiskgif___exit___obj) },
286307
{ MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&gifio_ondiskgif_height_obj) },
287308
{ MP_ROM_QSTR(MP_QSTR_bitmap), MP_ROM_PTR(&gifio_ondiskgif_bitmap_obj) },
309+
{ MP_ROM_QSTR(MP_QSTR_palette), MP_ROM_PTR(&gifio_ondiskgif_palette_obj) },
288310
{ MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&gifio_ondiskgif_width_obj) },
289311
{ MP_ROM_QSTR(MP_QSTR_next_frame), MP_ROM_PTR(&gifio_ondiskgif_next_frame_obj) },
290312
{ MP_ROM_QSTR(MP_QSTR_duration), MP_ROM_PTR(&gifio_ondiskgif_duration_obj) },

shared-bindings/gifio/OnDiskGif.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,14 @@
3232

3333
extern const mp_obj_type_t gifio_ondiskgif_type;
3434

35-
void common_hal_gifio_ondiskgif_construct(gifio_ondiskgif_t *self, pyb_file_obj_t *file);
35+
void common_hal_gifio_ondiskgif_construct(gifio_ondiskgif_t *self, pyb_file_obj_t *file, bool use_palette);
3636

3737
uint32_t common_hal_gifio_ondiskgif_get_pixel(gifio_ondiskgif_t *bitmap,
3838
int16_t x, int16_t y);
3939

4040
uint16_t common_hal_gifio_ondiskgif_get_height(gifio_ondiskgif_t *self);
4141
mp_obj_t common_hal_gifio_ondiskgif_get_bitmap(gifio_ondiskgif_t *self);
42+
mp_obj_t common_hal_gifio_ondiskgif_get_palette(gifio_ondiskgif_t *self);
4243
uint16_t common_hal_gifio_ondiskgif_get_width(gifio_ondiskgif_t *self);
4344
uint32_t common_hal_gifio_ondiskgif_next_frame(gifio_ondiskgif_t *self, bool setDirty);
4445
int32_t common_hal_gifio_ondiskgif_get_duration(gifio_ondiskgif_t *self);

shared-module/gifio/OnDiskGif.c

Lines changed: 85 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
#include "shared-bindings/gifio/OnDiskGif.h"
2828
#include "shared-bindings/displayio/Bitmap.h"
29+
#include "shared-bindings/displayio/Palette.h"
2930

3031
#include <string.h>
3132

@@ -34,7 +35,6 @@
3435

3536

3637
static int32_t GIFReadFile(GIFFILE *pFile, uint8_t *pBuf, int32_t iLen) {
37-
// mp_printf(&mp_plat_print, "GifReadFile len %d ", iLen);
3838
uint32_t iBytesRead;
3939
iBytesRead = iLen;
4040
pyb_file_obj_t *f = pFile->fHandle;
@@ -50,18 +50,15 @@ static int32_t GIFReadFile(GIFFILE *pFile, uint8_t *pBuf, int32_t iLen) {
5050
mp_raise_OSError(MP_EIO);
5151
}
5252
pFile->iPos = f->fp.fptr;
53-
// mp_printf(&mp_plat_print, " now at %d\n", pFile->iPos);
5453

5554
return bytes_read;
5655
} /* GIFReadFile() */
5756

5857
static int32_t GIFSeekFile(GIFFILE *pFile, int32_t iPosition) {
59-
// mp_printf(&mp_plat_print, "GifSeekFile %d ", iPosition);
6058
pyb_file_obj_t *f = pFile->fHandle;
6159

6260
f_lseek(&f->fp, iPosition);
6361
pFile->iPos = f->fp.fptr;
64-
// mp_printf(&mp_plat_print, " now at %d\n", pFile->iPos);
6562
return pFile->iPos;
6663
} /* GIFSeekFile() */
6764

@@ -71,10 +68,25 @@ static void GIFDraw(GIFDRAW *pDraw) {
7168
// The palette is either RGB565 or the original 24-bit RGB values
7269
// depending on the pixel type selected with gif.begin()
7370

74-
displayio_bitmap_t *bitmap = (displayio_bitmap_t *)pDraw->pUser;
75-
76-
uint8_t *s;
77-
uint16_t *d;
71+
gifio_ondiskgif_displayio_objs_t *displayio_objs = (gifio_ondiskgif_displayio_objs_t *)pDraw->pUser;
72+
displayio_bitmap_t *bitmap = displayio_objs->bitmap;
73+
displayio_palette_t *palette = displayio_objs->palette;
74+
75+
// Update the palette if we have one in RGB888
76+
if (palette != NULL) {
77+
uint8_t *pPal = pDraw->pPalette24;
78+
for (int p = 0; p < 256; p++) {
79+
uint8_t r = *pPal++;
80+
uint8_t g = *pPal++;
81+
uint8_t b = *pPal++;
82+
uint32_t color = (r << 16) + (g << 8) + b;
83+
common_hal_displayio_palette_set_color(palette, p, color);
84+
common_hal_displayio_palette_make_opaque(palette, p); // Transparency can change frame to frame
85+
}
86+
if (pDraw->ucHasTransparency) {
87+
common_hal_displayio_palette_make_transparent(palette, pDraw->ucTransparent);
88+
}
89+
}
7890

7991
int iWidth = pDraw->iWidth;
8092
if (iWidth + pDraw->iX > bitmap->width) {
@@ -87,11 +99,6 @@ static void GIFDraw(GIFDRAW *pDraw) {
8799

88100
int32_t row_start = (pDraw->y + pDraw->iY) * bitmap->stride;
89101
uint32_t *row = bitmap->data + row_start;
90-
s = pDraw->pPixels;
91-
d = (uint16_t *)row;
92-
93-
uint16_t *pPal;
94-
pPal = (uint16_t *)pDraw->pPalette;
95102

96103
if (pDraw->ucDisposalMethod == 2) { // restore to background color
97104
// Not supported currently. Need to reset the area the previous frame occupied
@@ -101,31 +108,53 @@ static void GIFDraw(GIFDRAW *pDraw) {
101108
// To workaround clear the gif.bitmap object yourself as required.
102109
}
103110

104-
uint8_t c, ucTransparent = pDraw->ucTransparent;
105-
d += pDraw->iX;
106-
if (pDraw->ucHasTransparency == 1) {
111+
if (palette != NULL) {
112+
uint8_t *s = pDraw->pPixels;
113+
uint8_t *d = (uint8_t *)row;
114+
115+
d += pDraw->iX;
107116
for (int x = 0; x < iWidth; x++)
108117
{
109-
c = *s++;
110-
if (c != ucTransparent) {
111-
*d = pPal[c];
112-
}
113-
d++;
118+
*d++ = *s++;
114119
}
115120
} else {
116-
for (int x = 0; x < iWidth; x++)
117-
{
118-
c = *s++;
119-
*d++ = pPal[c];
121+
// No palette writing RGB565_SWAPPED right to bitmap buffer
122+
uint8_t *s = pDraw->pPixels;
123+
;
124+
uint16_t *d = (uint16_t *)row;
125+
126+
uint16_t *pPal;
127+
pPal = (uint16_t *)pDraw->pPalette;
128+
129+
uint8_t c, ucTransparent = pDraw->ucTransparent;
130+
d += pDraw->iX;
131+
if (pDraw->ucHasTransparency == 1) {
132+
for (int x = 0; x < iWidth; x++)
133+
{
134+
c = *s++;
135+
if (c != ucTransparent) {
136+
*d = pPal[c];
137+
}
138+
d++;
139+
}
140+
} else {
141+
for (int x = 0; x < iWidth; x++)
142+
{
143+
c = *s++;
144+
*d++ = pPal[c];
145+
}
120146
}
121147
}
122148
}
123149

124-
void common_hal_gifio_ondiskgif_construct(gifio_ondiskgif_t *self, pyb_file_obj_t *file) {
125-
// mp_printf(&mp_plat_print, "Begin OnDiskGif\n");
150+
void common_hal_gifio_ondiskgif_construct(gifio_ondiskgif_t *self, pyb_file_obj_t *file, bool use_palette) {
126151
self->file = file;
127152

128-
GIF_begin(&self->gif, GIF_PALETTE_RGB565_BE);
153+
if (use_palette == true) {
154+
GIF_begin(&self->gif, GIF_PALETTE_RGB888);
155+
} else {
156+
GIF_begin(&self->gif, GIF_PALETTE_RGB565_BE);
157+
}
129158

130159
self->gif.iError = GIF_SUCCESS;
131160
self->gif.pfnRead = GIFReadFile;
@@ -143,10 +172,22 @@ void common_hal_gifio_ondiskgif_construct(gifio_ondiskgif_t *self, pyb_file_obj_
143172
mp_arg_error_invalid(MP_QSTR_file);
144173
}
145174

175+
int bpp = 16;
176+
if (use_palette == true) {
177+
mp_printf(&mp_plat_print, "Using palette\n");
178+
displayio_palette_t *palette = m_new_obj(displayio_palette_t);
179+
palette->base.type = &displayio_palette_type;
180+
common_hal_displayio_palette_construct(palette, 256, false);
181+
self->displayio_objs.palette = palette;
182+
bpp = 8;
183+
} else {
184+
self->displayio_objs.palette = NULL;
185+
}
186+
146187
displayio_bitmap_t *bitmap = m_new_obj(displayio_bitmap_t);
147188
bitmap->base.type = &displayio_bitmap_type;
148-
common_hal_displayio_bitmap_construct(bitmap, self->gif.iCanvasWidth, self->gif.iCanvasHeight, 16);
149-
self->bitmap = bitmap;
189+
common_hal_displayio_bitmap_construct(bitmap, self->gif.iCanvasWidth, self->gif.iCanvasHeight, bpp);
190+
self->displayio_objs.bitmap = bitmap;
150191

151192
GIFINFO info;
152193
GIF_getInfo(&self->gif, &info);
@@ -158,12 +199,13 @@ void common_hal_gifio_ondiskgif_construct(gifio_ondiskgif_t *self, pyb_file_obj_
158199

159200
void common_hal_gifio_ondiskgif_deinit(gifio_ondiskgif_t *self) {
160201
self->file = NULL;
161-
common_hal_displayio_bitmap_deinit(self->bitmap);
162-
self->bitmap = NULL;
202+
common_hal_displayio_bitmap_deinit(self->displayio_objs.bitmap);
203+
self->displayio_objs.bitmap = NULL;
204+
self->displayio_objs.palette = NULL;
163205
}
164206

165207
bool common_hal_gifio_ondiskgif_deinited(gifio_ondiskgif_t *self) {
166-
return self->bitmap == NULL;
208+
return self->displayio_objs.bitmap == NULL;
167209
}
168210

169211
uint16_t common_hal_gifio_ondiskgif_get_height(gifio_ondiskgif_t *self) {
@@ -175,7 +217,11 @@ uint16_t common_hal_gifio_ondiskgif_get_width(gifio_ondiskgif_t *self) {
175217
}
176218

177219
mp_obj_t common_hal_gifio_ondiskgif_get_bitmap(gifio_ondiskgif_t *self) {
178-
return MP_OBJ_FROM_PTR(self->bitmap);
220+
return MP_OBJ_FROM_PTR(self->displayio_objs.bitmap);
221+
}
222+
223+
mp_obj_t common_hal_gifio_ondiskgif_get_palette(gifio_ondiskgif_t *self) {
224+
return MP_OBJ_FROM_PTR(self->displayio_objs.palette);
179225
}
180226

181227
int32_t common_hal_gifio_ondiskgif_get_duration(gifio_ondiskgif_t *self) {
@@ -196,17 +242,18 @@ int32_t common_hal_gifio_ondiskgif_get_max_delay(gifio_ondiskgif_t *self) {
196242

197243
uint32_t common_hal_gifio_ondiskgif_next_frame(gifio_ondiskgif_t *self, bool setDirty) {
198244
int nextDelay = 0;
199-
int result = GIF_playFrame(&self->gif, &nextDelay, self->bitmap);
245+
int result = 0;
246+
result = GIF_playFrame(&self->gif, &nextDelay, &self->displayio_objs);
200247

201248
if ((result >= 0) && (setDirty)) {
202249
displayio_area_t dirty_area = {
203250
.x1 = 0,
204251
.y1 = 0,
205-
.x2 = self->bitmap->width,
206-
.y2 = self->bitmap->height,
252+
.x2 = self->displayio_objs.bitmap->width,
253+
.y2 = self->displayio_objs.bitmap->height,
207254
};
208255

209-
displayio_bitmap_set_dirty_area(self->bitmap, &dirty_area);
256+
displayio_bitmap_set_dirty_area(self->displayio_objs.bitmap, &dirty_area);
210257
}
211258

212259
return nextDelay;

shared-module/gifio/OnDiskGif.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,20 @@
3434

3535
#include "lib/AnimatedGIF/AnimatedGIF_circuitpy.h"
3636
#include "shared-module/displayio/Bitmap.h"
37+
#include "shared-module/displayio/Palette.h"
3738

3839
#include "extmod/vfs_fat.h"
3940

41+
typedef struct {
42+
displayio_bitmap_t *bitmap;
43+
displayio_palette_t *palette;
44+
} gifio_ondiskgif_displayio_objs_t;
45+
4046
typedef struct {
4147
mp_obj_base_t base;
4248
GIFIMAGE gif;
4349
pyb_file_obj_t *file;
44-
displayio_bitmap_t *bitmap;
50+
gifio_ondiskgif_displayio_objs_t displayio_objs;
4551
int32_t duration;
4652
int32_t frame_count;
4753
int32_t min_delay;

0 commit comments

Comments
 (0)