From b10e9e0c3730cd409ffa7dabb3718f60b7eaacf2 Mon Sep 17 00:00:00 2001 From: raster Date: Fri, 30 Sep 2011 07:10:40 +0000 Subject: [PATCH] From: Jiyoun Park Subject: [E-devel] [Patch] support Animation gif's disposal mode I make patch support animation gif disposal mode. Before, gif loader only decode & render based on previous frame. This patch can support "do not dispose mode" & "restore background mode". So It solve after image problem of restore background mode. git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/evas@63716 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- src/modules/loaders/gif/evas_image_load_gif.c | 186 +++++++++++++++++++++----- 1 file changed, 154 insertions(+), 32 deletions(-) diff --git a/src/modules/loaders/gif/evas_image_load_gif.c b/src/modules/loaders/gif/evas_image_load_gif.c index 3433dba..976df0d 100644 --- a/src/modules/loaders/gif/evas_image_load_gif.c +++ b/src/modules/loaders/gif/evas_image_load_gif.c @@ -209,6 +209,8 @@ _evas_image_load_frame_image_data(Image_Entry *ie, GifFileType *gif, Image_Entry int cache_h; int cur_h; int cur_w; + int disposal = 0; + int bg_val = 0; DATA32 *ptr; Gif_Frame *gif_frame = NULL; @@ -282,6 +284,25 @@ _evas_image_load_frame_image_data(Image_Entry *ie, GifFileType *gif, Image_Entry bg = gif->SBackGroundColor; cmap = (gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap); + if (!cmap) + { + DGifCloseFile(gif); + for (i = 0; i < h; i++) + { + free(rows[i]); + } + free(rows); + if (frame->data) free(frame->data); + *error = EVAS_LOAD_ERROR_CORRUPT_FILE; + return EINA_FALSE; + } + + /* get the background value */ + r = cmap->Colors[bg].Red; + g = cmap->Colors[bg].Green; + b = cmap->Colors[bg].Blue; + bg_val = ARGB_JOIN(0xff, r, g, b); + per_inc = 100.0 / (((double)w) * h); cur_h = h; cur_w = w; @@ -314,7 +335,6 @@ _evas_image_load_frame_image_data(Image_Entry *ie, GifFileType *gif, Image_Entry goto error; } } - if (!_find_frame(ie, cur_frame - 1, &new_frame)) { *error = EVAS_LOAD_ERROR_CORRUPT_FILE; @@ -322,51 +342,153 @@ _evas_image_load_frame_image_data(Image_Entry *ie, GifFileType *gif, Image_Entry } else { + Gif_Frame *gif_frame = NULL; ptr_src = new_frame->data; - memcpy(ptr, ptr_src, siz); - } - - /* composite frames */ - ptr = ptr + cache_w * y; - - for (i = 0; i < cur_h; i++) - { - ptr = ptr + x; - for (j = 0; j < cur_w; j++) + if (new_frame->info) { - if (rows[i][j] == alpha) + gif_frame = (Gif_Frame *)(new_frame->info); + disposal = gif_frame->frame_info.disposal; + } + switch(disposal) /* we only support disposal flag 0,1,2 */ + { + case 1: /* Do not dispose. need previous frame*/ + memcpy(ptr, ptr_src, siz); + /* composite frames */ + ptr = ptr + cache_w * y; + + for (i = 0; i < cur_h; i++) { - ptr++ ; + ptr = ptr + x; + for (j = 0; j < cur_w; j++) + { + if (rows[i][j] == alpha) + { + ptr++ ; + } + else + { + r = cmap->Colors[rows[i][j]].Red; + g = cmap->Colors[rows[i][j]].Green; + b = cmap->Colors[rows[i][j]].Blue; + *ptr++ = ARGB_JOIN(0xff, r, g, b); + } + per += per_inc; + } + ptr = ptr + (cache_w - (x + cur_w)); } - else + break; + case 2: /* Restore to background color */ + memcpy(ptr, ptr_src, siz); + /* composite frames */ + for (i = 0; i < cache_h; i++) { - r = cmap->Colors[rows[i][j]].Red; - g = cmap->Colors[rows[i][j]].Green; - b = cmap->Colors[rows[i][j]].Blue; - *ptr++ = ARGB_JOIN(0xff, r, g, b); + if ((i < y) || (i >= (y + cur_h))) + { + for (j = 0; j < cache_w; j++) + { + *ptr = bg_val; + ptr++; + } + } + else + { + int i1, j1; + i1 = i -y; + + for (j = 0; j < cache_w; j++) + { + j1 = j - x; + if ((j < x) || (j >= (x + cur_w))) + { + *ptr = bg_val; + ptr++; + } + else + { + r = cmap->Colors[rows[i1][j1]].Red; + g = cmap->Colors[rows[i1][j1]].Green; + b = cmap->Colors[rows[i1][j1]].Blue; + *ptr++ = ARGB_JOIN(0xff, r, g, b); + } + } + } } - per += per_inc; + break; + case 0: /* No disposal specified */ + default: + memset(ptr, 0, siz); + for (i = 0; i < cache_h; i++) + { + if ((i < y) || (i >= (y + cur_h))) + { + for (j = 0; j < cache_w; j++) + { + *ptr = bg_val; + ptr++; + } + } + else + { + int i1, j1; + i1 = i -y; + + for (j = 0; j < cache_w; j++) + { + j1 = j - x; + if ((j < x) || (j >= (x + cur_w))) + { + *ptr = bg_val; + ptr++; + } + else + { + r = cmap->Colors[rows[i1][j1]].Red; + g = cmap->Colors[rows[i1][j1]].Green; + b = cmap->Colors[rows[i1][j1]].Blue; + *ptr++ = ARGB_JOIN(0xff, r, g, b); + } + } + } + } + break; } - ptr = ptr + (cache_w - (x + cur_w)); } } - else + else /* first frame decoding */ { - ptr = ptr + cache_w * y; - - for (i = 0; i < cur_h; i++) + /* fill background color */ + for (i = 0; i < cache_h; i++) { - ptr = ptr + x; - for (j = 0; j < cur_w; j++) + if ((i < y) || (i >= (y + cur_h))) + { + for (j = 0; j < cache_w; j++) + { + *ptr = bg_val; + ptr++; + } + } + else { - r = cmap->Colors[rows[i][j]].Red; - g = cmap->Colors[rows[i][j]].Green; - b = cmap->Colors[rows[i][j]].Blue; - *ptr++ = ARGB_JOIN(0xff, r, g, b); + int i1, j1; + i1 = i -y; - per += per_inc; + for (j = 0; j < cache_w; j++) + { + j1 = j - x; + if ((j < x) || (j >= (x + cur_w))) + { + *ptr = bg_val; + ptr++; + } + else + { + r = cmap->Colors[rows[i1][j1]].Red; + g = cmap->Colors[rows[i1][j1]].Green; + b = cmap->Colors[rows[i1][j1]].Blue; + *ptr++ = ARGB_JOIN(0xff, r, g, b); + } + } } - ptr = ptr + (cache_w - (x + cur_w)); } } -- 2.7.4