Permalink
Browse files

Fix handling of alpha values in animated gifs

The gif loader was incorrectly setting pixels as transparent in certain animated gifs. It was ignoring the disposal method value in the extension block and always overwriting the alpha value in each frame. It is common for some animated gifs to set the disposal method so that the previous alpha value is retained. This patch modifies the loader to respect the disposal method flag.
  • Loading branch information...
flashk committed Nov 1, 2018
1 parent 7729d38 commit f4c4905d9eda05332f970eeadc7a2a5b2ddb31a2
Showing with 23 additions and 5 deletions.
  1. +23 −5 src/osgPlugins/gif/ReaderWriterGIF.cpp
@@ -295,7 +295,8 @@ decode_row(GifFileType * giffile,
unsigned char * buffer,
unsigned char * rowdata,
int x, int y, int len,
int transparent)
int transparent,
int overwrite)
{
GifColorType * cmentry;
ColorMapObject * colormap;
@@ -321,6 +322,8 @@ int transparent)
// keep pixels of last image if transparent mode is on
// this is necessary for GIF animating
ptr += 3;
if(overwrite) *ptr = 0x00;
++ptr;
}
else
{
@@ -337,8 +340,8 @@ int transparent)
*ptr++ = col;
*ptr++ = col;
}
*ptr++ = 0xff;
}
*ptr++ = (col == transparent ? 0x00 : 0xff);
}
}
@@ -360,7 +363,7 @@ GifImageStream** obj)
unsigned char * rowdata;
unsigned char * buffer, * ptr;
unsigned char bg;
int transparent, delaytime;
int transparent, delaytime, overwrite;
GifRecordType recordtype;
GifByteType * extension;
GifFileType * giffile;
@@ -383,6 +386,7 @@ GifImageStream** obj)
transparent = -1; /* no transparent color by default */
delaytime = 8; /* delay time of a frame */
overwrite = 1; /* overwrite previous alpha values in animated gifs */
n = giffile->SHeight * giffile->SWidth;
buffer = new unsigned char [n * 4];
@@ -485,7 +489,7 @@ GifImageStream** obj)
delete [] rowdata;
return NULL;
}
else decode_row(giffile, buffer, rowdata, col, j, width, transparent);
else decode_row(giffile, buffer, rowdata, col, j, width, transparent, gif_num > 1 ? overwrite : true);
}
}
}
@@ -500,7 +504,7 @@ GifImageStream** obj)
delete [] rowdata;
return NULL;
}
else decode_row(giffile, buffer, rowdata, col, row, width, transparent);
else decode_row(giffile, buffer, rowdata, col, row, width, transparent, gif_num > 1 ? overwrite : true);
}
}
@@ -529,6 +533,20 @@ GifImageStream** obj)
if (extension[0] >= 4 && extension[1] & 0x1) transparent = extension[4];
else transparent = -1;
// Set alpha overwrite flag based on disposal method
unsigned char disposal_method = (extension[1]>>2) & 0x7;
switch (disposal_method)
{
case 0:
case 2:
overwrite = 1;
break;
case 1:
case 3:
overwrite = 0;
break;
}
delaytime = (extension[3]<<8)+extension[2]; // minimum unit 1/100s, so 8 here means 8/100s
}
while (extension != NULL)

0 comments on commit f4c4905

Please sign in to comment.