Bug 1249576 - If the first frame of an APNG doesn't cover the whole image mark the image as transparent. r=edwin

In (non-animated) PNGs the image data is contained in IDAT chunks. In APNGs there are IDAT chunks, which contain the default image, and fDAT chunks, which contain frames of the animation. The default image is sometimes part of the animation (as the first frame), and sometimes not (displayed only by non-APNG aware viewers).

The default image must have the same size as in the PNG header chunk. But the fDAT images can be any (smaller) size. So the first frame of a PNG is allowed to be smaller than the whole image size so long as we are in an APNG and the first frame is from an fDAT chunk, not an IDAT chunk.

We post transparency if we encounter this case because we don't draw into those pixels on at least the first frame.
This commit is contained in:
Timothy Nikkel 2016-02-23 20:22:00 +01:00
Родитель 753cad635e
Коммит c29791aa23
1 изменённых файлов: 12 добавлений и 3 удалений

Просмотреть файл

@ -133,9 +133,12 @@ nsPNGDecoder::CheckForTransparency(SurfaceFormat aFormat,
PostHasTransparency();
}
// PNGs shouldn't have first-frame padding.
MOZ_ASSERT_IF(mNumFrames == 0,
IntRect(IntPoint(), GetSize()).IsEqualEdges(aFrameRect));
// If the first frame of animated image doesn't draw into the whole image,
// then record that it is transparent.
if (mNumFrames == 0 && !IntRect(IntPoint(), GetSize()).IsEqualEdges(aFrameRect)) {
MOZ_ASSERT(HasAnimation());
PostHasTransparency();
}
}
// CreateFrame() is used for both simple and animated images
@ -597,6 +600,12 @@ nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr)
#endif
if (decoder->IsMetadataDecode()) {
// If we are animated then the first frame rect is either: 1) the whole image
// if the IDAT chunk is part of the animation 2) the frame rect of the first
// fDAT chunk otherwise. If we are not animated then we want to make sure to
// call PostHasTransparency in the metadata decode if we need to. So it's okay
// to pass IntRect(0, 0, width, height) here for animated images; they will
// call with the proper first frame rect in the full decode.
decoder->CheckForTransparency(decoder->format,
IntRect(0, 0, width, height));