summaryrefslogtreecommitdiff
path: root/apps/plugins/imageviewer/gif/gif.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/imageviewer/gif/gif.c')
-rw-r--r--apps/plugins/imageviewer/gif/gif.c69
1 files changed, 53 insertions, 16 deletions
diff --git a/apps/plugins/imageviewer/gif/gif.c b/apps/plugins/imageviewer/gif/gif.c
index 672735af94..c3cad71e10 100644
--- a/apps/plugins/imageviewer/gif/gif.c
+++ b/apps/plugins/imageviewer/gif/gif.c
@@ -31,9 +31,11 @@ static struct gif_decoder decoder;
31 31
32static char print[32]; /* use a common snprintf() buffer */ 32static char print[32]; /* use a common snprintf() buffer */
33 33
34/* decompressed image in the possible sizes (1,2,4,8), wasting the other */ 34/* pointers to decompressed frame in the possible sizes ds = (1,2,4,8)
35/* max 32 frames */ 35 * basicaly equivalent to *disp[n][4] where n is the number of frames
36static unsigned char *disp[GIF_MAX_FRAMES][9]; 36 * in gif file. The matrix is allocated after decoded frames.
37 */
38static unsigned char **disp;
37static unsigned char *disp_buf; 39static unsigned char *disp_buf;
38 40
39#if defined(HAVE_LCD_COLOR) 41#if defined(HAVE_LCD_COLOR)
@@ -81,10 +83,7 @@ static int load_image(char *filename, struct image_info *info,
81 struct gif_decoder *p_decoder = &decoder; 83 struct gif_decoder *p_decoder = &decoder;
82 84
83 unsigned char *memory, *memory_max; 85 unsigned char *memory, *memory_max;
84 size_t memory_size; 86 size_t memory_size, img_size, disp_size;
85
86 /* cleanup */
87 memset(&disp, 0, sizeof(disp));
88 87
89 /* align buffer */ 88 /* align buffer */
90 memory = (unsigned char *)((intptr_t)(buf + 3) & ~3); 89 memory = (unsigned char *)((intptr_t)(buf + 3) & ~3);
@@ -153,18 +152,50 @@ static int load_image(char *filename, struct image_info *info,
153 info->frames_count = p_decoder->frames_count; 152 info->frames_count = p_decoder->frames_count;
154 info->delay = p_decoder->delay; 153 info->delay = p_decoder->delay;
155 154
156 //p_decoder->native_img_size = (p_decoder->native_img_size + 3) & ~3; 155 /* check mem constraints
157 disp_buf = p_decoder->mem + 156 * each frame can have 4 scaled versions with ds = (1,2,4,8)
158 ((p_decoder->native_img_size*p_decoder->frames_count + 3) & ~3); 157 */
158 img_size = (p_decoder->native_img_size*p_decoder->frames_count + 3) & ~3;
159 disp_size = (sizeof(unsigned char *)*p_decoder->frames_count*4 + 3) & ~3;
160
161 if (memory_size < img_size + disp_size)
162 {
163 /* No memory to allocate disp matrix */
164 rb->splashf(HZ, "%s", GifErrorString(D_GIF_ERR_NOT_ENOUGH_MEM));
165 return PLUGIN_ERROR;
166 }
167
168 disp = (unsigned char **)(p_decoder->mem + img_size);
169 disp_buf = (unsigned char *)disp + disp_size;
159 170
160 *buf_size = memory_max - disp_buf; 171 *buf_size = memory_max - disp_buf;
161 172
173 /* set all pointers to NULL initially */
174 memset(disp, 0, sizeof(unsigned char *)*p_decoder->frames_count*4);
175
162 return PLUGIN_OK; 176 return PLUGIN_OK;
163} 177}
164 178
179/* small helper to convert scalling factor ds
180 * into disp[frame][] array index
181 */
182static int ds2index(int ds)
183{
184 int index = 0;
185
186 ds >>= 1;
187 while (ds)
188 {
189 index++;
190 ds >>=1;
191 }
192
193 return index;
194}
195
165static int get_image(struct image_info *info, int frame, int ds) 196static int get_image(struct image_info *info, int frame, int ds)
166{ 197{
167 unsigned char **p_disp = &disp[frame][ds]; /* short cut */ 198 unsigned char **p_disp = disp + frame*4 + ds2index(ds);
168 struct gif_decoder *p_decoder = &decoder; 199 struct gif_decoder *p_decoder = &decoder;
169 200
170 info->width = p_decoder->width / ds; 201 info->width = p_decoder->width / ds;
@@ -192,14 +223,20 @@ static int get_image(struct image_info *info, int frame, int ds)
192 223
193 if (disp_buf + size >= p_decoder->mem + p_decoder->mem_size) 224 if (disp_buf + size >= p_decoder->mem + p_decoder->mem_size)
194 { 225 {
195 /* have to discard the current */ 226 /* have to discard scaled versions */
196 int i; 227 for (int i=0; i<p_decoder->frames_count; i++)
197 for (i=1; i<=8; i++) 228 {
198 disp[frame][i] = NULL; /* invalidate all bitmaps */ 229 /* leave unscaled pointer allone,
230 * set rest to NULL
231 */
232 p_disp = disp + i*4 + 1;
233 memset(p_disp, 0, 3*sizeof(unsigned char *));
234 }
199 235
200 /* start again from the beginning of the buffer */ 236 /* start again from the beginning of the buffer */
201 disp_buf = p_decoder->mem + 237 disp_buf = p_decoder->mem +
202 p_decoder->native_img_size*p_decoder->frames_count; 238 p_decoder->native_img_size*p_decoder->frames_count +
239 sizeof(unsigned char *)*p_decoder->frames_count*4;
203 } 240 }
204 241
205 *p_disp = disp_buf; 242 *p_disp = disp_buf;