From: Jiyoun Park <jy0703.park@samsung.com>
authorraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Fri, 30 Sep 2011 07:10:40 +0000 (07:10 +0000)
committerraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Fri, 30 Sep 2011 07:10:40 +0000 (07:10 +0000)
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

index 3433dba..976df0d 100644 (file)
@@ -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));
           }
      }