Fix Fl_GIF_Image Color Table handling (STR 3491)

Loading GIF images could crash if there was no "Global Color Table"
but individual "Local Color Tables" with individual images.

Now local color tables are used correctly if available, but images that
lack both global and local color tables are being loaded with a default
(gray) color table and a warning is issued with Fl::warning().

The default color table uses black and white in the first two indices
as recommended by the standard.

Cherry-picked from: 35e03733f4
This commit is contained in:
Albrecht Schlosser 2019-01-03 14:48:48 +01:00
parent 2bc7816cab
commit 1a1492a174

View File

@ -3,7 +3,7 @@
//
// Fl_GIF_Image routines.
//
// Copyright 1997-2015 by Bill Spitzak and others.
// Copyright 1997-2019 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@ -19,6 +19,16 @@
//
//
//
// Reference: GIF89a Specification (links valid as of Jan 05, 2019):
//
// "GRAPHICS INTERCHANGE FORMAT(sm), Version 89a" (authoritative):
// https://www.w3.org/Graphics/GIF/spec-gif89a.txt
//
// HTML version (non-authoritative):
// https://web.archive.org/web/20160304075538/http://qalle.net/gif89a.php
//
//
// Include necessary header files...
//
@ -113,7 +123,12 @@ Fl_GIF_Image::Fl_GIF_Image(const char *infname) : Fl_Pixmap((char *const*)0) {
uchar ch = NEXTBYTE;
char HasColormap = ((ch & 0x80) != 0);
int BitsPerPixel = (ch & 7) + 1;
int ColorMapSize = 1 << BitsPerPixel;
int ColorMapSize;
if (HasColormap) {
ColorMapSize = 2 << (ch & 7);
} else {
ColorMapSize = 0;
}
// int OriginalResolution = ((ch>>4)&7)+1;
// int SortedTable = (ch&8)!=0;
ch = NEXTBYTE; // Background Color index
@ -129,10 +144,6 @@ Fl_GIF_Image::Fl_GIF_Image(const char *infname) : Fl_Pixmap((char *const*)0) {
Green[i] = NEXTBYTE;
Blue[i] = NEXTBYTE;
}
} else {
Fl::warning("%s does not have a colormap.", infname);
for (int i = 0; i < ColorMapSize; i++)
Red[i] = Green[i] = Blue[i] = (uchar)(255 * i / (ColorMapSize-1));
}
int CodeSize; /* Code size, init from GIF header, increases... */
@ -179,10 +190,10 @@ Fl_GIF_Image::Fl_GIF_Image(const char *infname) : Fl_Pixmap((char *const*)0) {
GETSHORT(Height);
ch = NEXTBYTE;
Interlace = ((ch & 0x40) != 0);
if (ch&0x80) {
// read local color map
int n = 2<<(ch&7);
for (i=0; i < n; i++) {
if (ch & 0x80) { // image has local color table
BitsPerPixel = (ch & 7) + 1;
ColorMapSize = 2 << (ch & 7);
for (i=0; i < ColorMapSize; i++) {
Red[i] = NEXTBYTE;
Green[i] = NEXTBYTE;
Blue[i] = NEXTBYTE;
@ -206,6 +217,27 @@ Fl_GIF_Image::Fl_GIF_Image(const char *infname) : Fl_Pixmap((char *const*)0) {
ColorMapSize = 1 << BitsPerPixel;
}
// Fix images w/o color table. The standard allows this and lets the
// decoder choose a default color table. The standard recommends the
// first two color table entries should be black and white.
if (ColorMapSize == 0) { // no global and no local color table
Fl::warning("%s does not have a color table, using default.\n", infname);
BitsPerPixel = CodeSize - 1;
ColorMapSize = 1 << BitsPerPixel;
Red[0] = Green[0] = Blue[0] = 0; // black
Red[1] = Green[1] = Blue[1] = 255; // white
for (int i = 2; i < ColorMapSize; i++) {
Red[i] = Green[i] = Blue[i] = (uchar)(255 * i / (ColorMapSize - 1));
}
#if (0)
// fill color table to maximum size
for (int i = ColorMapSize; i < 256; i++) {
Red[i] = Green[i] = Blue[i] = 0; // black
}
#endif
}
uchar *Image = new uchar[Width*Height];
int YC = 0, Pass = 0; /* Used to de-interlace the picture */