-
Bug
-
Resolution: Fixed
-
P4
-
1.3.0
-
beta2
-
generic
-
generic
Name: rlT66838 Date: 03/27/2000
java version "1.2.2"
(and 1.1.8, per # 102099)
(and kestrel-rc1, per # 102245)
Description-
Just see the animated gif of the specified kind:
o the bg color is transparent
o gif contains the several frames of the different size
o all of the frame should contains transparent pixels
(not a rectangular pictures) and they should be of the
different shape (to see superposing)
o the dispose method for the first frames is DISPOSAL_SAVE
o then dispose method changes to DISPOSAL_BGCOLOR,
and the next frame is of the smaller size (smaller bound rect)
When a bigger frame with dispose method DISPOSAL_BGCOLOR is replaced
by a smaller frame, you will see, that:
o the difference in bounds rects is filled with transparent (RIGHT!)
o but the transparent area of a smaller frame contains the pixels
of the previous frame.
Evaluation-
The reason of the bug is as follows:
The class sun.awt.image.GifImageDecoder uses the "saved_image" field (buffer)
to keep the previous image while drawing the next one with the method
"Do not dispose between frames" or "GifFrame.DISPOSAL_SAVE".
There is a part of the code in the GifImageDecoder.sendPixels method, that
copies data from the "saved_image" to the new one, if the "saved_image"
is not null. BUT THERE IS NO CHECKING if the redrawing method is
"GifFrame.DISPOSAL_SAVE":
> boolean save = (curframe.disposal_method == GifFrame.DISPOSAL_SAVE);
> if (trans_pixel >= 0 && !curframe.initialframe) {
> if (saved_image != null && saved_model == model) {
> for (int i = rasbeg; i < rasend; i++, off++) {
> byte pixel = rasline[i];
> if ((pixel & 0xff) == trans_pixel) {
>!!!!! rasline[i] = saved_image[off];
> } else if (save) {
> saved_image[off] = pixel;
> }
> }
So, while showing the test.gif animated image, the GifImageDecoder first creates
a saved_image, because the redrawing method for the first frames is
"Do not dispose between frames" one. Then while drawing the next (smaller)
frame with "Overwrite frame with background color from header" method, the
GifImageDecoder copies data from saved_image without checking the type
of redrawing method and you may see a part of "bigger" frame at
the transparent area of the "smaller" one...
Suggested fix-
at sun.awt.image.GifFrame (location: sun/awt/image/GifImageDecoder.java):
at method: public boolean dispose()
at place: case DISPOSAL_BGCOLOR:
before: setPixels(x, y, width, height, model, rasline, 0, 0);
code:
if( decoder.saved_image != null )
for( int i = 0; i < global_width * global_height; i ++ )
decoder.saved_image[i] = tpix;
diff -c for jdk1.1.8
***************
*** 697,702 ****
--- 697,705 ----
rasline[i] = tpix;
}
}
+ if (decoder.saved_image != null)
+ for (int i = 0; i < global_width*global_height; i ++)
+ decoder.saved_image[i] = tpix;
setPixels(x, y, width, height, model, rasline, 0, 0);
if (store != null) {
store.setPixels(x, y, width, height, rasline, 0, 0);
Also, I have the specified animated image to reproduce this bug
(Review ID: 102100)
======================================================================