gifimage.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:31k
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: RCSL 1.0/RPSL 1.0
- *
- * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file, are
- * subject to the current version of the RealNetworks Public Source License
- * Version 1.0 (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the RealNetworks Community Source License Version 1.0
- * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
- * in which case the RCSL will apply. You may also obtain the license terms
- * directly from RealNetworks. You may not use this file except in
- * compliance with the RPSL or, if you have a valid RCSL with RealNetworks
- * applicable to this file, the RCSL. Please see the applicable RPSL or
- * RCSL for the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the portions
- * it created.
- *
- * This file, and the files included with this file, is distributed and made
- * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- // system
- #include <hlxclib/memory.h>
- #include <string.h>
- // include
- #include "hxtypes.h"
- #include "hxcom.h"
- // pnmisc
- #include "baseobj.h"
- #include "unkimp.h"
- // pxcomlib
- #include "pxtransp.h"
- // pxgiflib
- #include "gifimage.h"
- #include "gifcodec.h"
- // pndebug
- #include "hxheap.h"
- #ifdef _DEBUG
- #undef HX_THIS_FILE
- static char HX_THIS_FILE[] = __FILE__;
- #endif
- CGIFImage::CGIFImage()
- {
- Reset();
- };
- CGIFImage::~CGIFImage()
- {
- TermDecompress();
- };
- void CGIFImage::Reset()
- {
- m_cID.m_ulImageLeft = 0;
- m_cID.m_ulImageTop = 0;
- m_cID.m_ulImageWidth = 0;
- m_cID.m_ulImageHeight = 0;
- m_cID.m_bLocalColorTablePresent = FALSE;
- m_cID.m_bInterlaced = FALSE;
- m_cID.m_bLocalColorsSorted = FALSE;
- m_cID.m_ulLocalColorTableBits = 0;
- m_cID.m_ulLocalColorTableNumEntries = 0;
- m_cGCE.m_ulDisposalMethod = 0;
- m_cGCE.m_bUserInputExpected = FALSE;
- m_cGCE.m_bTransparentIndexGiven = FALSE;
- m_cGCE.m_ulDelayTime = 0;
- m_cGCE.m_ulTransparentColorIndex = 0;
- m_bGCEPresent = FALSE;
- m_pucLocalColorMap = NULL;
- m_bGlobalColorMapPresent = FALSE;
- m_ulNumGlobalColors = 0;
- m_pucGlobalColorMap = NULL;
- m_pOutputBuffer = NULL;
- m_ulOutputBufferSize = 0;
- m_ulCurX = 0;
- m_ulCurY = 0;
- m_ulPass = 0;
- m_pOutPtr = NULL;
- m_ulState = kStateConstructed;
- m_pLZWCodec = NULL;
- m_bValid = TRUE;
- }
- void CGIFImage::TermDecompress()
- {
- /* Free the local color map */
- if (m_pucLocalColorMap)
- {
- delete [] m_pucLocalColorMap;
- m_pucLocalColorMap = NULL;
- }
- /* Free the output buffer */
- if (m_pOutputBuffer)
- {
- delete [] m_pOutputBuffer;
- m_pOutputBuffer = NULL;
- }
- /* Delete the LZW Codec */
- HX_DELETE(m_pLZWCodec);
- /* Reset all member variables */
- Reset();
- }
- void CGIFImage::SetGlobalColorMap(UINT32 ulNumColors, BYTE *pMap)
- {
- if (ulNumColors > 0 && pMap != NULL)
- {
- m_bGlobalColorMapPresent = TRUE;
- m_ulNumGlobalColors = ulNumColors;
- m_pucGlobalColorMap = pMap;
- }
- else
- {
- m_bGlobalColorMapPresent = FALSE;
- m_ulNumGlobalColors = 0;
- m_pucGlobalColorMap = NULL;
- }
- }
- HX_RESULT CGIFImage::SetCompressedBufferSize(UINT32 ulSize)
- {
- // Check for input error
- if (m_pLZWCodec == NULL)
- {
- return HXR_INVALID_PARAMETER;
- }
- return m_pLZWCodec->SetCompressedBufferSize((INT32) ulSize);
- }
- void CGIFImage::ParseImageDescriptor(BYTE *pBuffer, ImageDescriptor &cID)
- {
- cID.m_ulImageLeft = (pBuffer[1] << 8) | pBuffer[0];
- cID.m_ulImageTop = (pBuffer[3] << 8) | pBuffer[2];
- cID.m_ulImageWidth = (pBuffer[5] << 8) | pBuffer[4];
- cID.m_ulImageHeight = (pBuffer[7] << 8) | pBuffer[6];
- cID.m_bLocalColorTablePresent = (pBuffer[8] & 0x80 ? TRUE : FALSE);
- cID.m_bInterlaced = (pBuffer[8] & 0x40 ? TRUE : FALSE);
- cID.m_bLocalColorsSorted = (pBuffer[8] & 0x20 ? TRUE : FALSE);
- cID.m_ulLocalColorTableBits = (pBuffer[8] & 0x07) + 1;
- cID.m_ulLocalColorTableNumEntries = 1 << cID.m_ulLocalColorTableBits;
- }
- void CGIFImage::ParseGraphicControlExtension(BYTE *pBuffer, GraphicControlExtension &cGCE)
- {
- cGCE.m_ulDisposalMethod = (pBuffer[0] & 0x1C) >> 2;
- cGCE.m_bUserInputExpected = ((pBuffer[0] & 0x02) ? TRUE : FALSE);
- cGCE.m_bTransparentIndexGiven = ((pBuffer[0] & 0x01) ? TRUE : FALSE);
- cGCE.m_ulDelayTime = (pBuffer[2] << 8) | pBuffer[1];
- cGCE.m_ulTransparentColorIndex = pBuffer[3];
- }
- HX_RESULT CGIFImage::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;
- }
- /*
- * We're either right at an Image Descriptor or a Graphic Control Extension.
- * If we're at an
- */
- BYTE *pBufPtr = pBuffer;
- if (*pBufPtr == CGIFCodec::kExtension)
- {
- /* Advance the pointer to the extension type */
- pBufPtr++;
- /* Verify the extension is a GCE */
- UINT32 ulExtension = *pBufPtr++;
- if (ulExtension != CGIFCodec::kGraphicControlExtension)
- {
- return HXR_UNEXPECTED;
- }
- /* Note the presence of the GCE - this means we're GIF89a */
- m_bGCEPresent = TRUE;
- UINT32 ulBlockSize;
- do
- {
- /* Get the block size */
- ulBlockSize = *pBufPtr++;
- /* Initialize the GCE */
- if (ulBlockSize >= 4)
- {
- ParseGraphicControlExtension(pBufPtr, m_cGCE);
- }
- /* Advance by the block size */
- pBufPtr += ulBlockSize;
- }
- while (ulBlockSize > 0);
- }
- // Skip forward to the image descriptor
- // if (*pBuffer != CGIFCodec::kImageDescriptor)
- // {
- // return HXR_UNEXPECTED;
- // }
- while (*pBufPtr != CGIFCodec::kImageDescriptor && pBufPtr < pBuffer + ulLen)
- {
- // We assume here that these can only be extensions
- pBufPtr += 2;
- CGIFCodec::SkipBlocks(pBufPtr);
- }
- if (pBufPtr >= pBuffer + ulLen)
- {
- return HXR_FAIL;
- }
- /* Advance the pointer */
- pBufPtr++;
- /* Parse the Image Descriptor */
- ParseImageDescriptor(pBufPtr, m_cID);
- pBufPtr += 9;
- /* Get the local colormap (if present) */
- if (m_cID.m_bLocalColorTablePresent == TRUE)
- {
- /* Allocate memory for the local color table */
- if (m_pucLocalColorMap)
- {
- delete [] m_pucLocalColorMap;
- m_pucLocalColorMap = NULL;
- }
- UINT32 ulNumBytes = m_cID.m_ulLocalColorTableNumEntries * 3;
- m_pucLocalColorMap = new BYTE [ulNumBytes];
- if (!m_pucLocalColorMap)
- {
- return HXR_OUTOFMEMORY;
- }
- /* Read in the local color table */
- memcpy(m_pucLocalColorMap, pBufPtr, ulNumBytes); /* Flawfinder: ignore */
- /* Advance the pointer */
- pBufPtr += ulNumBytes;
- }
- /* Allocate an output buffer */
- if (m_pOutputBuffer)
- {
- delete [] m_pOutputBuffer;
- m_pOutputBuffer = NULL;
- }
- m_ulOutputBufferSize = m_cID.m_ulImageWidth * m_cID.m_ulImageHeight;
- m_pOutputBuffer = new BYTE [m_ulOutputBufferSize];
- if (!m_pOutputBuffer)
- {
- if (m_pucLocalColorMap)
- {
- delete [] m_pucLocalColorMap;
- m_pucLocalColorMap = NULL;
- }
- return HXR_OUTOFMEMORY;
- }
- /* Clear the output buffer */
- memset(m_pOutputBuffer, 0, m_ulOutputBufferSize);
- /* Allocate an LZW Codec */
- HX_DELETE(m_pLZWCodec);
- m_pLZWCodec = new LZWCodec();
- if (!m_pLZWCodec)
- {
- if (m_pucLocalColorMap)
- {
- delete [] m_pucLocalColorMap;
- m_pucLocalColorMap = NULL;
- }
- if (m_pOutputBuffer)
- {
- delete [] m_pOutputBuffer;
- m_pOutputBuffer = NULL;
- }
- return HXR_OUTOFMEMORY;
- }
- /* 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;
- }
- HX_RESULT CGIFImage::GetRGBImageEx(BYTE *pLogicalScreen, 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 (pLogicalScreen &&
- m_cID.m_ulImageLeft + m_cID.m_ulImageWidth <= ulWidth &&
- m_cID.m_ulImageTop + m_cID.m_ulImageHeight <= ulHeight &&
- (m_cID.m_bLocalColorTablePresent || m_bGlobalColorMapPresent))
- {
- BYTE *pSrc = m_pOutputBuffer;
- BYTE *pDst = NULL;
- INT32 lRowStride = 0;
- 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;
- }
- BYTE ucBackAlpha = (BYTE) ((ulBgColor & 0xFF000000) >> 24);
- BYTE ucBackRed = (BYTE) ((ulBgColor & 0x00FF0000) >> 16);
- BYTE ucBackGreen = (BYTE) ((ulBgColor & 0x0000FF00) >> 8);
- BYTE ucBackBlue = (BYTE) (ulBgColor & 0x000000FF);
- // Compute the media alpha
- BYTE ucMediaAlpha = 0;
- if (bMediaOpacity)
- {
- INT32 lAlpha = (INT32) (255 - ulMediaOpacity);
- if (lAlpha < 0) lAlpha = 0;
- if (lAlpha > 255) lAlpha = 255;
- ucMediaAlpha = (BYTE) lAlpha;
- }
- // Compute the chroma key alpha
- BYTE ucChromaAlpha = 255;
- if (bChromaKey)
- {
- // We need to adjust the chroma key opacity by the media
- // opacity
- UINT32 ulNewChromaKeyOpacity = ulChromaKeyOpacity * ulMediaOpacity / 255;
- INT32 lAlpha = (INT32) (255 - ulNewChromaKeyOpacity);
- if (lAlpha < 0) lAlpha = 0;
- if (lAlpha > 255) lAlpha = 255;
- ucChromaAlpha = (BYTE) lAlpha;
- }
- 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];
- pDst[ulAlphaIndex] = ucMediaAlpha;
- if (bChromaKey)
- {
- UINT32 ulMapColor = (pMap[0] << 16) | (pMap[1] << 8) | pMap[2];
- if (DoesChromaKeyMatch(ulMapColor, ulChromaKey, ulChromaKeyTol))
- {
- pDst[ulAlphaIndex] = ucChromaAlpha;
- }
- }
- }
- 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[ulAlphaIndex] = ucMediaAlpha;
- if (bChromaKey)
- {
- UINT32 ulMapColor = (pMap[0] << 16) | (pMap[1] << 8) | pMap[2];
- if (DoesChromaKeyMatch(ulMapColor, ulChromaKey, ulChromaKeyTol))
- {
- pDst[ulAlphaIndex] = ucChromaAlpha;
- }
- }
- pDst += ulBytesPerPixel;
- }
- pDst += lDstJump;
- }
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- return retVal;
- }
- HX_RESULT CGIFImage::GetRGB32(BYTE *pBuffer, UINT32 ulRowStride, BOOL bRowsInverted)
- {
- HX_RESULT retVal = HXR_OK;
- if (pBuffer)
- {
- if (m_pOutputBuffer)
- {
- BYTE* pColorMap = NULL;
- if (m_cID.m_bLocalColorTablePresent)
- {
- pColorMap = m_pucLocalColorMap;
- }
- else if (m_bGlobalColorMapPresent)
- {
- pColorMap = m_pucGlobalColorMap;
- }
- else
- {
- retVal = HXR_FAIL;
- }
- if (SUCCEEDED(retVal))
- {
- BYTE* pSrc = m_pOutputBuffer;
- UINT32* pDstRow = NULL;
- INT32 lRowJump = 0;
- if (bRowsInverted)
- {
- pDstRow = (UINT32*) (pBuffer + (m_cID.m_ulImageHeight - 1) * ulRowStride);
- lRowJump = - (INT32) (ulRowStride >> 2);
- }
- else
- {
- pDstRow = (UINT32*) pBuffer;
- lRowJump = ulRowStride >> 2;
- }
- if (m_bGCEPresent && m_cGCE.m_bTransparentIndexGiven)
- {
- UINT32 ulTransparentPixel = 0xFF000000;
- for (UINT32 ulY = m_cID.m_ulImageHeight; ulY; ulY--)
- {
- UINT32* pDst = pDstRow;
- for (UINT32 ulX = m_cID.m_ulImageWidth; ulX; ulX--)
- {
- UINT32 ulColorIndex = *pSrc++;
- if (ulColorIndex == m_cGCE.m_ulTransparentColorIndex)
- {
- *pDst++ = ulTransparentPixel;
- }
- else
- {
- BYTE* pMap = pColorMap + (ulColorIndex * 3);
- *pDst++ = (pMap[0] << 16) | (pMap[1] << 8) | pMap[2];
- }
- }
- pDstRow += lRowJump;
- }
- }
- else
- {
- for (UINT32 ulY = m_cID.m_ulImageHeight; ulY; ulY--)
- {
- UINT32* pDst = pDstRow;
- for (UINT32 ulX = m_cID.m_ulImageWidth; ulX; ulX--)
- {
- UINT32 ulColorIndex = *pSrc++;
- BYTE* pMap = pColorMap + (ulColorIndex * 3);
- *pDst++ = (pMap[0] << 16) | (pMap[1] << 8) | pMap[2];
- }
- pDstRow += lRowJump;
- }
- }
- }
- }
- else
- {
- retVal = HXR_UNEXPECTED;
- }
- }
- else
- {
- retVal = HXR_INVALID_PARAMETER;
- }
- return retVal;
- }
- void CGIFImage::BumpPixel()
- {
- /* Bump the current X position */
- m_ulCurX++;
- /*
- * If we are at the end of a scan line, set current x back to the beginning
- * If we are interlaced, bump the current y to the appropriate spot,
- * Otherwise, just increment it.
- */
- if(m_ulCurX == m_cID.m_ulImageWidth)
- {
- m_ulCurX = 0;
- if(m_cID.m_bInterlaced == FALSE)
- {
- ++m_ulCurY;
- }
- else
- {
- switch(m_ulPass)
- {
- case 0:
- m_ulCurY += 8;
- if(m_ulCurY >= m_cID.m_ulImageHeight)
- {
- ++m_ulPass;
- m_ulCurY = 4;
- }
- break;
- case 1:
- m_ulCurY += 8;
- if(m_ulCurY >= m_cID.m_ulImageHeight)
- {
- ++m_ulPass;
- m_ulCurY = 2;
- }
- break;
- case 2:
- m_ulCurY += 4;
- if(m_ulCurY >= m_cID.m_ulImageHeight)
- {
- ++m_ulPass;
- m_ulCurY = 1;
- }
- break;
- case 3:
- m_ulCurY += 2;
- break;
- }
- }
- }
- }