gifcodec.cpp
来自「symbian 下的helix player源代码」· C++ 代码 · 共 1,349 行 · 第 1/3 页
CPP
1,349 行
}
while (ulBlockSize > 0);
break;
case kCommentExtension:
case kPlainTextExtension:
pBuf += 2;
SkipBlocks(pBuf, pBufLimit);
break;
case kApplicationExtension:
ParseApplicationExtension(pBuf);
break;
default:
// An extension we don't know - just try to
// pass it through
pBuf += 2;
SkipBlocks(pBuf, pBufLimit);
break;
}
}
else if (pBuf[0] == kTrailer)
{
/* We found a GIF trailer - we should be at the end of the file */
cMarkList.PushBack((void *) pBuf);
break;
}
else
{
// Sometimes extra 0 blocks get stuck in GIFs. Check for them
// here - if the current byte is 0, then it's OK. If it's not,
// then we've gotten lost somewhere.
if (pBuf[0] == 0x00)
{
pBuf++;
}
else
{
// Something is wrong with the GIF file.
//
// XXXMEH - instead of returning an error, we will
// be lax and just break here. This will have the effect
// of potentially sending garbage GIFs down to the
// client. The upside is that there are a lot of
// non-standard GIFs out there that will display in
// browsers and this will allow them to be displayed.
break;
}
}
}
/* The last mark is, of course, the end of the file. */
cMarkList.PushBack((void *) pBufLimit);
/*
* Now we convert our list to a more usable array of ParseSegment's. First
* we compute the number of segments, which is one less than the number
* of marks.
*/
m_ulNumSegmentsAllocated = cMarkList.Size() - 1;
if (m_ulNumSegmentsAllocated == 0 || m_ulNumSegmentsAllocated > cMarkList.Size())
{
return HXR_UNEXPECTED;
}
/* Allocate memory for the segment array */
if (m_pSegment)
{
delete [] m_pSegment;
m_pSegment = NULL;
}
m_pSegment = new ParseSegment [m_ulNumSegmentsAllocated];
if (!m_pSegment)
{
return HXR_OUTOFMEMORY;
}
/*
* Now run through the list of marks, computing segments. Note that
* if the mark in the marklist is an extension not necessary for
* deompression, we do not make it into a segment.
*/
m_ulNumSegments = 0;
GListIterator itr = cMarkList.Begin();
BYTE *pLastMark = (BYTE *) *itr;
itr++;
do
{
BYTE *pCurMark = (BYTE *) *itr;
/*
* Filter out all unwanted extensions. We don't send application,
* comment, or plain text extensions. We also don't send the GIF
* Trailer
*/
if (!((pLastMark[0] == kExtension && (pLastMark[1] == kApplicationExtension ||
pLastMark[1] == kCommentExtension ||
pLastMark[1] == kPlainTextExtension)) ||
pLastMark[0] == kTrailer))
{
m_pSegment[m_ulNumSegments].pMark = pLastMark;
m_pSegment[m_ulNumSegments].ulSize = pCurMark - pLastMark;
m_ulNumSegments++;
}
pLastMark = pCurMark;
itr++;
}
while (itr != cMarkList.End());
/* Now we're done with the list */
cMarkList.EraseAll();
/* Set the state */
m_ulParseState = kStateParseInitialized;
return HXR_OK;
}
UINT32 CGIFCodec::GetDelayTime(UINT32 i)
{
if (i >= m_ulNumImages || m_bIsGIF89a == FALSE)
{
return 0;
}
UINT32 ulDelay;
ParseSegment *pSeg = &m_pSegment[1 + (i << 1)];
if (pSeg->pMark[0] == kExtension && pSeg->pMark[1] == kGraphicControlExtension)
{
CGIFImage::GraphicControlExtension cGCE;
CGIFImage::ParseGraphicControlExtension(pSeg->pMark + 3, cGCE);
ulDelay = cGCE.m_ulDelayTime;
if (ulDelay == 0)
{
ulDelay = 1;
}
}
else
{
ulDelay = 0;
}
return ulDelay;
}
UINT32 CGIFCodec::GetImageDataSize(UINT32 i)
{
if (i >= m_ulNumImages)
{
return 0;
}
return m_pSegment[2 + (i << 1)].ulSize;
}
HX_RESULT CGIFCodec::GetPacketBufferLength(UINT32 &rulLen)
{
/* Check state */
if (m_ulParseState != kStateParseInitialized &&
m_ulParseState != kStateParseInProgress)
{
return HXR_UNEXPECTED;
}
/* Is this our first time here? */
if (m_ulParseState == kStateParseInitialized)
{
/* This is the first time here - we need to find the header length */
UINT32 ulLen = 8 + /* Container header size, num images */
8 * m_ulNumImages + /* Image header size and compressed data size */
m_pSegment[0].ulSize; /* Container header */
/*
* Add the individual image header sizes - these are the segments which
* begin with either an Image Descriptor or a GCE.
*/
UINT32 i;
for (i = 0; i < m_ulNumSegments; i++)
{
BYTE *pMark = m_pSegment[i].pMark;
if ( pMark[0] == kImageDescriptor ||
(pMark[0] == kExtension && pMark[1] == kGraphicControlExtension))
{
ulLen += m_pSegment[i].ulSize;
}
}
/* Set the initial segment for data packet parsing */
m_ulCurSegIndex = 2;
m_ulCurSegOffset = 0;
/* We have our length */
rulLen = ulLen;
}
else
{
/* This is NOT the first time here - we need to find the data packet length */
BYTE *pBufStart = m_pSegment[m_ulCurSegIndex].pMark;
BYTE *pBuf = pBufStart + m_ulCurSegOffset;
UINT32 ulSize = 0;
/* If we are at the beginning of a LZW segment, we need to skip the min code size */
if (m_ulCurSegOffset == 0)
{
pBuf++;
ulSize++;
}
/* Advance through the blocks, until we reach the ideal packet size */
UINT32 ulBlockSize;
do
{
ulBlockSize = *pBuf;
ulSize += ulBlockSize + 1;
pBuf += ulBlockSize + 1;
}
while (ulBlockSize > 0 && ulSize < kIdealPacketSize);
/*
* Make a check to see if what's left over is not less than the
* minimum packet size. If it IS less than the minimum packet size,
* then go ahead and get the rest of it.
*/
UINT32 ulBytesLeftInSegment = pBufStart + m_pSegment[m_ulCurSegIndex].ulSize - pBuf;
if (ulBytesLeftInSegment > 0 && ulBytesLeftInSegment < kMinimumPacketSize)
{
ulSize += ulBytesLeftInSegment;
}
/* Now we have our length */
rulLen = ulSize;
}
return HXR_OK;
}
UINT32 CGIFCodec::ComputeLZWDataSize(BYTE *pLZW)
{
/* Skip the minimum code size */
pLZW++;
/* Run through blocks, adding up sizes */
UINT32 ulSum = 0;
UINT32 ulBlockSize;
do
{
ulBlockSize = *pLZW++;
ulSum += ulBlockSize;
pLZW += ulBlockSize;
}
while (ulBlockSize > 0);
return ulSum;
}
HX_RESULT CGIFCodec::GetPacketBuffer(BYTE *pBuffer, UINT32 ulLen, BOOL &rbFirstInImage)
{
/* Check for input error conditions */
if (pBuffer == NULL || ulLen == 0)
{
return HXR_INVALID_PARAMETER;
}
/* Check state */
if (m_ulParseState != kStateParseInitialized &&
m_ulParseState != kStateParseInProgress)
{
return HXR_UNEXPECTED;
}
/* Is this our first time here? */
if (m_ulParseState == kStateParseInitialized)
{
/* Conainer header size */
Pack32(m_pSegment[0].ulSize, pBuffer);
pBuffer += 4;
/* Number of Images */
Pack32(m_ulNumImages, pBuffer);
pBuffer += 4;
/* Individual image parameters */
UINT32 i;
for (i = 0; i < m_ulNumImages; i++)
{
/* Individual image header size */
Pack32(m_pSegment[1 + (i << 1)].ulSize, pBuffer);
pBuffer += 4;
/* Individual image compressed data size */
Pack32(ComputeLZWDataSize(m_pSegment[2 + (i << 1)].pMark), pBuffer);
pBuffer += 4;
}
/* Copy container header */
memcpy(pBuffer, m_pSegment[0].pMark, m_pSegment[0].ulSize); /* Flawfinder: ignore */
pBuffer += m_pSegment[0].ulSize;
/* Copy each individual image header */
for (i = 0; i < m_ulNumImages; i++)
{
ParseSegment *pSegment = &m_pSegment[1 + (i << 1)];
memcpy(pBuffer, pSegment->pMark, pSegment->ulSize); /* Flawfinder: ignore */
pBuffer += pSegment->ulSize;
}
/* Clear the flag */
rbFirstInImage = FALSE;
/* Set the new state */
m_ulParseState = kStateParseInProgress;
}
else
{
/* Copy the data packet */
memcpy(pBuffer, /* Flawfinder: ignore */
m_pSegment[m_ulCurSegIndex].pMark + m_ulCurSegOffset,
ulLen);
/* Was this the first packet for one of the images? */
if (m_ulCurSegOffset == 0)
{
rbFirstInImage = TRUE;
}
else
{
rbFirstInImage = FALSE;
}
/* Check to see if we're done with this segment */
if (m_ulCurSegOffset + ulLen >= m_pSegment[m_ulCurSegIndex].ulSize)
{
m_ulCurSegIndex += 2;
m_ulCurSegOffset = 0;
}
else
{
m_ulCurSegOffset += ulLen;
}
/* Check to see if we finished */
if (m_ulCurSegIndex >= m_ulNumSegments)
{
m_ulParseState = kStateParseFinished;
}
}
return HXR_OK;
}
void CGIFCodec::ParseLogicalScreenDescriptor(BYTE *pBuffer, LogicalScreenDescriptor &cLSD)
{
/* Read Logical Screen Descriptor */
cLSD.m_ulLogicalScreenWidth = (pBuffer[1] << 8) | pBuffer[0];
cLSD.m_ulLogicalScreenHeight = (pBuffer[3] << 8) | pBuffer[2];
cLSD.m_bGlobalColorTablePresent = (pBuffer[4] & 0x80 ? TRUE : FALSE);
cLSD.m_ulOriginalColorBits = ((pBuffer[4] & 0x70) >> 4) + 1;
cLSD.m_bColorsSorted = (pBuffer[4] & 0x08 ? TRUE : FALSE);
cLSD.m_ulColorTableBits = (pBuffer[4] & 0x07) + 1;
cLSD.m_ulColorTableNumEntries = 1 << cLSD.m_ulColorTableBits;
cLSD.m_ulBackgroundColorIndex = pBuffer[5];
cLSD.m_ulPixelAspectRatio = pBuffer[6];
cLSD.m_fPixelAspectRatio = (cLSD.m_ulPixelAspectRatio + 15.0F) / 64.0F;
}
HX_RESULT CGIFCodec::ParseContainerHeader(BYTE * &pBuffer)
{
/* Verify the signature */
if (pBuffer[0] != 'G' || pBuffer[1] != 'I' || pBuffer[2] != 'F')
{
return HXR_INVALID_OPERATION;
}
pBuffer += 3;
/* Get the version */
if (pBuffer[0] == '8' && pBuffer[1] == '9' && pBuffer[2] == 'a')
{
m_bIsGIF89a = TRUE;
}
else if (pBuffer[0] == '8' && pBuffer[1] == '7' && pBuffer[2] == 'a')
{
m_bIsGIF89a = FALSE;
}
else
{
return HXR_INVALID_OPERATION;
}
pBuffer += 3;
/* Read the Logical Screen Descriptor */
ParseLogicalScreenDescriptor(pBuffer, m_cLSD);
pBuffer += 7;
/* Read the colortable if present */
if (m_cLSD.m_bGlobalColorTablePresent == TRUE)
{
/* Allocate space for the global color table */
if (m_pucGlobalColorMap)
{
delete [] m_pucGlobalColorMap;
m_pucGlobalColorMap = NULL;
}
UINT32 ulColorTableBytes = m_cLSD.m_ulColorTableNumEntries * 3;
m_pucGlobalColorMap = new BYTE [ulColorTableBytes];
if (!m_pucGlobalColorMap)
{
return HXR_OUTOFMEMORY;
}
/* Copy the global color table */
memcpy(m_pucGlobalColorMap, pBuffer, ulColorTableBytes); /* Flawfinder: ignore */
/* Advance the pointer */
pBuffer += ulColorTableBytes;
/* Loop through the images, setting the global color map */
UINT32 i;
for (i = 0; i < m_ulNumImages; i++)
{
m_pImage[i].SetGlobalColorMap(m_cLSD.m_ulColorTableNumEntries,
m_pucGlobalColorMap);
}
}
// Reset the delay time sum
m_ulDelayTimeSum = 0;
/* Here we loop through looking for Image Descriptors or Graphic Control Extensions */
HX_RESULT retVal;
UINT32 ulImageNum = 0;
for (;;)
{
UINT32 ulMarker = *pBuffer;
switch(ulMarker)
{
case kImageDescriptor:
retVal = m_pImage[ulImageNum].InitDecompress(pBuffer, m_pImageHeaderSize[ulImageNum]);
if (retVal != HXR_OK)
{
return retVal;
}
retVal = m_pImage[ulImageNum].SetCompressedBufferSize(m_pCompressedBufferSize[ulImageNum]);
if (retVal != HXR_OK)
{
return retVal;
}
pBuffer += m_pImageHeaderSize[ulImageNum];
ulImageNum++;
break;
case kExtension:
if (pBuffer[1] == kGraphicControlExtension)
{
retVal = m_pImage[ulImageNum].InitDecompress(pBuffer, m_pImageHeaderSize[ulImageNum]);
if (retVal != HXR_OK)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?