Skip to content

Commit 3ee8d0b

Browse files
authored
Merge pull request #7878 from gamblor21/gifio_palettes
Palettes for OnDiskGif
2 parents b5a26c7 + ae73032 commit 3ee8d0b

File tree

4 files changed

+112
-38
lines changed

4 files changed

+112
-38
lines changed

shared-bindings/gifio/OnDiskGif.c

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,20 +117,27 @@
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];
122-
123-
if (mp_obj_is_str(arg)) {
124-
arg = mp_call_function_2(MP_OBJ_FROM_PTR(&mp_builtin_open_obj), arg, MP_ROM_QSTR(MP_QSTR_rb));
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);
128+
129+
mp_obj_t filename = all_args[0];
130+
if (mp_obj_is_str(filename)) {
131+
filename = mp_call_function_2(MP_OBJ_FROM_PTR(&mp_builtin_open_obj), filename, MP_ROM_QSTR(MP_QSTR_rb));
125132
}
126133

127-
if (!mp_obj_is_type(arg, &mp_type_fileio)) {
134+
if (!mp_obj_is_type(filename, &mp_type_fileio)) {
128135
mp_raise_TypeError(translate("file must be a file opened in byte mode"));
129136
}
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(filename), 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: Optional[displayio.Palette]
210+
//| """The palette for the current frame if it exists."""
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: 79 additions & 30 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_t *ondiskgif = (gifio_ondiskgif_t *)pDraw->pUser;
72+
displayio_bitmap_t *bitmap = ondiskgif->bitmap;
73+
displayio_palette_t *palette = ondiskgif->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,9 +172,20 @@ 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+
displayio_palette_t *palette = m_new_obj(displayio_palette_t);
178+
palette->base.type = &displayio_palette_type;
179+
common_hal_displayio_palette_construct(palette, 256, false);
180+
self->palette = palette;
181+
bpp = 8;
182+
} else {
183+
self->palette = NULL;
184+
}
185+
146186
displayio_bitmap_t *bitmap = m_new_obj(displayio_bitmap_t);
147187
bitmap->base.type = &displayio_bitmap_type;
148-
common_hal_displayio_bitmap_construct(bitmap, self->gif.iCanvasWidth, self->gif.iCanvasHeight, 16);
188+
common_hal_displayio_bitmap_construct(bitmap, self->gif.iCanvasWidth, self->gif.iCanvasHeight, bpp);
149189
self->bitmap = bitmap;
150190

151191
GIFINFO info;
@@ -160,6 +200,7 @@ void common_hal_gifio_ondiskgif_deinit(gifio_ondiskgif_t *self) {
160200
self->file = NULL;
161201
common_hal_displayio_bitmap_deinit(self->bitmap);
162202
self->bitmap = NULL;
203+
self->palette = NULL;
163204
}
164205

165206
bool common_hal_gifio_ondiskgif_deinited(gifio_ondiskgif_t *self) {
@@ -178,6 +219,13 @@ mp_obj_t common_hal_gifio_ondiskgif_get_bitmap(gifio_ondiskgif_t *self) {
178219
return MP_OBJ_FROM_PTR(self->bitmap);
179220
}
180221

222+
mp_obj_t common_hal_gifio_ondiskgif_get_palette(gifio_ondiskgif_t *self) {
223+
if (self->palette == NULL) {
224+
return mp_const_none;
225+
}
226+
return MP_OBJ_FROM_PTR(self->palette);
227+
}
228+
181229
int32_t common_hal_gifio_ondiskgif_get_duration(gifio_ondiskgif_t *self) {
182230
return self->duration;
183231
}
@@ -196,7 +244,8 @@ int32_t common_hal_gifio_ondiskgif_get_max_delay(gifio_ondiskgif_t *self) {
196244

197245
uint32_t common_hal_gifio_ondiskgif_next_frame(gifio_ondiskgif_t *self, bool setDirty) {
198246
int nextDelay = 0;
199-
int result = GIF_playFrame(&self->gif, &nextDelay, self->bitmap);
247+
int result = 0;
248+
result = GIF_playFrame(&self->gif, &nextDelay, self);
200249

201250
if ((result >= 0) && (setDirty)) {
202251
displayio_area_t dirty_area = {

shared-module/gifio/OnDiskGif.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
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

@@ -42,6 +43,7 @@ typedef struct {
4243
GIFIMAGE gif;
4344
pyb_file_obj_t *file;
4445
displayio_bitmap_t *bitmap;
46+
displayio_palette_t *palette;
4547
int32_t duration;
4648
int32_t frame_count;
4749
int32_t min_delay;

0 commit comments

Comments
 (0)