evas - fix gif animatd loader segv just inroduced.

This commit is contained in:
Carsten Haitzler 2013-07-05 23:11:18 +09:00
parent 7431e6a02a
commit fab94cb3ea
1 changed files with 152 additions and 31 deletions

View File

@ -187,7 +187,7 @@ _evas_image_load_frame_image_des_info(GifFileType *gif, Image_Entry_Frame *frame
static Eina_Bool static Eina_Bool
_evas_image_load_frame_image_data(Eina_File *f, _evas_image_load_frame_image_data(Eina_File *f,
const Evas_Image_Load_Opts *opts, const Evas_Image_Load_Opts *opts EINA_UNUSED,
Evas_Image_Property *prop, Evas_Image_Property *prop,
Evas_Image_Animated *animated, Evas_Image_Animated *animated,
GifFileType *gif, Image_Entry_Frame *frame, int *error) GifFileType *gif, Image_Entry_Frame *frame, int *error)
@ -198,8 +198,8 @@ _evas_image_load_frame_image_data(Eina_File *f,
DATA32 *ptr; DATA32 *ptr;
Gif_Frame *gif_frame = NULL; Gif_Frame *gif_frame = NULL;
double per; // double per;
double per_inc; // double per_inc;
size_t siz; size_t siz;
int intoffset[] = { 0, 4, 2, 1 }; int intoffset[] = { 0, 4, 2, 1 };
int intjump[] = { 8, 8, 4, 2 }; int intjump[] = { 8, 8, 4, 2 };
@ -226,7 +226,9 @@ _evas_image_load_frame_image_data(Eina_File *f,
cache_h = prop->h; cache_h = prop->h;
/* if user don't set scale down, default scale_ratio is 1 */ /* if user don't set scale down, default scale_ratio is 1 */
if (opts->scale_down_by > 1) scale_ratio = opts->scale_down_by; // 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_w = w / scale_ratio;
scale_h = h / scale_ratio; scale_h = h / scale_ratio;
scale_x = x / scale_ratio; scale_x = x / scale_ratio;
@ -246,7 +248,7 @@ _evas_image_load_frame_image_data(Eina_File *f,
/* alloc memory according to scaled size */ /* alloc memory according to scaled size */
for (i = 0; i < scale_h; i++) for (i = 0; i < scale_h; i++)
{ {
rows[i] = malloc(w * sizeof(GifPixelType)); rows[i] = malloc(scale_w * sizeof(GifPixelType));
if (!rows[i]) if (!rows[i])
{ {
for (i = 0; i < scale_h; i++) for (i = 0; i < scale_h; i++)
@ -262,15 +264,15 @@ _evas_image_load_frame_image_data(Eina_File *f,
} }
} }
if (scale_ratio > 1) // if (scale_ratio > 1)
{ // {
tmp = malloc(w * sizeof(GifPixelType)); // tmp = malloc(w * sizeof(GifPixelType));
if (!tmp) // if (!tmp)
{ // {
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; // *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
goto error; // goto error;
} // }
} // }
if (gif->Image.Interlace) if (gif->Image.Interlace)
{ {
@ -345,8 +347,8 @@ _evas_image_load_frame_image_data(Eina_File *f,
return EINA_FALSE; return EINA_FALSE;
} }
per_inc = 100.0 / (((double)w) * h); // per_inc = 100.0 / (((double)w) * h);
per = 0.0; // per = 0.0;
cur_h = scale_h; cur_h = scale_h;
cur_w = scale_w; cur_w = scale_w;
@ -387,15 +389,130 @@ _evas_image_load_frame_image_data(Eina_File *f,
else else
{ {
Gif_Frame *gif_frame2 = NULL; Gif_Frame *gif_frame2 = NULL;
int xx, yy, xin = 0, yin = 0;
ptr_src = new_frame->data; ptr_src = new_frame->data;
if (new_frame->info) if (new_frame->info)
{ {
gif_frame2 = (Gif_Frame *)(new_frame->info); gif_frame2 = (Gif_Frame *)(new_frame->info);
// the disposal mode of this frame
disposal = gif_frame2->frame_info.disposal; disposal = gif_frame2->frame_info.disposal;
// background rgba color value
gif_frame->bg_val = gif_frame2->bg_val; gif_frame->bg_val = gif_frame2->bg_val;
bg_val = gif_frame->bg_val; bg_val = gif_frame->bg_val;
} #if 1
switch(disposal) /* we only support disposal flag 0,1,2 */ // 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++;
}
}
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++;
}
}
break;
default:
break;
}
#else
switch (disposal) /* we only support disposal flag 0,1,2 */
{ {
case 1: /* Do not dispose. need previous frame*/ case 1: /* Do not dispose. need previous frame*/
memcpy(ptr, ptr_src, siz); memcpy(ptr, ptr_src, siz);
@ -409,7 +526,7 @@ _evas_image_load_frame_image_data(Eina_File *f,
{ {
if (rows[i][j * scale_ratio] == alpha) if (rows[i][j * scale_ratio] == alpha)
{ {
ptr++ ; ptr++;
} }
else else
{ {
@ -453,7 +570,7 @@ _evas_image_load_frame_image_data(Eina_File *f,
{ {
if (rows[i][j * scale_ratio] == alpha) if (rows[i][j * scale_ratio] == alpha)
{ {
ptr++ ; ptr++;
} }
else else
{ {
@ -467,14 +584,15 @@ _evas_image_load_frame_image_data(Eina_File *f,
} }
} }
break; break;
case 3: /* Restore previous */
case 0: /* No disposal specified */ case 0: /* No disposal specified */
default: default:
memset(ptr, 0, siz); memset(ptr, 0, siz);
for (i = 0; i < cache_h; i++) for (i = 0; i < gif_frame2->image_des.h; i++)
{ {
if ((i < scale_y) || (i >= (scale_y + cur_h))) if ((i < scale_y) || (i >= (scale_y + cur_h)))
{ {
for (j = 0; j < cache_w; j++) for (j = 0; j < gif_frame2->image_des.w; j++)
{ {
*ptr = bg_val; *ptr = bg_val;
ptr++; ptr++;
@ -485,7 +603,7 @@ _evas_image_load_frame_image_data(Eina_File *f,
int i1, j1; int i1, j1;
i1 = i - scale_y; i1 = i - scale_y;
for (j = 0; j < cache_w; j++) for (j = 0; j < gif_frame2->image_des.w; j++)
{ {
j1 = j - scale_x; j1 = j - scale_x;
if ((j < scale_x) || (j >= (scale_x + cur_w))) if ((j < scale_x) || (j >= (scale_x + cur_w)))
@ -497,7 +615,7 @@ _evas_image_load_frame_image_data(Eina_File *f,
{ {
if (rows[i][j * scale_ratio] == alpha) if (rows[i][j * scale_ratio] == alpha)
{ {
ptr++ ; ptr++;
} }
else else
{ {
@ -512,6 +630,8 @@ _evas_image_load_frame_image_data(Eina_File *f,
} }
break; break;
} }
#endif
}
} }
} }
else /* first frame decoding */ else /* first frame decoding */
@ -711,7 +831,7 @@ evas_image_load_file_head_gif(void *loader_data,
int *error) int *error)
{ {
Evas_Loader_Internal *loader = loader_data; Evas_Loader_Internal *loader = loader_data;
Evas_Image_Load_Opts *load_opts; // Evas_Image_Load_Opts *load_opts;
Evas_Image_Animated *animated; Evas_Image_Animated *animated;
Eina_File *f; Eina_File *f;
@ -726,7 +846,7 @@ evas_image_load_file_head_gif(void *loader_data,
int image_count = 0; int image_count = 0;
f = loader->f; f = loader->f;
load_opts = loader->opts; // load_opts = loader->opts;
animated = loader->animated; animated = loader->animated;
prop->w = 0; prop->w = 0;
@ -757,11 +877,12 @@ evas_image_load_file_head_gif(void *loader_data,
prop->w = gif->SWidth; prop->w = gif->SWidth;
prop->h = gif->SHeight; prop->h = gif->SHeight;
/* support scale down feture in gif*/ /* support scale down feture in gif*/
if (load_opts->scale_down_by > 1) // disable scale down for gif until gif is handled right
{ // if (load_opts->scale_down_by > 1)
prop->w /= load_opts->scale_down_by; // {
prop->h /= load_opts->scale_down_by; // prop->w /= load_opts->scale_down_by;
} // prop->h /= load_opts->scale_down_by;
// }
if ((prop->w < 1) || (prop->h < 1) || if ((prop->w < 1) || (prop->h < 1) ||
(prop->w > IMG_MAX_SIZE) || (prop->h > IMG_MAX_SIZE) || (prop->w > IMG_MAX_SIZE) || (prop->h > IMG_MAX_SIZE) ||