bool ImageReaderGIF::copyFrameRegion()

in imagecore/formats/internal/gif.cpp [159:226]


bool ImageReaderGIF::copyFrameRegion(unsigned int frameIndex, ImageRGBA* destImage, bool writeBackground)
{
	if( m_Gif == NULL || (unsigned int)m_Gif->ImageCount <= frameIndex ) {
		return false;
	}

	SavedImage* savedImage = &m_Gif->SavedImages[frameIndex];
	if( savedImage->RasterBits == NULL ) {
		if( DGifDecodeFrame(m_Gif, frameIndex) != GIF_OK || savedImage->RasterBits == NULL ) {
			return false;
		}
	}
	GifImageDesc& imageDesc = savedImage->ImageDesc;
	int transparentIndex = getTransparentIndex(savedImage);
	uint8_t* regionImage = savedImage->RasterBits;
	if( regionImage == NULL ) {
		return false;
	}

	ColorMapObject* colorMap = imageDesc.ColorMap ? imageDesc.ColorMap : m_Gif->SColorMap;
	if( colorMap == NULL ) {
		return false;
	}

	int regionX;
	int regionY;
	int regionWidth;
	int regionHeight;
	getValidRegion(regionX, regionY, regionWidth, regionHeight, imageDesc, m_Width, m_Height);

	unsigned int destPitch = 0;
	uint8_t* destBuffer = destImage->lockRect(regionX, regionY, regionWidth, regionHeight, destPitch);
	bool hadAlpha = false;

	for( unsigned int y = 0; y < regionHeight; y++ ) {
		for( unsigned int x = 0; x < regionWidth; x++ ) {
			unsigned char paletteIndex = regionImage[y * imageDesc.Width + x];
			unsigned int outIndex = y * destPitch + x * 4U;
			bool isAlpha = transparentIndex == paletteIndex;
			if( !isAlpha ) {
				GifColorType* color = &colorMap->Colors[paletteIndex];
				destBuffer[outIndex + 0] = color->Red;
				destBuffer[outIndex + 1] = color->Green;
				destBuffer[outIndex + 2] = color->Blue;
				destBuffer[outIndex + 3] = 255;
			} else {
				if( writeBackground ) {
					destBuffer[outIndex + 0] = 255;
					destBuffer[outIndex + 1] = 255;
					destBuffer[outIndex + 2] = 255;
					destBuffer[outIndex + 3] = 0;
				}
				if( !hadAlpha ) {
					hadAlpha = true;
				}
			}
		}
	}

	// If we previously had a transparent frame, but just wrote a full frame over it, then it no longer has alpha.
	if( m_HasAlpha && !hadAlpha && regionWidth == m_Width && regionHeight == m_Height) {
		m_HasAlpha = false;
	}

	destImage->unlockRect();

	return true;
}