GIF loader: Simplify error handling.

Also:
- Fix memory leak when image data allocation fails.
- Some aux data arrays may as well be const.
This commit is contained in:
Kim Woelders 2013-12-31 18:13:45 +01:00
parent 6b24728fb8
commit b7ad34abbc
1 changed files with 32 additions and 48 deletions

View File

@ -8,6 +8,9 @@ char
load(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity, load(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity,
char immediate_load) char immediate_load)
{ {
static const int intoffset[] = { 0, 4, 2, 1 };
static const int intjump[] = { 8, 8, 4, 2 };
int rc;
DATA32 *ptr; DATA32 *ptr;
GifFileType *gif; GifFileType *gif;
GifRowType *rows; GifRowType *rows;
@ -16,8 +19,6 @@ load(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity,
int i, j, done, bg, r, g, b, w = 0, h = 0; int i, j, done, bg, r, g, b, w = 0, h = 0;
float per = 0.0, per_inc; float per = 0.0, per_inc;
int last_per = 0, last_y = 0; int last_per = 0, last_y = 0;
int intoffset[] = { 0, 4, 2, 1 };
int intjump[] = { 8, 8, 4, 2 };
int transp; int transp;
int fd; int fd;
@ -45,6 +46,8 @@ load(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity,
return 0; return 0;
} }
rc = 0; /* Failure */
do do
{ {
if (DGifGetRecordType(gif, &rec) == GIF_ERROR) if (DGifGetRecordType(gif, &rec) == GIF_ERROR)
@ -62,37 +65,19 @@ load(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity,
w = gif->Image.Width; w = gif->Image.Width;
h = gif->Image.Height; h = gif->Image.Height;
if (!IMAGE_DIMENSIONS_OK(w, h)) if (!IMAGE_DIMENSIONS_OK(w, h))
{ goto quit2;
DGifCloseFile(gif);
return 0; rows = calloc(h, sizeof(GifRowType *));
}
rows = malloc(h * sizeof(GifRowType *));
if (!rows) if (!rows)
{ goto quit2;
DGifCloseFile(gif);
return 0;
}
for (i = 0; i < h; i++)
{
rows[i] = NULL;
}
for (i = 0; i < h; i++) for (i = 0; i < h; i++)
{ {
rows[i] = malloc(w * sizeof(GifPixelType)); rows[i] = malloc(w * sizeof(GifPixelType));
if (!rows[i]) if (!rows[i])
{ goto quit;
DGifCloseFile(gif);
for (i = 0; i < h; i++)
{
if (rows[i])
{
free(rows[i]);
}
}
free(rows);
return 0;
}
} }
if (gif->Image.Interlace) if (gif->Image.Interlace)
{ {
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
@ -131,6 +116,7 @@ load(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity,
} }
} }
while (rec != TERMINATE_RECORD_TYPE); while (rec != TERMINATE_RECORD_TYPE);
if (transp >= 0) if (transp >= 0)
{ {
SET_FLAG(im->flags, F_HAS_ALPHA); SET_FLAG(im->flags, F_HAS_ALPHA);
@ -139,6 +125,7 @@ load(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity,
{ {
UNSET_FLAG(im->flags, F_HAS_ALPHA); UNSET_FLAG(im->flags, F_HAS_ALPHA);
} }
/* set the format string member to the lower-case full extension */ /* set the format string member to the lower-case full extension */
/* name for the format - so example names would be: */ /* name for the format - so example names would be: */
/* "png", "jpeg", "tiff", "ppm", "pgm", "pbm", "gif", "xpm" ... */ /* "png", "jpeg", "tiff", "ppm", "pgm", "pbm", "gif", "xpm" ... */
@ -146,17 +133,15 @@ load(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity,
im->h = h; im->h = h;
if (!im->format) if (!im->format)
im->format = strdup("gif"); im->format = strdup("gif");
if (im->loader || immediate_load || progress) if (im->loader || immediate_load || progress)
{ {
bg = gif->SBackGroundColor; bg = gif->SBackGroundColor;
cmap = (gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap); cmap = (gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap);
im->data = (DATA32 *) malloc(sizeof(DATA32) * w * h); im->data = (DATA32 *) malloc(sizeof(DATA32) * w * h);
if (!im->data) if (!im->data)
{ goto quit;
DGifCloseFile(gif);
free(rows);
return 0;
}
ptr = im->data; ptr = im->data;
per_inc = 100.0 / (((float)w) * h); per_inc = 100.0 / (((float)w) * h);
for (i = 0; i < h; i++) for (i = 0; i < h; i++)
@ -184,30 +169,29 @@ load(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity,
last_per = (int)per; last_per = (int)per;
if (!(progress(im, (int)per, 0, last_y, w, i))) if (!(progress(im, (int)per, 0, last_y, w, i)))
{ {
DGifCloseFile(gif); rc = 2;
for (i = 0; i < h; i++) goto quit;
{
free(rows[i]);
}
free(rows);
return 2;
} }
last_y = i; last_y = i;
} }
} }
} }
if (progress)
progress(im, 100, 0, last_y, w, h);
} }
if (progress)
{ rc = 1; /* Success */
progress(im, 100, 0, last_y, w, h);
} quit:
DGifCloseFile(gif);
for (i = 0; i < h; i++) for (i = 0; i < h; i++)
{ free(rows[i]);
free(rows[i]);
}
free(rows); free(rows);
return 1;
quit2:
DGifCloseFile(gif);
return rc;
} }
void void