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 + -
显示快捷键?