gifimage.cpp

来自「symbian 下的helix player源代码」· C++ 代码 · 共 966 行 · 第 1/3 页

CPP
966
字号

    /* Set the state */
    m_ulState = kStateDecoInitialized;

    return HXR_OK;
}

HX_RESULT CGIFImage::Decompress(BYTE *pBuffer, UINT32 ulLen)
{
    /* Check for input error conditions */
    if (pBuffer == NULL || ulLen == 0)
    {
        return HXR_INVALID_PARAMETER;
    }

    /* Check state */
    if (m_ulState != kStateDecoInitialized &&
        m_ulState != kStateDecoInProgress)
    {
        return HXR_UNEXPECTED;
    }

    /* If the state is kStateDecoInitialized, then 
     * this is the first time in Decompress(). Therefore,
     * we need to initialize the LZWCodec.
     */
    HX_RESULT retVal;
    if (m_ulState == kStateDecoInitialized)
    {
        /*
         * To initialize, we have to extract the first byte of the buffer, 
         * which is the minimum LZW code size.
         */
        INT32 lSize = *pBuffer++;

        /* Decrement the length */
        ulLen--;

        /* Intialize the LZW Codec */
        retVal = m_pLZWCodec->InitDecompress(lSize);
        if (retVal != HXR_OK)
        {
            return retVal;
        }

        /* Intialize the current x and y */
        m_ulCurX  = 0;
        m_ulCurY  = 0;
        m_ulPass  = 0;
        m_pOutPtr = m_pOutputBuffer;

        /* Set the state so we won't call LZWCodec::InitDecompress() again. */
        m_ulState = kStateDecoInProgress;
    }

    /*
     * Now what we have to do is parse our buffer, sending only actual LZW
     * data to the GIF codec - NOT the GIF block sizes.
     */
    UINT32 ulLZWBlockSize;
    do
    {
        /* Read the block size */
        ulLZWBlockSize = *pBuffer++;

        /* Decrement the length */
        ulLen--;

        /* Do we have the amount of data we think we do? */
        if (ulLen < ulLZWBlockSize)
        {
            /* Something's wrong we don't have the amount of data we thought we would */
            return HXR_FAILED;
        }

        /* If we have data, send the LZW compressed data to the LZW codec */
        if (ulLZWBlockSize > 0)
        {
            retVal = m_pLZWCodec->AppendCompressedBuffer(pBuffer, (INT32) ulLZWBlockSize);
            if (retVal != HXR_OK)
            {
                return retVal;
            }

            /* Update the pointer and decrement the length */
            pBuffer += ulLZWBlockSize;
            ulLen   -= ulLZWBlockSize;
        }
    }
    while (ulLZWBlockSize > 0 && ulLen > 0);

    /*
     * We've now sent all the data in this buffer, so now decompress until 
     * we run out of data.
     */
    for (;;)
    {
        /* Get a color index */
        INT32 lColorIndex = -1;
        retVal = m_pLZWCodec->LZWReadByte(lColorIndex);
        if (retVal != HXR_OK)
        {
            return retVal;
        }

        /* Did we finish? */
        if (m_pLZWCodec->Finished() == TRUE)
        {
            m_ulState = kStateDecoFinished;
            break;
        }

        // Some GIF encoders don't seem to properly terminate the LZW stream.
        // Therefore, we have to check to make sure we're not about
        // to write off the end of the image
        if (m_ulCurY >= m_cID.m_ulImageHeight || m_ulCurX >= m_cID.m_ulImageWidth)
        {
            m_ulState = kStateDecoFinished;
            break;
        }

        /* If we suspended AND don't have a valid index, then get out */
        if (lColorIndex == -1 && m_pLZWCodec->Suspended() == TRUE)
        {
            break;
        }

        /* Place the index in the output buffer */
        m_pOutputBuffer[m_ulCurY * m_cID.m_ulImageWidth + m_ulCurX] = (BYTE) lColorIndex;

        /* Now update the location of the next pixel value */
        BumpPixel();
    }

    return HXR_OK;
}

HX_RESULT CGIFImage::GetIndexImage(BYTE *pLogicalScreen, UINT32 ulWidth, UINT32 ulHeight,
                                   UINT32 ulPadWidth, BOOL bRowsInverted)
{
    if (m_cID.m_ulImageLeft + m_cID.m_ulImageWidth  >  ulWidth  ||
        m_cID.m_ulImageTop  + m_cID.m_ulImageHeight >  ulHeight ||
        m_cID.m_bLocalColorTablePresent             == TRUE)
    {
        return HXR_INVALID_PARAMETER;
    }

    BYTE *pSrc = m_pOutputBuffer;
    BYTE *pDst;
    INT32 lRowStride;
    if (bRowsInverted)
    {
        pDst       = pLogicalScreen + (ulHeight - 1 - m_cID.m_ulImageTop) * ulPadWidth + m_cID.m_ulImageLeft;
        lRowStride = - ((INT32) ulPadWidth);
    }
    else
    {
        pDst       = pLogicalScreen + m_cID.m_ulImageTop * ulPadWidth + m_cID.m_ulImageLeft;
        lRowStride = (INT32) ulPadWidth;
    }

    if (m_bGCEPresent && m_cGCE.m_bTransparentIndexGiven)
    {
        UINT32 ulX;
        UINT32 ulY;
        INT32  lDstJump = lRowStride - m_cID.m_ulImageWidth;
        for (ulY = m_cID.m_ulImageHeight; ulY; ulY--)
        {
            for (ulX = m_cID.m_ulImageWidth; ulX; ulX--)
            {
                if (*pSrc != m_cGCE.m_ulTransparentColorIndex)
                {
                    *pDst = *pSrc;
                }
                pSrc++;
                pDst++;
            }
            pDst += lDstJump;
        }
    }
    else
    {
        UINT32 ulRow;
        for (ulRow = m_cID.m_ulImageHeight; ulRow; ulRow--)
        {
            memcpy(pDst, pSrc, m_cID.m_ulImageWidth); /* Flawfinder: ignore */
            pSrc += m_cID.m_ulImageWidth;
            pDst += lRowStride;
        }
    }

    return HXR_OK;
}

HX_RESULT CGIFImage::GetRGBImage(BYTE *pLogicalScreen, UINT32 ulWidth, UINT32 ulHeight, UINT32 ulPadWidth,
                                 UINT32 ulBytesPerPixel, BOOL bRowsInverted, BOOL bRGBOrdering,
                                 BYTE ucBackRed, BYTE ucBackGreen, BYTE ucBackBlue,
                                 BYTE ucBackAlpha)
{
    if (m_cID.m_ulImageLeft + m_cID.m_ulImageWidth  >  ulWidth  ||
        m_cID.m_ulImageTop  + m_cID.m_ulImageHeight >  ulHeight ||
        (m_cID.m_bLocalColorTablePresent == FALSE &&
         m_bGlobalColorMapPresent        == FALSE))
    {
        return HXR_INVALID_PARAMETER;
    }

    BYTE *pSrc = m_pOutputBuffer;
    BYTE *pDst;
    INT32 lRowStride;
    if (bRowsInverted)
    {
        pDst       = pLogicalScreen + (ulHeight - 1 - m_cID.m_ulImageTop) * ulPadWidth + m_cID.m_ulImageLeft * ulBytesPerPixel;
        lRowStride = - ((INT32) ulPadWidth);
    }
    else
    {
        pDst       = pLogicalScreen + m_cID.m_ulImageTop * ulPadWidth + m_cID.m_ulImageLeft * ulBytesPerPixel;
        lRowStride = ulPadWidth;
    }
    BYTE *pColorMap = m_pucGlobalColorMap;
    if (m_cID.m_bLocalColorTablePresent)
    {
        pColorMap = m_pucLocalColorMap;
    }
    UINT32 ulRedIndex;
    UINT32 ulGreenIndex;
    UINT32 ulBlueIndex;
    UINT32 ulAlphaIndex;
    if (bRGBOrdering)
    {
        ulAlphaIndex = 0;
        ulRedIndex   = 1;
        ulGreenIndex = 2;
        ulBlueIndex  = 3;
    }
    else
    {
        ulAlphaIndex = 3;
        ulRedIndex   = 2;
        ulGreenIndex = 1;
        ulBlueIndex  = 0;
    }

    if (m_bGCEPresent && m_cGCE.m_bTransparentIndexGiven)
    {
        // Here we take care of a special case: when the current frame is a subimage and
        // the disposal method for this frame is restore to background. Then we have to
        // go to all the pixels in the logical screen outside the subimage and also restore
        // them to the background color. This fixes PR6182.
        if (m_cGCE.m_ulDisposalMethod == kDisposalMethodRestoreToBackground &&
            (m_cID.m_ulImageWidth < ulWidth || m_cID.m_ulImageHeight < ulHeight))
        {
            for (UINT32 ulLogY = 0; ulLogY < ulHeight; ulLogY++)
            {
                BYTE *pLogRow = pLogicalScreen + ulLogY * ulPadWidth;
                for (UINT32 ulLogX = ulWidth; ulLogX; ulLogX--)
                {
                    pLogRow[ulRedIndex]   = ucBackRed;
                    pLogRow[ulGreenIndex] = ucBackGreen;
                    pLogRow[ulBlueIndex]  = ucBackBlue;
                    pLogRow[ulAlphaIndex] = ucBackAlpha;
                    pLogRow              += ulBytesPerPixel;
                }
            }
        }

        UINT32 ulX;
        UINT32 ulY;
        INT32  lDstJump = lRowStride - ((INT32) (m_cID.m_ulImageWidth * ulBytesPerPixel));
        BYTE  *pMap;
        for (ulY = m_cID.m_ulImageHeight; ulY; ulY--)
        {
            for (ulX = m_cID.m_ulImageWidth; ulX; ulX--)
            {
                UINT32 ulColorIndex = *pSrc++;
                if (ulColorIndex != m_cGCE.m_ulTransparentColorIndex)
                {
                    pMap               = pColorMap + (ulColorIndex * 3);
                    pDst[ulRedIndex]   = pMap[0];
                    pDst[ulGreenIndex] = pMap[1];
                    pDst[ulBlueIndex]  = pMap[2];
                }
                else
                {
                    if (m_cGCE.m_ulDisposalMethod == kDisposalMethodRestoreToBackground)
                    {
                       pDst[ulRedIndex]   = ucBackRed;
                       pDst[ulGreenIndex] = ucBackGreen;
                       pDst[ulBlueIndex]  = ucBackBlue;
                       pDst[ulAlphaIndex] = ucBackAlpha;
                    }
                }
                pDst += ulBytesPerPixel;
            }
            pDst += lDstJump;
        }
    }
    else
    {
        UINT32 ulX;
        UINT32 ulY;
        INT32  lDstJump = lRowStride - ((INT32) (m_cID.m_ulImageWidth * ulBytesPerPixel));
        BYTE  *pMap;
        for (ulY = m_cID.m_ulImageHeight; ulY; ulY--)
        {
            for (ulX = m_cID.m_ulImageWidth; ulX; ulX--)
            {
                UINT32 ulColorIndex = *pSrc++;
                pMap                = pColorMap + (ulColorIndex * 3);
                pDst[ulRedIndex]    = pMap[0];
                pDst[ulGreenIndex]  = pMap[1];
                pDst[ulBlueIndex]   = pMap[2];
                pDst               += ulBytesPerPixel;
            }
            pDst += lDstJump;
        }
    }

    return HXR_OK;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?