gifcodec.cpp
来自「symbian 下的helix player源代码」· C++ 代码 · 共 1,349 行 · 第 1/3 页
CPP
1,349 行
{
return retVal;
}
// Add the delay time to the delay time sum
m_ulDelayTimeSum += m_pImage[ulImageNum].GetDelayTime() * 10;
retVal = m_pImage[ulImageNum].SetCompressedBufferSize(m_pCompressedBufferSize[ulImageNum]);
if (retVal != HXR_OK)
{
return retVal;
}
pBuffer += m_pImageHeaderSize[ulImageNum];
ulImageNum++;
}
else if (pBuffer[1] == kApplicationExtension)
{
ParseApplicationExtension(pBuffer);
}
else
{
/* Skip the extension marker and type */
pBuffer += 2;
/* Now skip the extension itself */
SkipBlocks(pBuffer);
}
break;
case kTrailer:
default:
/* Something went wrong */
return HXR_INVALID_OPERATION;
break;
}
/* If we've gotten all intialized all images, then we're done */
if (ulImageNum >= m_ulNumImages)
{
break;
}
}
return HXR_OK;
}
void CGIFCodec::SkipBlocks(BYTE * &pBuffer, BYTE* pBufLimit)
{
// If pBufLimit is NULL, then we won't use it at all.
// If pBufLimit is not NULL, then we will make sure
// we don't go past the end of the buffer
UINT32 ulBlockSize;
do
{
/* Get the block size */
ulBlockSize = *pBuffer++;
/* Skip that amount of bytes */
pBuffer += ulBlockSize;
}
while (ulBlockSize > 0 &&
(!pBufLimit || (pBufLimit && pBuffer < pBufLimit)));
}
HX_RESULT CGIFCodec::InitDecompress(BYTE *pBuffer, UINT32 ulLen)
{
/* Check for input error conditions */
if (pBuffer == NULL || ulLen == 0)
{
return HXR_INVALID_PARAMETER;
}
/* Check the state */
if (m_ulState != kStateConstructed)
{
return HXR_UNEXPECTED;
}
/* Get the master header length */
UINT32 ulHeaderLength = UnPack32(pBuffer);
pBuffer += 4;
/* Get the number of images */
m_ulNumImages = UnPack32(pBuffer);
pBuffer += 4;
if (m_ulNumImages == 0)
{
return HXR_UNEXPECTED;
}
/* Allocate array of images */
if (m_pImage)
{
delete [] m_pImage;
m_pImage = NULL;
}
m_pImage = new CGIFImage [m_ulNumImages];
if (!m_pImage)
{
return HXR_OUTOFMEMORY;
}
/* Allocate array for image header sizes */
if (m_pImageHeaderSize)
{
delete [] m_pImageHeaderSize;
m_pImageHeaderSize = NULL;
}
m_pImageHeaderSize = new UINT32 [m_ulNumImages];
if (!m_pImageHeaderSize)
{
if (m_pImage)
{
delete [] m_pImage;
m_pImage = NULL;
}
return HXR_OUTOFMEMORY;
}
/* Allocate array for image header sizes */
if (m_pCompressedBufferSize)
{
delete [] m_pCompressedBufferSize;
m_pCompressedBufferSize = NULL;
}
m_pCompressedBufferSize = new UINT32 [m_ulNumImages];
if (!m_pCompressedBufferSize)
{
if (m_pImage)
{
delete [] m_pImage;
m_pImage = NULL;
}
if (m_pImageHeaderSize)
{
delete [] m_pImageHeaderSize;
m_pImageHeaderSize = NULL;
}
return HXR_OUTOFMEMORY;
}
/* Now set the compressed buffer size for each image */
HX_RESULT retVal;
UINT32 i;
for (i = 0; i < m_ulNumImages; i++)
{
/* Get the image header size */
m_pImageHeaderSize[i] = UnPack32(pBuffer);
pBuffer += 4;
/* Get a compressed buffer size */
m_pCompressedBufferSize[i] = UnPack32(pBuffer);
pBuffer += 4;
}
/* Now parse the container header */
retVal = ParseContainerHeader(pBuffer);
if (retVal != HXR_OK)
{
if (m_pImage)
{
delete [] m_pImage;
m_pImage = NULL;
}
if (m_pImageHeaderSize)
{
delete [] m_pImageHeaderSize;
m_pImageHeaderSize = NULL;
}
return retVal;
}
/* Set the current image */
m_ulCurrentImageIndex = 0;
/* Set the new state */
m_ulState = kStateDecoInitialized;
return HXR_OK;
}
HX_RESULT CGIFCodec::Decompress(BYTE *pBuffer, UINT32 ulLen, BOOL bNewImage)
{
/* Check for input error conditions */
if (pBuffer == NULL || ulLen == 0)
{
return HXR_INVALID_PARAMETER;
}
/* Check the state */
if (m_ulState != kStateDecoInitialized && m_ulState != kStateDecoInProgress)
{
return HXR_UNEXPECTED;
}
/* Check to see if the we lost a packet on this image */
if (m_pImage[m_ulCurrentImageIndex].GetValid() == FALSE)
{
/* This image was declared invalid due to a lost packet */
if (bNewImage == FALSE)
{
// We're still on the same image, so we can't do anything
return HXR_OK;
}
// We've moved on to a new image, so we can begin decompressing again
m_ulCurrentImageIndex++;
}
/* All we have to do is pass this data on to the current image */
HX_RESULT retVal = m_pImage[m_ulCurrentImageIndex].Decompress(pBuffer, ulLen);
if (retVal != HXR_OK)
{
return retVal;
}
/* Set the state */
m_ulState = kStateDecoInProgress;
/* Are we finished with this image? */
if (m_pImage[m_ulCurrentImageIndex].Finished() == TRUE)
{
/* Move on to the next image */
m_ulCurrentImageIndex++;
/* If we've done all images, then we're done */
if (m_ulCurrentImageIndex >= m_ulNumImages)
{
m_ulState = kStateDecoFinished;
}
}
return HXR_OK;
}
INT32 CGIFCodec::ComputeStartingImageIndex(INT32 lCurIndex, INT32 lDesiredIndex)
{
// Does the buffer currently hold any image now?
INT32 lStartIndex;
INT32 lBaseIndex;
if (lCurIndex == -1 || lCurIndex > lDesiredIndex)
{
// The buffer doesn't have anything in it now, so we must build
// from the last full screen image before or equal to ulImgIndex
// all the way back to 0.
lBaseIndex = 0;
}
else
{
// The buffer currently has a valid image in it, so we only need
// to go back to the first full screen image greater than lCurIndex.
lBaseIndex = lCurIndex + 1;
}
// Find the index of the first image we need to do
for (lStartIndex = lDesiredIndex; lStartIndex >= lBaseIndex; lStartIndex--)
{
if (m_pImage[lStartIndex].GetImageWidth() == m_cLSD.m_ulLogicalScreenWidth &&
m_pImage[lStartIndex].GetImageHeight() == m_cLSD.m_ulLogicalScreenHeight)
{
break;
}
}
if (lStartIndex < lBaseIndex)
{
lStartIndex = 0;
}
return lStartIndex;
}
HX_RESULT CGIFCodec::GetIndexImage(INT32 lCurIndex, UINT32 ulImgIndex, BYTE *pBuffer, UINT32 ulWidth, UINT32 ulHeight,
UINT32 ulPadWidth, BOOL bRowsInverted)
{
// Check for input error
if (lCurIndex < -1 || lCurIndex >= (INT32) m_ulNumImages || ulImgIndex >= m_ulNumImages ||
pBuffer == NULL || ulWidth == 0 || ulHeight == 0 || ulPadWidth == 0)
{
return HXR_INVALID_PARAMETER;
}
// Since frames of a GIF can be dependent upon prior frames, we need to
// determine which frame we need to go back to
INT32 lStartIndex = ComputeStartingImageIndex(lCurIndex, (INT32) ulImgIndex);
// Now do the images from lStartIndex to ulImgIndex
INT32 i;
for (i = lStartIndex; i <= (INT32) ulImgIndex; i++)
{
HX_RESULT retVal = m_pImage[i].GetIndexImage(pBuffer, ulWidth, ulHeight,
ulPadWidth, bRowsInverted);
if (retVal != HXR_OK)
{
return retVal;
}
}
return HXR_OK;
}
HX_RESULT CGIFCodec::GetRGBImage(INT32 lCurIndex, UINT32 ulImgIndex, BYTE *pBuffer, UINT32 ulWidth, UINT32 ulHeight, UINT32 ulPadWidth,
UINT32 ulBytesPerPixel, BOOL bRowsInverted, BOOL bRGBOrdering, BYTE ucBackRed, BYTE ucBackGreen, BYTE ucBackBlue,
BYTE ucBackAlpha)
{
// Check for input error
if (lCurIndex < -1 || lCurIndex >= (INT32) m_ulNumImages || ulImgIndex >= m_ulNumImages ||
pBuffer == NULL || ulWidth == 0 || ulHeight == 0 || ulPadWidth == 0 || ulBytesPerPixel == 0)
{
return HXR_INVALID_PARAMETER;
}
// Since frames of a GIF can be dependent upon prior frames, we need to
// determine which frame we need to go back to
INT32 lStartIndex = ComputeStartingImageIndex(lCurIndex, (INT32) ulImgIndex);
// Now do the images from lStartIndex to ulImgIndex
INT32 i;
for (i = lStartIndex; i <= (INT32) ulImgIndex; i++)
{
HX_RESULT retVal = m_pImage[i].GetRGBImage(pBuffer, ulWidth, ulHeight, ulPadWidth,
ulBytesPerPixel, bRowsInverted, bRGBOrdering,
ucBackRed, ucBackGreen, ucBackBlue, ucBackAlpha);
if (retVal != HXR_OK)
{
return retVal;
}
}
return HXR_OK;
}
HX_RESULT CGIFCodec::GetRGBImageEx(INT32 lCurIndex, UINT32 ulImgIndex, BYTE *pBuffer, UINT32 ulWidth, UINT32 ulHeight,
UINT32 ulPadWidth, UINT32 ulBytesPerPixel, BOOL bRowsInverted, BOOL bRGBOrdering,
UINT32 ulBgColor, BOOL bMediaOpacity, UINT32 ulMediaOpacity,
BOOL bChromaKey, UINT32 ulChromaKey, UINT32 ulChromaKeyTol, UINT32 ulChromaKeyOpacity)
{
HX_RESULT retVal = HXR_OK;
if (lCurIndex >= -1 && lCurIndex < (INT32) m_ulNumImages &&
ulImgIndex < m_ulNumImages && pBuffer && ulWidth && ulHeight &&
ulPadWidth && ulBytesPerPixel)
{
// Since frames of a GIF can be dependent upon prior frames, we need to
// determine which frame we need to go back to
INT32 lStartIndex = ComputeStartingImageIndex(lCurIndex, (INT32) ulImgIndex);
// Now do the images from lStartIndex to ulImgIndex
INT32 i = 0;
for (i = lStartIndex; i <= (INT32) ulImgIndex; i++)
{
retVal = m_pImage[i].GetRGBImageEx(pBuffer, ulWidth, ulHeight, ulPadWidth,
ulBytesPerPixel, bRowsInverted, bRGBOrdering,
ulBgColor, bMediaOpacity, ulMediaOpacity,
bChromaKey, ulChromaKey, ulChromaKeyTol, ulChromaKeyOpacity);
if (FAILED(retVal))
{
break;
}
}
}
else
{
retVal = HXR_INVALID_PARAMETER;
}
return retVal;
}
HX_RESULT CGIFCodec::GetRGB32(UINT32 ulImageNum, BYTE *pBuffer, UINT32 ulRowStride, BOOL bRowsInverted)
{
HX_RESULT retVal = HXR_OK;
if (pBuffer)
{
if (ulImageNum < m_ulNumImages && m_pImage)
{
retVal = m_pImage[ulImageNum].GetRGB32(pBuffer, ulRowStride, bRowsInverted);
}
else
{
retVal = HXR_UNEXPECTED;
}
}
else
{
retVal = HXR_INVALID_PARAMETER;
}
return retVal;
}
void CGIFCodec::PacketLost()
{
// Clear the valid flag for the current image
m_pImage[m_ulCurrentImageIndex].SetValid(FALSE);
// Set the finished flag for this image
m_pImage[m_ulCurrentImageIndex].SetFinished();
}
BOOL CGIFCodec::LocalColorMapsPresent()
{
UINT32 i;
for (i = 0; i < m_ulNumImages; i++)
{
if (m_pImage[i].LocalColorMapPresent())
{
return TRUE;
}
}
return FALSE;
}
void CGIFCodec::ParseApplicationExtension(BYTE * &pBuf)
{
pBuf += 2; // skip the extension introducer and the application extension label
// The next block should always be 11 bytes - 8 bytes for application identifier
// and 3 bytes for the application authentication code. If it's not then just
// skip these blocks
if (pBuf[0] == 11)
{
// Now we check to see if this is a NETSCAPE2.0 application extension.
// If it is, then it contains the loop count for the animation.
if (!strncmp((const char *) pBuf + 1, "NETSCAPE2.0", 11))
{
// Yep, we've got a NETSCAPE2.0 application extension,
// so attempt to extract the loop count
if (pBuf[12] == 0x03 && pBuf[13] == 0x01 && pBuf[16] == 0x00)
{
UINT32 ulCount = (pBuf[15] << 8) | pBuf[14];
if (ulCount == 0)
{
m_ulLoopCount = 0;
}
else
{
m_ulLoopCount = ulCount + 1;
}
pBuf += 17;
}
else
{
SkipBlocks(pBuf);
}
}
else
{
SkipBlocks(pBuf);
}
}
else
{
SkipBlocks(pBuf);
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?