[*] impelment scale down decoding feature.
authorJiyoun Park <jy0703.park@samsung.com>
Tue, 4 Oct 2011 10:56:12 +0000 (19:56 +0900)
committerJiyoun Park <jy0703.park@samsung.com>
Tue, 4 Oct 2011 11:03:26 +0000 (20:03 +0900)
add scale down feature to bmp,gif,png
using down sample method

Change-Id: I42e9044b2b5136e7b697f90679353b706fd85e45

src/modules/loaders/bmp/evas_image_load_bmp.c
src/modules/loaders/gif/evas_image_load_gif.c
src/modules/loaders/png/evas_image_load_png.c

index a391ef8..47e5854 100644 (file)
@@ -259,7 +259,20 @@ evas_image_load_file_head_bmp(Image_Entry *ie, const char *file, const char *key
           *error = EVAS_LOAD_ERROR_GENERIC;
        goto close_file;
      }
-   
+   /* It is not bad idea that bmp loader support scale down decoding
+    * because of memory issue in mobile world.
+    * But there are many bit count(bit per pixel) type in BMP format.
+    * Generally, 1,2,4,8 bit count have row risk of memory problem,
+    * so I add scale down feature only when bit count is 16 or 24 or 32 */
+   if (ie->load_opts.scale_down_by > 1)
+     {
+        if ((bit_count == 16) || (bit_count == 24) || (bit_count == 32))
+          {
+             w /= ie->load_opts.scale_down_by;
+             h /= ie->load_opts.scale_down_by;
+          }
+     }
+
    if (bit_count < 16)
      {
         if ((palette_size < 0) || (palette_size > 256)) pal_num = 256;
@@ -337,6 +350,7 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
    char hasa = 0;
    int x = 0, y = 0, w = 0, h = 0, planes = 0, bit_count = 0, image_size = 0,
      comp = 0, hdpi = 0, vdpi = 0, palette_size = -1, important_colors = 0;
+   int scale_ratio = 1, image_w = 0, image_h = 0;
    unsigned int offset = 0, head_size = 0;
    unsigned int *pal = NULL, pal_num = 0, *pix = NULL, *surface = NULL, fix,
      rmask = 0, gmask = 0, bmask = 0, amask = 0;
@@ -533,13 +547,37 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
           *error = EVAS_LOAD_ERROR_GENERIC;
        goto close_file;
      }
-   
+   /* It is not bad idea that bmp loader support scale down decoding
+    * because of memory issue in mobile world.
+    * But there are many bit count(bit per pixel) type in BMP format.
+    * Generally, 1,2,4,8 bit count have row risk of memory problem,
+    * so I add scale down feature only when bit count is 16 or 24 or 32 */
+   if(ie->load_opts.scale_down_by > 1)
+     {
+        if ((bit_count == 16) || (bit_count == 24) || (bit_count == 32))
+          scale_ratio = ie->load_opts.scale_down_by;
+     }
+
+   if (scale_ratio > 1)
+     {
+        image_w = w;
+        image_h = h;
+        w /= scale_ratio;
+        h /= scale_ratio;
+
+        if ((w < 1) || (h < 1) )
+          {
+             *error = EVAS_LOAD_ERROR_GENERIC;
+             goto close_file;
+          }
+     }
+
    if ((w != (int)ie->w) || (h != (int)ie->h))
      {
        *error = EVAS_LOAD_ERROR_GENERIC;
        goto close_file;
      }
-   evas_cache_image_surface_alloc(ie, w, h);
+   evas_cache_image_surface_alloc(ie, ie->w, ie->h);
    surface = evas_cache_image_pixels(ie);
    if (!surface)
      {
@@ -892,22 +930,41 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
      }
    else if ((bit_count == 16) || (bit_count == 24) || (bit_count == 32))
      {
+        /* Row size is rounded up to a multiple of 4bytes */
+        int row_size = 0;
+        int read_line = 0; /* total read line */
+
+        row_size = ceil((double)(image_w * bit_count) / 32) * 4;
         if (comp == 0) // no compression
           {
              fseek(f, offset, SEEK_SET);
-             buffer = malloc(image_size + 8); // add 8 for padding to avoid checks
+             if (scale_ratio == 1)
+               buffer = malloc(image_size + 8); // add 8 for padding to avoid checks
+             else
+               buffer = malloc(row_size); // scale down is usually set because of memory issue, so read line by line
              if (!buffer)
                {
                   *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
                   goto close_file;
                }
-             buffer_end = buffer + image_size;
+             if (scale_ratio == 1)
+               buffer_end = buffer + image_size;
+             else
+               buffer_end = buffer + row_size;
+
              p = buffer;
-             if (fread(buffer, image_size, 1, f) != 1) goto close_file;
+             if (scale_ratio == 1)
+               {
+                  if (fread(buffer, image_size, 1, f) != 1) goto close_file;
+               }
+             else
+               {
+                  if (fread(buffer, row_size, 1, f) != 1) goto close_file;
+               }
              if (bit_count == 16)
                {
                   unsigned short tmp;
-                  
+
                   pix = surface;
                   for (y = 0; y < h; y++)
                     {
@@ -920,13 +977,29 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
                             g = (tmp >> 2) & 0xf8; g |= g >> 5;
                             b = (tmp << 3) & 0xf8; b |= b >> 5;
                             *pix = ARGB_JOIN(0xff, r, g, b);
-                            p += 2;
+                            if (scale_ratio > 1)
+                              p += 2 * scale_ratio;
+                            else
+                              p += 2;
                             if (p >= buffer_end) break;
                             pix++;
                          }
-                       fix = (int)(((unsigned long)p) & 0x3);
-                       if (fix > 0) p += 4 - fix; // align row read
-                       if (p >= buffer_end) break;
+                       if (scale_ratio > 1)
+                         {
+                            read_line += scale_ratio;
+                            if (read_line >= image_h) break;
+
+                            fseek(f, row_size * (scale_ratio - 1), SEEK_CUR);
+                            if (fread(buffer, row_size, 1, f) != 1) goto close_file;
+                            p = buffer;
+                            buffer_end = buffer + row_size;
+                         }
+                       else
+                         {
+                            fix = (int)(((unsigned long)p) & 0x3);
+                            if (fix > 0) p += 4 - fix; // align row read
+                            if (p >= buffer_end) break;
+                         }
                     }
                }
              else if (bit_count == 24)
@@ -941,13 +1014,29 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
                             g = p[1];
                             r = p[2];
                             *pix = ARGB_JOIN(0xff, r, g, b);
-                            p += 3;
+                            if (scale_ratio > 1)
+                              p += 3 * scale_ratio;
+                            else
+                              p += 3;
                             if (p >= buffer_end) break;
                             pix++;
                          }
-                       fix = (int)(((unsigned long)p) & 0x3);
-                       if (fix > 0) p += 4 - fix; // align row read
-                       if (p >= buffer_end) break;
+                       if (scale_ratio > 1)
+                         {
+                            read_line += scale_ratio;
+                            if (read_line >= image_h) break;
+
+                            fseek(f, row_size * (scale_ratio - 1), SEEK_CUR);
+                            if (fread(buffer, row_size, 1, f) != 1) goto close_file;
+                            p = buffer;
+                            buffer_end = buffer + row_size;
+                         }
+                       else
+                         {
+                            fix = (int)(((unsigned long)p) & 0x3);
+                            if (fix > 0) p += 4 - fix; // align row read
+                            if (p >= buffer_end) break;
+                         }
                     }
                }
              else if (bit_count == 32)
@@ -966,13 +1055,29 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
                             if (a) none_zero_alpha = 1;
                             if (!hasa) a = 0xff;
                             *pix = ARGB_JOIN(a, r, g, b);
-                            p += 4;
+                            if (scale_ratio > 1)
+                              p += 4 * scale_ratio;
+                            else
+                              p += 4;
                             if (p >= buffer_end) break;
                             pix++;
                          }
-                       fix = (int)(((unsigned long)p) & 0x3);
-                       if (fix > 0) p += 4 - fix; // align row read
-                       if (p >= buffer_end) break;
+                       if (scale_ratio > 1)
+                         {
+                            read_line += scale_ratio;
+                            if (read_line >= image_h) break;
+
+                            fseek(f, row_size * (scale_ratio - 1), SEEK_CUR);
+                            if (fread(buffer, row_size, 1, f) != 1) goto close_file;
+                            p = buffer;
+                            buffer_end = buffer + row_size;
+                         }
+                       else
+                         {
+                            fix = (int)(((unsigned long)p) & 0x3);
+                            if (fix > 0) p += 4 - fix; // align row read
+                            if (p >= buffer_end) break;
+                         }
                     }
                   if (!none_zero_alpha)
                     {
@@ -996,15 +1101,32 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
              if (!read_uint(f, &bmask)) goto close_file;
 
              fseek(f, offset, SEEK_SET);
-             buffer = malloc(image_size + 8); // add 8 for padding to avoid checks
+
+             if (scale_ratio == 1)
+               buffer = malloc(image_size + 8); // add 8 for padding to avoid checks
+             else
+               buffer = malloc(row_size); // scale down is usually set because of memory issue, so read line by line
+
              if (!buffer)
                {
                   *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
                   goto close_file;
                }
-             buffer_end = buffer + image_size;
+             if (scale_ratio == 1)
+               buffer_end = buffer + image_size;
+             else
+               buffer_end = buffer + row_size;
+
              p = buffer;
-             if (fread(buffer, image_size, 1, f) != 1) goto close_file;
+             if (scale_ratio == 1)
+               {
+                  if (fread(buffer, image_size, 1, f) != 1) goto close_file;
+               }
+             else
+               {
+                  if (fread(buffer, row_size, 1, f) != 1) goto close_file;
+               }
+
              if ((bit_count == 16) && 
                  (rmask == 0xf800) && (gmask == 0x07e0) && (bmask == 0x001f)
                  )
@@ -1023,13 +1145,28 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
                             g = (tmp >> 3) & 0xfc; g |= g >> 6;
                             b = (tmp << 3) & 0xf8; b |= b >> 5;
                             *pix = ARGB_JOIN(0xff, r, g, b);
-                            p += 2;
+                            if (scale_ratio > 1)
+                              p += 2 * scale_ratio;
+                            else
+                              p += 2;
                             if (p >= buffer_end) break;
                             pix++;
                          }
-                       fix = (int)(((unsigned long)p) & 0x3);
-                       if (fix > 0) p += 4 - fix; // align row read
-                       if (p >= buffer_end) break;
+                       if (scale_ratio > 1)
+                         {
+                            read_line += scale_ratio;
+                            if (read_line >= image_h) break;
+                            fseek(f, row_size * (scale_ratio - 1), SEEK_CUR);
+                            if (fread(buffer, row_size, 1, f) != 1) goto close_file;
+                            p = buffer;
+                            buffer_end = buffer + row_size;
+                         }
+                       else
+                         {
+                            fix = (int)(((unsigned long)p) & 0x3);
+                            if (fix > 0) p += 4 - fix; // align row read
+                            if (p >= buffer_end) break;
+                         }
                     }
                }
              else if ((bit_count == 16) && 
@@ -1050,13 +1187,28 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
                             g = (tmp >> 2) & 0xf8; g |= g >> 5;
                             b = (tmp << 3) & 0xf8; b |= b >> 5;
                             *pix = ARGB_JOIN(0xff, r, g, b);
-                            p += 2;
+                            if (scale_ratio > 1)
+                              p += 2 * scale_ratio;
+                            else
+                              p += 2;
                             if (p >= buffer_end) break;
                             pix++;
                          }
-                       fix = (int)(((unsigned long)p) & 0x3);
-                       if (fix > 0) p += 4 - fix; // align row read
-                       if (p >= buffer_end) break;
+                       if (scale_ratio > 1)
+                         {
+                            read_line += scale_ratio;
+                            if (read_line >= image_h) break;
+                            fseek(f, row_size * (scale_ratio - 1), SEEK_CUR);
+                            if (fread(buffer, row_size, 1, f) != 1) goto close_file;
+                            p = buffer;
+                            buffer_end = buffer + row_size;
+                         }
+                       else
+                         {
+                            fix = (int)(((unsigned long)p) & 0x3);
+                            if (fix > 0) p += 4 - fix; // align row read
+                            if (p >= buffer_end) break;
+                         }
                     }
                }
              else if (bit_count == 32)
@@ -1073,13 +1225,28 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
                             a = p[3];
                             if (!hasa) a = 0xff;
                             *pix = ARGB_JOIN(a, r, g, b);
-                            p += 4;
+                            if (scale_ratio > 1)
+                              p += 4 * scale_ratio;
+                            else
+                              p += 4;
                             if (p >= buffer_end) break;
                             pix++;
                          }
-                       fix = (int)(((unsigned long)p) & 0x3);
-                       if (fix > 0) p += 4 - fix; // align row read
-                       if (p >= buffer_end) break;
+                       if (scale_ratio > 1)
+                         {
+                            read_line += scale_ratio;
+                            if (read_line >= image_h) break;
+                            fseek(f, row_size * (scale_ratio - 1), SEEK_CUR);
+                            if (fread(buffer, row_size, 1, f) != 1) goto close_file;
+                            p = buffer;
+                            buffer_end = buffer + row_size;
+                         }
+                       else
+                         {
+                            fix = (int)(((unsigned long)p) & 0x3);
+                            if (fix > 0) p += 4 - fix; // align row read
+                            if (p >= buffer_end) break;
+                         }
                     }
                }
              else
index 0f2e738..220afe1 100644 (file)
@@ -188,31 +188,26 @@ _evas_image_load_frame_image_des_info(GifFileType *gif, Image_Entry_Frame *frame
 static Eina_Bool
 _evas_image_load_frame_image_data(Image_Entry *ie, GifFileType *gif, Image_Entry_Frame *frame, int *error)
 {
-   int                 w;
-   int                 h;
-   int                 x;
-   int                 y;
-   int                 i,j;
+   int                 w, h, x, y;
+   int                 i, j;
    int                 bg;
-   int                 r;
-   int                 g;
-   int                 b;
+   int                 r, g, b;
    int                 alpha;
-   double              per;
-   double              per_inc;
+   double              per, per_inc;
    ColorMapObject     *cmap;
    GifRowType         *rows;
+   GifRowType         *tmp; /*for skip gif line */
    int                 intoffset[] = { 0, 4, 2, 1 };
    int                 intjump[] = { 8, 8, 4, 2 };
    size_t              siz;
-   int                 cache_w;
-   int                 cache_h;
-   int                 cur_h;
-   int                 cur_w;
+   int                 cache_w, cache_h, cur_w, cur_h;
    int                 disposal = 0;
    int                 bg_val = 0;
    DATA32             *ptr;
    Gif_Frame          *gif_frame = NULL;
+   /* for scale down decoding */
+   int                 scale_ratio = 1;
+   int                 scale_w, scale_h, scale_x, scale_y;
 
    if ((!gif) || (!frame)) return EINA_FALSE;
 
@@ -224,22 +219,42 @@ _evas_image_load_frame_image_data(Image_Entry *ie, GifFileType *gif, Image_Entry
    cache_w = ie->w;
    cache_h = ie->h;
 
-   rows = malloc(h * sizeof(GifRowType *));
+   /* if user don't set scale down, default scale_ratio is 1 */
+   if (ie->load_opts.scale_down_by > 1) scale_ratio = ie->load_opts.scale_down_by;
+   scale_w = w / scale_ratio;
+   scale_h = h / scale_ratio;
+   scale_x = x / scale_ratio;
+   scale_y = y / scale_ratio;
+
+   if (scale_ratio > 1)
+     {
+        tmp = malloc(w * sizeof(GifPixelType));
+        if (!tmp)
+          {
+             *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
+             return EINA_FALSE;
+          }
+     }
+
+   rows = malloc(scale_h * sizeof(GifRowType *));
+
    if (!rows)
      {
         *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
         return EINA_FALSE;
      }
-   for (i = 0; i < h; i++)
+
+   for (i = 0; i < scale_h; i++)
      {
         rows[i] = NULL;
      }
-   for (i = 0; i < h; i++)
+   /* alloc memory according to scaled size */
+   for (i = 0; i < scale_h; i++)
      {
         rows[i] = malloc(w * sizeof(GifPixelType));
         if (!rows[i])
           {
-             for (i = 0; i < h; i++)
+             for (i = 0; i < scale_h; i++)
                {
                   if (rows[i])
                     {
@@ -257,19 +272,34 @@ _evas_image_load_frame_image_data(Image_Entry *ie, GifFileType *gif, Image_Entry
           {
              for (j = intoffset[i]; j < h; j += intjump[i])
                {
-                  DGifGetLine(gif, rows[j], w);
+                  if ((j % scale_ratio) == 0)
+                    DGifGetLine(gif, rows[(j / scale_ratio)], w);
+                  else
+                    DGifGetLine(gif, tmp, w);
                }
           }
      }
    else
      {
-        for (i = 0; i < h; i++)
+        for (i = 0; i < scale_h; i++)
           {
              if (DGifGetLine(gif, rows[i], w) != GIF_OK)
                {
                   *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
                   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;
+                         }
+                    }
+               }
           }
      }
    alpha = gif_frame->frame_info.transparent;
@@ -287,7 +317,7 @@ _evas_image_load_frame_image_data(Image_Entry *ie, GifFileType *gif, Image_Entry
    if (!cmap)
      {
         DGifCloseFile(gif);
-        for (i = 0; i < h; i++)
+        for (i = 0; i < scale_h; i++)
           {
              free(rows[i]);
           }
@@ -304,8 +334,9 @@ _evas_image_load_frame_image_data(Image_Entry *ie, GifFileType *gif, Image_Entry
    bg_val =  ARGB_JOIN(0xff, r, g, b);
 
    per_inc = 100.0 / (((double)w) * h);
-   cur_h = h;
-   cur_w = w;
+   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;
 
@@ -354,27 +385,27 @@ _evas_image_load_frame_image_data(Image_Entry *ie, GifFileType *gif, Image_Entry
                 case 1: /* Do not dispose. need previous frame*/
                    memcpy(ptr, ptr_src, siz);
                    /* only decoding image descriptor's region */
-                   ptr = ptr + cache_w * y;
+                   ptr = ptr + cache_w * scale_y;
 
                    for (i = 0; i < cur_h; i++)
                      {
-                        ptr = ptr + x;
+                        ptr = ptr + scale_x;
                         for (j = 0; j < cur_w; j++)
                           {
-                             if (rows[i][j] == alpha)
+                             if (rows[i][j * scale_ratio] == alpha)
                                {
                                   ptr++ ;
                                }
                              else
                                {
-                                  r = cmap->Colors[rows[i][j]].Red;
-                                  g = cmap->Colors[rows[i][j]].Green;
-                                  b = cmap->Colors[rows[i][j]].Blue;
+                                  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 - (x + cur_w));
+                        ptr = ptr + (cache_w - (scale_x + cur_w));
                      }
                    break;
                 case 2: /* Restore to background color */
@@ -382,7 +413,7 @@ _evas_image_load_frame_image_data(Image_Entry *ie, GifFileType *gif, Image_Entry
                    /* composite frames */
                    for (i = 0; i < cache_h; i++)
                      {
-                        if ((i < y) || (i >= (y + cur_h)))
+                        if ((i < scale_y) || (i >= (scale_y + cur_h)))
                           {
                              for (j = 0; j < cache_w; j++)
                                {
@@ -393,21 +424,21 @@ _evas_image_load_frame_image_data(Image_Entry *ie, GifFileType *gif, Image_Entry
                         else
                           {
                              int i1, j1;
-                             i1 = i -y;
+                             i1 = i - scale_y;
 
                              for (j = 0; j < cache_w; j++)
                                {
-                                  j1 = j - x;
-                                  if ((j < x) || (j >= (x + cur_w)))
+                                  j1 = j - scale_x;
+                                  if ((j < scale_x) || (j >= (scale_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;
+                                       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);
                                     }
                                }
@@ -419,7 +450,7 @@ _evas_image_load_frame_image_data(Image_Entry *ie, GifFileType *gif, Image_Entry
                    memset(ptr, 0, siz);
                    for (i = 0; i < cache_h; i++)
                      {
-                        if ((i < y) || (i >= (y + cur_h)))
+                        if ((i < scale_y) || (i >= (scale_y + cur_h)))
                           {
                              for (j = 0; j < cache_w; j++)
                                {
@@ -430,21 +461,21 @@ _evas_image_load_frame_image_data(Image_Entry *ie, GifFileType *gif, Image_Entry
                         else
                           {
                              int i1, j1;
-                             i1 = i -y;
+                             i1 = i - scale_y;
 
                              for (j = 0; j < cache_w; j++)
                                {
-                                  j1 = j - x;
-                                  if ((j < x) || (j >= (x + cur_w)))
+                                  j1 = j - scale_x;
+                                  if ((j < scale_x) || (j >= (scale_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;
+                                       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);
                                     }
                                }
@@ -459,7 +490,8 @@ _evas_image_load_frame_image_data(Image_Entry *ie, GifFileType *gif, Image_Entry
         /* fill background color */
         for (i = 0; i < cache_h; i++)
           {
-             if ((i < y) || (i >= (y + cur_h)))
+             /* 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++)
                     {
@@ -470,21 +502,21 @@ _evas_image_load_frame_image_data(Image_Entry *ie, GifFileType *gif, Image_Entry
              else
                {
                   int i1, j1;
-                  i1 = i -y;
+                  i1 = i -scale_y;
 
                   for (j = 0; j < cache_w; j++)
                     {
-                       j1 = j - x;
-                       if ((j < x) || (j >= (x + cur_w)))
+                       j1 = j - scale_x;
+                       if ((j < scale_x) || (j >= (scale_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;
+                            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);
                          }
                     }
@@ -492,7 +524,7 @@ _evas_image_load_frame_image_data(Image_Entry *ie, GifFileType *gif, Image_Entry
           }
      }
 
-   for (i = 0; i < h; i++)
+   for (i = 0; i < scale_h; i++)
      {
         if (rows[i]) free(rows[i]);
      }
@@ -500,7 +532,7 @@ _evas_image_load_frame_image_data(Image_Entry *ie, GifFileType *gif, Image_Entry
    frame->loaded = EINA_TRUE;
    return EINA_TRUE;
 error:
-   for (i = 0; i < h; i++)
+   for (i = 0; i < scale_h; i++)
      {
         if (rows[i]) free(rows[i]);
      }
@@ -648,6 +680,12 @@ evas_image_load_file_head_gif(Image_Entry *ie, const char *file, const char *key
    /* check logical screen size */
    w = gif->SWidth;
    h = gif->SHeight;
+   /* support scale down feture in gif*/
+   if (ie->load_opts.scale_down_by > 1)
+     {
+        w /= ie->load_opts.scale_down_by;
+        h /= ie->load_opts.scale_down_by;
+     }
 
    if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
        IMG_TOO_BIG(w, h))
index c4a907a..c29f7ba 100644 (file)
@@ -107,8 +107,21 @@ evas_image_load_file_head_png(Image_Entry *ie, const char *file, const char *key
          *error = EVAS_LOAD_ERROR_GENERIC;
        goto close_file;
      }
-   ie->w = (int) w32;
-   ie->h = (int) h32;
+   if (ie->load_opts.scale_down_by > 1)
+     {
+        ie->w = (int) w32 / ie->load_opts.scale_down_by ;
+        ie->h = (int) h32 / ie->load_opts.scale_down_by ;
+        if((ie->w < 1) || (ie->h < 1))
+          {
+             *error = EVAS_LOAD_ERROR_GENERIC;
+             goto close_file;
+          }
+     }
+   else
+     {
+        ie->w = (int) w32;
+        ie->h = (int) h32;
+     }
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) hasa = 1;
    if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) hasa = 1;
    if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) hasa = 1;
@@ -137,7 +150,10 @@ evas_image_load_file_data_png(Image_Entry *ie, const char *file, const char *key
    unsigned char buf[PNG_BYTES_TO_CHECK];
    unsigned char **lines;
    char hasa;
-   int i;
+   int i, j;
+   int scale_ratio = 1, image_w = 0;
+   unsigned char *tmp_line;
+   unsigned char *src_ptr, *dst_ptr;
 
    hasa = 0;
    f = E_FOPEN(file, "rb");
@@ -184,6 +200,13 @@ evas_image_load_file_data_png(Image_Entry *ie, const char *file, const char *key
    png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *) (&w32),
                (png_uint_32 *) (&h32), &bit_depth, &color_type,
                &interlace_type, NULL, NULL);
+   image_w = w32;
+   if (ie->load_opts.scale_down_by > 1)
+     {
+        scale_ratio = ie->load_opts.scale_down_by;
+        w32 /= scale_ratio;
+        h32 /= scale_ratio;
+     }
    evas_cache_image_surface_alloc(ie, w32, h32);
    surface = (unsigned char *) evas_cache_image_pixels(ie);
    if (!surface)
@@ -233,10 +256,47 @@ evas_image_load_file_data_png(Image_Entry *ie, const char *file, const char *key
 #endif
    lines = (unsigned char **) alloca(h * sizeof(unsigned char *));
 
-   for (i = 0; i < h; i++)
-     lines[i] = surface + (i * w * sizeof(DATA32));
-   png_read_image(png_ptr, lines);
-   png_read_end(png_ptr, info_ptr);
+   /* we read image line by line if scale down was set */
+   if (scale_ratio == 1)
+     {
+        for (i = 0; i < h; i++)
+          lines[i] = surface + (i * w * sizeof(DATA32));
+     }
+   else
+     {
+        tmp_line = (unsigned char *) malloc(image_w * sizeof(DATA32));
+     }
+
+   if (scale_ratio == 1)
+     {
+        png_read_image(png_ptr, lines);
+        png_read_end(png_ptr, info_ptr);
+     }
+   else
+     {
+        src_ptr = surface;
+        for (i = 0; i < h; i++)
+          {
+             png_read_row(png_ptr, tmp_line, NULL);
+             dst_ptr = tmp_line;
+             for (j = 0; j < w; j++)
+               {
+                  src_ptr[0] = dst_ptr[0];
+                  src_ptr[1] = dst_ptr[1];
+                  src_ptr[2] = dst_ptr[2];
+                  src_ptr[3] = dst_ptr[3];
+                  src_ptr += 4;
+                  dst_ptr += scale_ratio * 4;
+               }
+             for (j = 0; j < (scale_ratio - 1); j++)
+               {
+                  png_read_row(png_ptr, tmp_line, NULL);
+               }
+          }
+        if (tmp_line)
+          free(tmp_line);
+     }
+
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    E_FCLOSE(f);
    evas_common_image_premul(ie);