bool ImageReaderGIF::readImage()

in imagecore/formats/internal/gif.cpp [228:281]


bool ImageReaderGIF::readImage(Image* dest)
{
	if( !supportsOutputColorModel(dest->getColorModel()) ) {
		return false;
	}

	ImageRGBA* destImage = dest->asRGBA();

	if( m_Gif == NULL || (unsigned int)m_Gif->ImageCount <= m_CurrentFrame) {
		return false;
	}

	SavedImage* prevFrame = m_CurrentFrame > 0 ? &m_Gif->SavedImages[m_CurrentFrame - 1] : NULL;
	SavedImage* currentFrame = &m_Gif->SavedImages[m_CurrentFrame];
	int prevDisposalMode = prevFrame != NULL ? getDisposalMode(prevFrame) : DISPOSAL_UNSPECIFIED;
	int currDisposalMode = getDisposalMode(currentFrame);

	// if this is the 1st frame and it is not equal to the full image size, perform a clear
	if((m_CurrentFrame == 0) && ((currentFrame->ImageDesc.Left != 0) || (currentFrame->ImageDesc.Top != 0) || (currentFrame->ImageDesc.Width != m_Width) || (currentFrame->ImageDesc.Height != m_Height))) {
		destImage->clear(0, 0, 0, 0);
	}

	// If consecutive frames use DISPOSE_PREVIOUS, it means keep using the original frame.
	// Otherwise, copy the current frame to copy back later.
	if( currDisposalMode == DISPOSE_PREVIOUS && prevDisposalMode != DISPOSE_PREVIOUS && prevFrame != NULL ) {
		if( m_PrevFrameCopy == NULL ) {
			m_PrevFrameCopy = ImageRGBA::create(destImage->getWidth(), destImage->getHeight(), destImage->getColorModel() == kColorModel_RGBA);
			if( m_PrevFrameCopy == NULL ) {
				return false;
			}
		}
		destImage->copy(m_PrevFrameCopy);
	}

	// Previous frame asked for it to be cleared by copying back the original frame.
	if( prevDisposalMode == DISPOSE_PREVIOUS && prevFrame != NULL && m_PrevFrameCopy != NULL ) {
		m_PrevFrameCopy->copy(destImage);
		const GifImageDesc& desc = prevFrame->ImageDesc;
		int left, top, width, height;
		getValidRegion(left, top, width, height, desc, m_Width, m_Height);
		destImage->copyRect(m_PrevFrameCopy, left, top, left, top, width, height);
	}

	// Previous frame specified a background clear, so clear the region covered by that frame.
	if( prevDisposalMode == DISPOSE_BACKGROUND  && prevFrame != NULL ) {
		const GifImageDesc& desc = prevFrame->ImageDesc;
		int left, top, width, height;
		getValidRegion(left, top, width, height, desc, m_Width, m_Height);
		destImage->clearRect(left, top, width, height, 255, 255, 255, 0);
		m_HasAlpha = true;
	}

	return copyFrameRegion(m_CurrentFrame, destImage, m_CurrentFrame == 0);
}