#include "imageri.h"
#include <gif_lib.h>
-#ifdef _MSCVER
+#ifdef _MSC_VER
#include <io.h>
#else
#include <unistd.h>
GifRowType GifRow;
int got_gce = 0;
- int trans_index; /* transparent index if we see a GCE */
- int gif_delay; /* delay from a GCE */
- int user_input; /* user input flag from a GCE */
- int disposal; /* disposal method from a GCE */
+ int trans_index = 0; /* transparent index if we see a GCE */
+ int gif_delay = 0; /* delay from a GCE */
+ int user_input = 0; /* user input flag from a GCE */
+ int disposal = 0; /* disposal method from a GCE */
int got_ns_loop = 0;
- int ns_loop;
+ int ns_loop = 0;
char *comment = NULL; /* a comment */
i_img **results = NULL;
int result_alloc = 0;
int channels;
+ int image_colors = 0;
+ i_color black; /* used to expand the palette if needed */
+
+ for (i = 0; i < MAXCHANNELS; ++i)
+ black.channel[i] = 0;
*count = 0;
free_images(results, *count);
DGifCloseFile(GifFile);
myfree(GifRow);
+ if (comment)
+ myfree(comment);
return NULL;
}
free_images(results, *count);
DGifCloseFile(GifFile);
myfree(GifRow);
+ if (comment)
+ myfree(comment);
return NULL;
}
free_images(results, *count);
DGifCloseFile(GifFile);
myfree(GifRow);
+ if (comment)
+ myfree(comment);
return NULL;
}
mm_log((1, "i_readgif: image size exceeds limits\n"));
DGifCloseFile(GifFile);
myfree(GifRow);
+ if (comment)
+ myfree(comment);
return NULL;
}
img = i_img_pal_new(Width, Height, channels, 256);
if (!img) {
free_images(results, *count);
DGifCloseFile(GifFile);
+ if (comment)
+ myfree(comment);
+ myfree(GifRow);
return NULL;
}
/* populate the palette of the new image */
i_addcolors(img, &col, 1);
}
+ image_colors = ColorMapSize;
++*count;
if (*count > result_alloc) {
if (result_alloc == 0) {
i_tags_addn(&img->tags, "gif_interlace", 0, GifFile->Image.Interlace);
i_tags_addn(&img->tags, "gif_screen_width", 0, GifFile->SWidth);
i_tags_addn(&img->tags, "gif_screen_height", 0, GifFile->SHeight);
+ i_tags_addn(&img->tags, "gif_colormap_size", 0, ColorMapSize);
if (GifFile->SColorMap && !GifFile->Image.ColorMap) {
i_tags_addn(&img->tags, "gif_background", 0,
GifFile->SBackGroundColor);
free_images(results, *count);
DGifCloseFile(GifFile);
myfree(GifRow);
+ if (comment)
+ myfree(comment);
return(0);
}
free_images(results, *count);
DGifCloseFile(GifFile);
myfree(GifRow);
+ if (comment)
+ myfree(comment);
return NULL;
}
-
+
+ /* range check the scanline if needed */
+ if (image_colors != 256) {
+ int x;
+ for (x = 0; x < Width; ++x) {
+ while (GifRow[x] >= image_colors) {
+ /* expand the palette since a palette index is too big */
+ i_addcolors(img, &black, 1);
+ ++image_colors;
+ }
+ }
+ }
+
i_ppal(img, 0, Width, j, GifRow);
}
}
free_images(results, *count);
DGifCloseFile(GifFile);
myfree(GifRow);
+ if (comment)
+ myfree(comment);
return NULL;
}
+ /* range check the scanline if needed */
+ if (image_colors != 256) {
+ int x;
+ for (x = 0; x < Width; ++x) {
+ while (GifRow[x] >= image_colors) {
+ /* expand the palette since a palette index is too big */
+ i_addcolors(img, &black, 1);
+ ++image_colors;
+ }
+ }
+ }
+
i_ppal(img, 0, Width, i, GifRow);
}
}
if (page != -1) {
myfree(GifRow);
DGifCloseFile(GifFile);
+ if (comment)
+ myfree(comment);
return results;
}
}
free_images(results, *count);
myfree(GifRow);
DGifCloseFile(GifFile);
+ if (comment)
+ myfree(comment);
return NULL;
}
}
gif_push_error();
i_push_error(0, "Reading extension record");
free_images(results, *count);
+ myfree(GifRow);
DGifCloseFile(GifFile);
+ if (comment)
+ myfree(comment);
return NULL;
}
+ /* possibly this should be an error, but "be liberal in what you accept" */
+ if (!Extension)
+ break;
if (ExtCode == 0xF9) {
got_gce = 1;
if (Extension[1] & 1)
else
trans_index = -1;
gif_delay = Extension[2] + 256 * Extension[3];
- user_input = (Extension[0] & 2) != 0;
- disposal = (Extension[0] >> 2) & 3;
+ user_input = (Extension[1] & 2) != 0;
+ disposal = (Extension[1] >> 2) & 7;
}
if (ExtCode == 0xFF && *Extension == 11) {
if (memcmp(Extension+1, "NETSCAPE2.0", 11) == 0) {
gif_push_error();
i_push_error(0, "reading loop extension");
free_images(results, *count);
- DGifCloseFile(GifFile);
+ myfree(GifRow);
+ DGifCloseFile(GifFile);
+ if (comment)
+ myfree(comment);
return NULL;
}
if (Extension && *Extension == 3) {
gif_push_error();
i_push_error(0, "reading next block of extension");
free_images(results, *count);
+ myfree(GifRow);
DGifCloseFile(GifFile);
+ if (comment)
+ myfree(comment);
return NULL;
}
}
Internal. Add the Netscape2.0 loop extension block, if requested.
-The code for this function is currently "#if 0"ed out since the giflib
-extension writing code currently doesn't seem to support writing
-application extension blocks.
+Giflib/libungif prior to 4.1.1 didn't support writing application
+extension blocks, so we don't attempt to write them for older versions.
+
+Giflib/libungif prior to 4.1.3 used the wrong write mechanism when
+writing extension blocks so that they could only be written to files.
=cut
*/
If giflib's callback interface wasn't broken by default, I'd
force file writes to use callbacks, but it is broken by default.
*/
-#if 0
/* yes this was another attempt at supporting the loop extension */
+#if IM_GIFMAJOR == 4 && IM_GIFMINOR >= 1
int loop_count;
if (i_tags_get_int(&img->tags, "gif_loop", 0, &loop_count)) {
unsigned char nsle[12] = "NETSCAPE2.0";
unsigned char subblock[3];
- if (EGifPutExtension(gf, 0xFF, 11, nsle) == GIF_ERROR) {
+ if (EGifPutExtensionFirst(gf, APPLICATION_EXT_FUNC_CODE, 11, nsle) == GIF_ERROR) {
gif_push_error();
i_push_error(0, "writing loop extension");
return 0;
subblock[0] = 1;
subblock[1] = loop_count % 256;
subblock[2] = loop_count / 256;
- if (EGifPutExtension(gf, 0, 3, subblock) == GIF_ERROR) {
- gif_push_error();
- i_push_error(0, "writing loop extention sub-block");
- return 0;
- }
- if (EGifPutExtension(gf, 0, 0, subblock) == GIF_ERROR) {
+ if (EGifPutExtensionLast(gf, APPLICATION_EXT_FUNC_CODE, 3, subblock) == GIF_ERROR) {
gif_push_error();
- i_push_error(0, "writing loop extension terminator");
+ i_push_error(0, "writing loop extension sub-block");
return 0;
}
}
#endif
+
return 1;
}
Failing to set the correct GIF version doesn't seem to cause a problem
with readers.
+Modern versions (4.1.4 anyway) of giflib/libungif handle
+EGifSetGifVersion correctly.
+
+If t/t105gif.t crashes here then run Makefile.PL with
+--nogifsetversion, eg.:
+
+ perl Makefile.PL --nogifsetversion
+
+or install a less buggy giflib.
+
=cut
*/
static void gif_set_version(i_quantize *quant, i_img **imgs, int count) {
- /* the following crashed giflib
- the EGifSetGifVersion() is seriously borked in giflib
- it's less borked in the ungiflib beta, but we don't have a mechanism
- to distinguish them
- Needs to be updated to support tags.
- if (opts->delay_count
- || opts->user_input_count
- || opts->disposal_count
- || opts->loop_count
- || quant->transp != tr_none)
+#if (IM_GIFMAJOR >= 4 || IM_GIFMAJOR == 4 && IM_GIFMINOR >= 1) \
+ && !defined(IM_NO_SET_GIF_VERSION)
+ int need_89a = 0;
+ int temp;
+ int i;
+
+ if (quant->transp != tr_none)
+ need_89a = 1;
+ else {
+ for (i = 0; i < count; ++i) {
+ if (i_tags_get_int(&imgs[i]->tags, "gif_delay", 0, &temp)) {
+ need_89a = 1;
+ break;
+ }
+ if (i_tags_get_int(&imgs[i]->tags, "gif_user_input", 0, &temp) && temp) {
+ need_89a = 1;
+ break;
+ }
+ if (i_tags_get_int(&imgs[i]->tags, "gif_disposal", 0, &temp)) {
+ need_89a = 1;
+ break;
+ }
+ if (i_tags_get_int(&imgs[i]->tags, "gif_loop", 0, &temp)) {
+ need_89a = 1;
+ break;
+ }
+ }
+ }
+ if (need_89a)
EGifSetGifVersion("89a");
- else
+ else
EGifSetGifVersion("87a");
- */
+#endif
}
static int
static undef_int
i_writegif_low(i_quantize *quant, GifFileType *gf, i_img **imgs, int count) {
- unsigned char *result;
+ unsigned char *result = NULL;
int color_bits;
ColorMapObject *map;
int scrw = 0, scrh = 0;
int imgn, orig_count, orig_size;
int posx, posy;
- int trans_index;
+ int trans_index = -1;
i_mempool mp;
int *localmaps;
int anylocal;
int glob_img_count;
i_color *orig_colors = quant->mc_colors;
i_color *glob_colors = NULL;
- int glob_color_count;
+ int glob_color_count = 0;
int glob_want_trans;
- int glob_paletted; /* the global map was made from the image palettes */
- int colors_paletted;
- int want_trans;
+ int glob_paletted = 0; /* the global map was made from the image palettes */
+ int colors_paletted = 0;
+ int want_trans = 0;
int interlace;
int gif_background;
if (!i_tags_get_int(&imgs[0]->tags, "gif_screen_width", 0, &scrw))
scrw = 0;
- if (!i_tags_get_int(&imgs[0]->tags, "gif_screen_height", 0, &scrw))
+ if (!i_tags_get_int(&imgs[0]->tags, "gif_screen_height", 0, &scrh))
scrw = 0;
anylocal = 0;