diff options
Diffstat (limited to 'apps/plugins/imageviewer/gif/gif.c')
-rw-r--r-- | apps/plugins/imageviewer/gif/gif.c | 69 |
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 | ||
32 | static char print[32]; /* use a common snprintf() buffer */ | 32 | static 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 |
36 | static unsigned char *disp[GIF_MAX_FRAMES][9]; | 36 | * in gif file. The matrix is allocated after decoded frames. |
37 | */ | ||
38 | static unsigned char **disp; | ||
37 | static unsigned char *disp_buf; | 39 | static 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 | */ | ||
182 | static 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 | |||
165 | static int get_image(struct image_info *info, int frame, int ds) | 196 | static 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; |