raster pushed a commit to branch master.

commit 28c2bd1918e5b8a46408ed17352098b44c76a6a7
Author: Carsten Haitzler (Rasterman) <[email protected]>
Date:   Sat Jul 6 15:11:59 2013 +0900

    evas - gif: refactor a lot of the gif animated loader code to be much 
cleaner.
---
 src/modules/evas/loaders/gif/evas_image_load_gif.c | 548 ++++++---------------
 1 file changed, 155 insertions(+), 393 deletions(-)

diff --git a/src/modules/evas/loaders/gif/evas_image_load_gif.c 
b/src/modules/evas/loaders/gif/evas_image_load_gif.c
index 4eccd4e..24993c7 100644
--- a/src/modules/evas/loaders/gif/evas_image_load_gif.c
+++ b/src/modules/evas/loaders/gif/evas_image_load_gif.c
@@ -185,6 +185,98 @@ _evas_image_load_frame_image_des_info(GifFileType *gif, 
Image_Entry_Frame *frame
    return EINA_TRUE;
 }
 
+#define PIX(_x, _y) rows[yin + _y][xin + _x]
+#define CMAP(_v) cmap->Colors[_v]
+
+static void
+_expand_gif_rows(GifRowType *rows, ColorMapObject *cmap, DATA32 *ptr,
+                 int rowpix, int xin, int yin, int w, int h,
+                 int x, int y, int alpha, Eina_Bool overwrite)
+{
+   int xx, yy, pix;
+   DATA32 *p;
+   
+   if (alpha >= 0)
+     {
+        if (overwrite)
+          {
+             for (yy = 0; yy < h; yy++)
+               {
+                  p = ptr + ((y + yy) * rowpix) + x;
+                  for (xx = 0; xx < w; xx++)
+                    {
+                       pix = PIX(xx, yy);
+                       if (pix != alpha)
+                         *p = ARGB_JOIN(0xff, CMAP(pix).Red,
+                                        CMAP(pix).Green, CMAP(pix).Blue);
+                       else *p = 0;
+                       p++;
+                    }
+               }
+          }
+        else
+          {
+             for (yy = 0; yy < h; yy++)
+               {
+                  p = ptr + ((y + yy) * rowpix) + x;
+                  for (xx = 0; xx < w; xx++)
+                    {
+                       pix = PIX(xx, yy);
+                       if (pix != alpha)
+                         *p = ARGB_JOIN(0xff, CMAP(pix).Red,
+                                        CMAP(pix).Green, CMAP(pix).Blue);
+                       p++;
+                    }
+               }
+          }
+     }
+   else
+     {
+        for (yy = 0; yy < h; yy++)
+          {
+             p = ptr + ((y + yy) * rowpix) + x;
+             for (xx = 0; xx < w; xx++)
+               {
+                  pix = PIX(xx, yy);
+                  *p = ARGB_JOIN(0xff, CMAP(pix).Red,
+                                 CMAP(pix).Green, CMAP(pix).Blue);
+                  p++;
+               }
+          }
+     }
+}
+
+static void
+_copy_pixels(DATA32 *ptr_src, DATA32 *ptr, int rowpix,
+             int x, int y, int w, int h)
+{
+   DATA32 *p1, *p2, *pe;
+   int yy;
+   
+   if ((w <= 0) || (h <= 0)) return;
+   for (yy = 0; yy < h; yy++)
+     {
+        p1 = ptr_src + ((y + yy) * rowpix) + x;
+        p2 = ptr + ((y + yy) * rowpix) + x;
+        for (pe = p2 + w; p2 < pe;) *p2++ = *p1++;
+     }
+}
+
+static void
+_fill_pixels(DATA32 val, DATA32 *ptr, int rowpix,
+             int x, int y, int w, int h)
+{
+   DATA32 *p2, *pe;
+   int yy;
+   
+   if ((w <= 0) || (h <= 0)) return;
+   for (yy = 0; yy < h; yy++)
+     {
+        p2 = ptr + ((y + yy) * rowpix) + x;
+        for (pe = p2 + w; p2 < pe;) *p2++ = val;
+     }
+}
+
 static Eina_Bool
 _evas_image_load_frame_image_data(Eina_File *f,
                                   const Evas_Image_Load_Opts *opts EINA_UNUSED,
@@ -193,27 +285,13 @@ _evas_image_load_frame_image_data(Eina_File *f,
                                   GifFileType *gif, Image_Entry_Frame *frame, 
int *error)
 {
    ColorMapObject *cmap;
-   GifRowType     *rows;
-   GifPixelType   *tmp = NULL; /*for skip gif line */
-   DATA32         *ptr;
-   Gif_Frame      *gif_frame = NULL;
-
-//   double          per;
-//   double          per_inc;
-   size_t          siz;
-   int             intoffset[] = { 0, 4, 2, 1 };
-   int             intjump[] = { 8, 8, 4, 2 };
-   int x, y, w, h;
-   int i, j;
-   int bg;
-   int r, g, b, alpha;
-   int cache_w, cache_h;
-   int cur_h, cur_w;
-   int disposal = 0;
-   int bg_val = 0;
-   /* for scale down decoding */
-   int scale_ratio = 1;
-   int scale_w, scale_h, scale_x, scale_y;
+   GifRowType *rows;
+   DATA32 *ptr, pad = 0xff000000;
+   Gif_Frame *gif_frame = NULL;
+   int intoffset[] = { 0, 4, 2, 1 };
+   int intjump[] = { 8, 8, 4, 2 };
+   int  x, y, w, h, i, bg, alpha, cache_w, cache_h, cur_h, cur_w, yy;
+   int  disposal = 0, xin = 0, yin = 0;
 
    if ((!gif) || (!frame)) return EINA_FALSE;
 
@@ -222,139 +300,85 @@ _evas_image_load_frame_image_data(Eina_File *f,
    h = gif->Image.Height;
    x = gif->Image.Left;
    y = gif->Image.Top;
+   cur_h = h;
+   cur_w = w;
    cache_w = prop->w;
    cache_h = prop->h;
 
-   /* if user don't set scale down, default scale_ratio is 1 */
-   // disable scale down by until gif is handled right
-   //if (opts->scale_down_by > 1) scale_ratio = opts->scale_down_by;
-   
-   scale_w = w / scale_ratio;
-   scale_h = h / scale_ratio;
-   scale_x = x / scale_ratio;
-   scale_y = y / scale_ratio;
-
-   rows = malloc(scale_h * sizeof(GifRowType *));
-
+   rows = malloc((h * sizeof(GifRowType *)) + (w * h * sizeof(GifPixelType)));
    if (!rows)
      {
         *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
         return EINA_FALSE;
      }
-   for (i = 0; i < scale_h; i++)
+   for (yy = 0; yy < h; yy++)
      {
-        rows[i] = NULL;
+        rows[yy] = ((unsigned char *)rows) + (h * sizeof(GifRowType *)) +
+          (yy * w * sizeof(GifPixelType));
      }
-   /* alloc memory according to scaled size */
-   for (i = 0; i < scale_h; i++)
-     {
-        rows[i] = malloc(scale_w * sizeof(GifPixelType));
-        if (!rows[i])
-          {
-             for (i = 0; i < scale_h; i++)
-               {
-                  if (rows[i])
-                    {
-                       free(rows[i]);
-                    }
-               }
-             free(rows);
-             *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
-             return EINA_FALSE;
-          }
-     }
-
-//   if (scale_ratio > 1)
-//     {
-//        tmp = malloc(w * sizeof(GifPixelType));
-//        if (!tmp)
-//          {
-//             *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
-//             goto error;
-//          }
-//     }
 
    if (gif->Image.Interlace)
      {
-        Eina_Bool multiple;
-        int scale_j;
         for (i = 0; i < 4; i++)
           {
-             for (j = intoffset[i]; j < h; j += intjump[i])
+             for (yy = intoffset[i]; yy < h; yy += intjump[i])
                {
-                  scale_j = j / scale_ratio;
-                  multiple = ((j % scale_ratio) ? EINA_FALSE : EINA_TRUE);
-
-                  if (multiple && (scale_j < scale_h))
-                    DGifGetLine(gif, rows[scale_j], w);
-                  else
-                    DGifGetLine(gif, tmp, w);
+                  if (DGifGetLine(gif, rows[yy], w) != GIF_OK)
+                    {
+                       *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
+                       goto error;
+                    }
                }
           }
      }
    else
      {
-        for (i = 0; i < scale_h; i++)
+        for (yy = 0; yy < h; yy++)
           {
-             if (DGifGetLine(gif, rows[i], w) != GIF_OK)
+             if (DGifGetLine(gif, rows[yy], w) != GIF_OK)
                {
-                  *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
+                  *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
                   goto error;
               }
-             if (scale_ratio > 1)
-               {
-                  /* we use down sample method for scale down, so skip other 
line */
-                  for (j = 0; j < (scale_ratio - 1); j++)
-                    {
-                       if (DGifGetLine(gif, tmp, w) != GIF_OK)
-                         {
-                            *error = 
EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
-                            goto error;
-                         }
-                    }
-               }
           }
      }
 
-   if (scale_ratio > 1)
-     {
-        if (tmp) free(tmp);
-        tmp = NULL;
-     }
-
    alpha = gif_frame->frame_info.transparent;
-   siz = cache_w *cache_h * sizeof(DATA32);
-   frame->data = malloc(siz);
+   if ((prop->alpha) || (alpha >= 0)) pad = 0x00000000;
+   frame->data = malloc(cache_w * cache_h * sizeof(DATA32));
    if (!frame->data)
      {
         *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
         goto error;
      }
-   ptr = frame->data;
    bg = gif->SBackGroundColor;
    cmap = (gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap);
 
    if (!cmap)
      {
         DGifCloseFile(gif);
-        for (i = 0; i < scale_h; i++)
-          {
-             free(rows[i]);
-          }
-        free(rows);
         if (frame->data) free(frame->data);
         *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
-        return EINA_FALSE;
+        goto error;
      }
 
-//   per_inc = 100.0 / (((double)w) * h);
-//   per = 0.0;
-   cur_h = scale_h;
-   cur_w = scale_w;
-
    if (cur_h > cache_h) cur_h = cache_h;
    if (cur_w > cache_w) cur_w = cache_w;
 
+   // clip the image region to be within current image size and note the inset
+   if (x < 0)
+     {
+        w += x; xin = -x; x = 0;
+     }
+   if ((x + w) > cache_w) w = cache_w - x;
+   if (y < 0)
+     {
+        h += y; yin = -y; y = 0;
+     }
+   if ((y + h) > cache_h) h = cache_h - y;
+   
+   // data ptr to write to
+   ptr = frame->data;
    if (frame->index > 1)
      {
         /* get previous frame only frame index is bigger than 1 */
@@ -372,10 +396,10 @@ _evas_image_load_frame_image_data(Eina_File *f,
              goto error;
           }
         /* load previous frame of cur_frame */
-        for (j = start_frame; j < cur_frame ; j++)
+        for (i = start_frame; i < cur_frame; i++)
           {
              // FIXME : that one -v
-             if (!evas_image_load_specific_frame(f, opts, prop, animated, j, 
error))
+             if (!evas_image_load_specific_frame(f, opts, prop, animated, i, 
error))
                {
                   *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
                   goto error;
@@ -389,320 +413,58 @@ _evas_image_load_frame_image_data(Eina_File *f,
         else
           {
              Gif_Frame *gif_frame2 = NULL;
-             int xx, yy, xin = 0, yin = 0;
              
              ptr_src = new_frame->data;
              if (new_frame->info)
                {
                   gif_frame2 = (Gif_Frame *)(new_frame->info);
-                  // the disposal mode of this frame
                   disposal = gif_frame2->frame_info.disposal;
-                  // background rgba color value
                   gif_frame->bg_val = gif_frame2->bg_val;
-                  bg_val = gif_frame->bg_val;
-#if 1                  
-                  // clip the image desc region to be within current image
-                  // size and note the inset
-                  if (x < 0)
-                    {
-                       w += x; xin = -x; x = 0;
-                    }
-                  if ((x + w) > cache_w)
-                    {
-                       w = cache_w - x;
-                    }
-                  if (y < 0)
-                    {
-                       h += y; yin = -y; y = 0;
-                    }
-                  if ((y + h) > cache_h)
-                    {
-                       h = cache_h - y;
-                    }
-#define PIX(_x, _y) rows[yin + _y][xin + (_x * scale_ratio)]
-#define CMAP(_v) cmap->Colors[_v]
                   switch (disposal)
                     {
                      case 0: // no nothing
-                       memset(ptr, 0, siz);
-                       for (yy = 0; yy < h; yy++)
-                         {
-                            ptr = frame->data;
-                            ptr += ((y + yy) * cache_w) + x;
-                            for (xx = 0; xx < w; xx++)
-                              {
-                                 if (PIX(xx, yy) != alpha)
-                                   {
-                                      r = CMAP(PIX(xx, yy)).Red;
-                                      g = CMAP(PIX(xx, yy)).Green;
-                                      b = CMAP(PIX(xx, yy)).Blue;
-                                      *ptr = ARGB_JOIN(0xff, r, g, b);
-                                   }
-                                 else
-                                   *ptr = 0;
-                                 ptr++;
-                              }
-                         }
+                     case 2: // restore bg ... browsers don't respect bg, so 
neither shall we.
+                       // fill in the area OUTSIDE the image with 0/black
+                       _fill_pixels(pad, ptr, cache_w, 0, 0, cache_w, y);
+                       _fill_pixels(pad, ptr, cache_w, 0, y + h, cache_w, 
cache_h - (y + h));
+                       _fill_pixels(pad, ptr, cache_w, 0, y, x, h);
+                       _fill_pixels(pad, ptr, cache_w, x + w, y, cache_w - (x 
+ w), h);
+                       _expand_gif_rows(rows, cmap, ptr, cache_w, xin, yin,
+                                        w, h, x, y, alpha, EINA_TRUE);
                        break;
                      case 1: // leave as-is
-                       memcpy(ptr, ptr_src, siz);
-                       for (yy = 0; yy < h; yy++)
-                         {
-                            ptr = frame->data;
-                            ptr += ((y + yy) * cache_w) + x;
-                            for (xx = 0; xx < w; xx++)
-                              {
-                                 if (PIX(xx, yy) != alpha)
-                                   {
-                                      r = CMAP(PIX(xx, yy)).Red;
-                                      g = CMAP(PIX(xx, yy)).Green;
-                                      b = CMAP(PIX(xx, yy)).Blue;
-                                      *ptr = ARGB_JOIN(0xff, r, g, b);
-                                   }
-                                 ptr++;
-                              }
-                         }
-                       break;
-                     case 2: // restore bg
-                       for (yy = 0; yy < cache_h; yy++)
-                         {
-                            for (xx = 0; xx < cache_w; xx++)
-                              {
-                                 *ptr = bg_val;
-                                 ptr++;
-                              }
-                         }
-                       for (yy = 0; yy < h; yy++)
-                         {
-                            ptr = frame->data;
-                            ptr += ((y + yy) * cache_w) + x;
-                            for (xx = 0; xx < w; xx++)
-                              {
-                                 if (PIX(xx, yy) != alpha)
-                                   {
-                                      r = CMAP(PIX(xx, yy)).Red;
-                                      g = CMAP(PIX(xx, yy)).Green;
-                                      b = CMAP(PIX(xx, yy)).Blue;
-                                      *ptr = ARGB_JOIN(0xff, r, g, b);
-                                   }
-                                 ptr++;
-                              }
-                         }
-                       break;
                      case 3: // previous image
-                       memcpy(ptr, ptr_src, siz);
-                       for (yy = 0; yy < h; yy++)
-                         {
-                            ptr = frame->data;
-                            ptr += ((y + yy) * cache_w) + x;
-                            for (xx = 0; xx < w; xx++)
-                              {
-                                 if (PIX(xx, yy) != alpha)
-                                   {
-                                      r = CMAP(PIX(xx, yy)).Red;
-                                      g = CMAP(PIX(xx, yy)).Green;
-                                      b = CMAP(PIX(xx, yy)).Blue;
-                                      *ptr = ARGB_JOIN(0xff, r, g, b);
-                                   }
-                                 ptr++;
-                              }
-                         }
+                       _copy_pixels(ptr_src, ptr, cache_w, 0, 0,
+                                    cache_w, cache_h);
+                       _expand_gif_rows(rows, cmap, ptr, cache_w, xin, yin,
+                                        w, h, x, y, alpha, EINA_FALSE);
                        break;
                      default:
                        break;
                     }
-#else
-             switch (disposal) /* we only support disposal flag 0,1,2 */
-               {
-                case 1: /* Do not dispose. need previous frame*/
-                  memcpy(ptr, ptr_src, siz);
-                  /* only decoding image descriptor's region */
-                  ptr = ptr + cache_w * scale_y;
-                  
-                  for (i = 0; i < cur_h; i++)
-                    {
-                       ptr = ptr + scale_x;
-                       for (j = 0; j < cur_w; j++)
-                         {
-                            if (rows[i][j * scale_ratio] == alpha)
-                              {
-                                 ptr++;
-                              }
-                            else
-                              {
-                                 r = cmap->Colors[rows[i][j * 
scale_ratio]].Red;
-                                 g = cmap->Colors[rows[i][j * 
scale_ratio]].Green;
-                                 b = cmap->Colors[rows[i][j * 
scale_ratio]].Blue;
-                                 *ptr++ = ARGB_JOIN(0xff, r, g, b);
-                              }
-                            per += per_inc;
-                         }
-                       ptr = ptr + (cache_w - (scale_x + cur_w));
-                    }
-                  break;
-                case 2: /* Restore to background color */
-                   memcpy(ptr, ptr_src, siz);
-                   /* composite frames */
-                   for (i = 0; i < cache_h; i++)
-                    {
-                       if ((i < scale_y) || (i >= (scale_y + cur_h)))
-                         {
-                            for (j = 0; j < cache_w; j++)
-                              {
-                                 *ptr = bg_val;
-                                 ptr++;
-                              }
-                         }
-                       else
-                         {
-                            int i1, j1;
-                            i1 = i - scale_y;
-                            
-                            for (j = 0; j < cache_w; j++)
-                              {
-                                 j1 = j - scale_x;
-                                 if ((j < scale_x) || (j >= (scale_x + cur_w)))
-                                   {
-                                      *ptr = bg_val;
-                                      ptr++;
-                                   }
-                                 else
-                                   {
-                                      if (rows[i][j * scale_ratio] == alpha)
-                                        {
-                                           ptr++;
-                                        }
-                                      else
-                                        {
-                                           r = cmap->Colors[rows[i1][j1 * 
scale_ratio]].Red;
-                                           g = cmap->Colors[rows[i1][j1 * 
scale_ratio]].Green;
-                                           b = cmap->Colors[rows[i1][j1 * 
scale_ratio]].Blue;
-                                           *ptr++ = ARGB_JOIN(0xff, r, g, b);
-                                        }
-                                   }
-                              }
-                         }
-                    }
-                   break;
-                case 3: /* Restore previous */
-                case 0: /* No disposal specified */
-                default:
-                   memset(ptr, 0, siz);
-                   for (i = 0; i < gif_frame2->image_des.h; i++)
-                     {
-                        if ((i < scale_y) || (i >= (scale_y + cur_h)))
-                          {
-                             for (j = 0; j < gif_frame2->image_des.w; j++)
-                               {
-                                  *ptr = bg_val;
-                                  ptr++;
-                               }
-                          }
-                        else
-                          {
-                             int i1, j1;
-                             i1 = i - scale_y;
-
-                             for (j = 0; j < gif_frame2->image_des.w; j++)
-                               {
-                                  j1 = j - scale_x;
-                                  if ((j < scale_x) || (j >= (scale_x + 
cur_w)))
-                                    {
-                                       *ptr = bg_val;
-                                       ptr++;
-                                    }
-                                  else
-                                    {
-                                      if (rows[i][j * scale_ratio] == alpha)
-                                        {
-                                           ptr++;
-                                        }
-                                      else
-                                        {
-                                           r = cmap->Colors[rows[i1][j1 * 
scale_ratio]].Red;
-                                           g = cmap->Colors[rows[i1][j1 * 
scale_ratio]].Green;
-                                           b = cmap->Colors[rows[i1][j1 * 
scale_ratio]].Blue;
-                                           *ptr++ = ARGB_JOIN(0xff, r, g, b);
-                                        }
-                                    }
-                               }
-                          }
-                     }
-                   break;
-               }
-#endif        
                }
           }
      }
    else /* first frame decoding */
      {
         /* 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);
-        gif_frame->bg_val = bg_val;
-
-        memset(ptr, 0, siz);
-
-        /* fill background color */
-        for (i = 0; i < cache_h; i++)
-          {
-             /* the row's of logical screen not overap with frame */
-             if ((i < scale_y) || (i >= (scale_y + cur_h)))
-               {
-                  for (j = 0; j < cache_w; j++)
-                    {
-                       *ptr = bg_val;
-                       ptr++;
-                    }
-               }
-             else
-               {
-                  int i1, j1;
-                  i1 = i -scale_y;
-
-                  for (j = 0; j < cache_w; j++)
-                    {
-                       j1 = j - scale_x;
-                       if ((j < scale_x) || (j >= (scale_x + cur_w)))
-                         {
-                            *ptr = bg_val;
-                            ptr++;
-                         }
-                       else
-                         {
-                            if (rows[i1][j1 * scale_ratio] == alpha)
-                              {
-                                 ptr++;
-                              }
-                            else
-                              {
-                                 r = cmap->Colors[rows[i1][j1 * 
scale_ratio]].Red;
-                                 g = cmap->Colors[rows[i1][j1 * 
scale_ratio]].Green;
-                                 b = cmap->Colors[rows[i1][j1 * 
scale_ratio]].Blue;
-                                 *ptr++ = ARGB_JOIN(0xff, r, g, b);
-                              }
-                         }
-                    }
-               }
-          }
+        gif_frame->bg_val = RGB_JOIN(cmap->Colors[bg].Red, 
+                                     cmap->Colors[bg].Green,
+                                     cmap->Colors[bg].Blue);
+        // fill in the area OUTSIDE the image with 0/black
+        _fill_pixels(pad, ptr, cache_w, 0, 0, cache_w, y);
+        _fill_pixels(pad, ptr, cache_w, 0, y + h, cache_w, cache_h - (y + h));
+        _fill_pixels(pad, ptr, cache_w, 0, y, x, h);
+        _fill_pixels(pad, ptr, cache_w, x + w, y, cache_w - (x + w), h);
+        _expand_gif_rows(rows, cmap, ptr, cache_w, xin, yin,
+                         w, h, x, y, alpha, EINA_TRUE);
      }
 
-   for (i = 0; i < scale_h; i++)
-     {
-        if (rows[i]) free(rows[i]);
-     }
    if (rows) free(rows);
    frame->loaded = EINA_TRUE;
    return EINA_TRUE;
 error:
-   for (i = 0; i < scale_h; i++)
-     {
-        if (rows[i]) free(rows[i]);
-     }
    if (rows) free(rows);
-   if (tmp) free(tmp);
    return EINA_FALSE;
 }
 

-- 

------------------------------------------------------------------------------
This SF.net email is sponsored by Windows:

Build for Windows Store.

http://p.sf.net/sfu/windows-dev2dev

Reply via email to