gifimage.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:31k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. // system
  36. #include <hlxclib/memory.h>
  37. #include <string.h>
  38. // include
  39. #include "hxtypes.h"
  40. #include "hxcom.h"
  41. // pnmisc
  42. #include "baseobj.h"
  43. #include "unkimp.h"
  44. // pxcomlib
  45. #include "pxtransp.h"
  46. // pxgiflib
  47. #include "gifimage.h"
  48. #include "gifcodec.h"
  49. // pndebug
  50. #include "hxheap.h"
  51. #ifdef _DEBUG
  52. #undef HX_THIS_FILE
  53. static char HX_THIS_FILE[] = __FILE__;
  54. #endif
  55. CGIFImage::CGIFImage()
  56. {
  57.     Reset();
  58. };
  59. CGIFImage::~CGIFImage()
  60. {
  61.     TermDecompress();
  62. };
  63. void CGIFImage::Reset()
  64. {
  65.     m_cID.m_ulImageLeft                 = 0;
  66.     m_cID.m_ulImageTop                  = 0;
  67.     m_cID.m_ulImageWidth                = 0;
  68.     m_cID.m_ulImageHeight               = 0;
  69.     m_cID.m_bLocalColorTablePresent     = FALSE;
  70.     m_cID.m_bInterlaced                 = FALSE;
  71.     m_cID.m_bLocalColorsSorted          = FALSE;
  72.     m_cID.m_ulLocalColorTableBits       = 0;
  73.     m_cID.m_ulLocalColorTableNumEntries = 0;
  74.     m_cGCE.m_ulDisposalMethod           = 0;
  75.     m_cGCE.m_bUserInputExpected         = FALSE;
  76.     m_cGCE.m_bTransparentIndexGiven     = FALSE;
  77.     m_cGCE.m_ulDelayTime                = 0;
  78.     m_cGCE.m_ulTransparentColorIndex    = 0;
  79.     m_bGCEPresent                       = FALSE;
  80.     m_pucLocalColorMap                  = NULL;
  81.     m_bGlobalColorMapPresent            = FALSE;
  82.     m_ulNumGlobalColors                 = 0;
  83.     m_pucGlobalColorMap                 = NULL;
  84.     m_pOutputBuffer                     = NULL;
  85.     m_ulOutputBufferSize                = 0;
  86.     m_ulCurX                            = 0;
  87.     m_ulCurY                            = 0;
  88.     m_ulPass                            = 0;
  89.     m_pOutPtr                           = NULL;
  90.     m_ulState                           = kStateConstructed;
  91.     m_pLZWCodec                         = NULL;
  92.     m_bValid                            = TRUE;
  93. }
  94. void CGIFImage::TermDecompress()
  95. {
  96.     /* Free the local color map */
  97.     if (m_pucLocalColorMap)
  98.     {
  99.         delete [] m_pucLocalColorMap;
  100.         m_pucLocalColorMap = NULL;
  101.     }
  102.     /* Free the output buffer */
  103.     if (m_pOutputBuffer)
  104.     {
  105.         delete [] m_pOutputBuffer;
  106.         m_pOutputBuffer = NULL;
  107.     }
  108.     /* Delete the LZW Codec */
  109.     HX_DELETE(m_pLZWCodec);
  110.     /* Reset all member variables */
  111.     Reset();
  112. }
  113. void CGIFImage::SetGlobalColorMap(UINT32 ulNumColors, BYTE *pMap)
  114. {
  115.     if (ulNumColors > 0 && pMap != NULL)
  116.     {
  117.         m_bGlobalColorMapPresent = TRUE;
  118.         m_ulNumGlobalColors      = ulNumColors;
  119.         m_pucGlobalColorMap      = pMap;
  120.     }
  121.     else
  122.     {
  123.         m_bGlobalColorMapPresent = FALSE;
  124.         m_ulNumGlobalColors      = 0;
  125.         m_pucGlobalColorMap      = NULL;
  126.     }
  127. }
  128. HX_RESULT CGIFImage::SetCompressedBufferSize(UINT32 ulSize)
  129. {
  130.     // Check for input error
  131.     if (m_pLZWCodec == NULL)
  132.     {
  133.         return HXR_INVALID_PARAMETER;
  134.     }
  135.     return m_pLZWCodec->SetCompressedBufferSize((INT32) ulSize);
  136. }
  137. void CGIFImage::ParseImageDescriptor(BYTE *pBuffer, ImageDescriptor &cID)
  138. {
  139.     cID.m_ulImageLeft                 = (pBuffer[1] << 8) | pBuffer[0];
  140.     cID.m_ulImageTop                  = (pBuffer[3] << 8) | pBuffer[2];
  141.     cID.m_ulImageWidth                = (pBuffer[5] << 8) | pBuffer[4];
  142.     cID.m_ulImageHeight               = (pBuffer[7] << 8) | pBuffer[6];
  143.     cID.m_bLocalColorTablePresent     = (pBuffer[8] & 0x80 ? TRUE : FALSE);
  144.     cID.m_bInterlaced                 = (pBuffer[8] & 0x40 ? TRUE : FALSE);
  145.     cID.m_bLocalColorsSorted          = (pBuffer[8] & 0x20 ? TRUE : FALSE);
  146.     cID.m_ulLocalColorTableBits       = (pBuffer[8] & 0x07) + 1;
  147.     cID.m_ulLocalColorTableNumEntries = 1 << cID.m_ulLocalColorTableBits;
  148. }
  149. void CGIFImage::ParseGraphicControlExtension(BYTE *pBuffer, GraphicControlExtension &cGCE)
  150. {
  151.     cGCE.m_ulDisposalMethod        =  (pBuffer[0] & 0x1C) >> 2;
  152.     cGCE.m_bUserInputExpected      = ((pBuffer[0] & 0x02) ? TRUE : FALSE);
  153.     cGCE.m_bTransparentIndexGiven  = ((pBuffer[0] & 0x01) ? TRUE : FALSE);
  154.     cGCE.m_ulDelayTime             =  (pBuffer[2] << 8) | pBuffer[1];
  155.     cGCE.m_ulTransparentColorIndex =   pBuffer[3];
  156. }
  157. HX_RESULT CGIFImage::InitDecompress(BYTE *pBuffer, UINT32 ulLen)
  158. {
  159.     /* Check for input error conditions */
  160.     if (pBuffer == NULL || ulLen == 0)
  161.     {
  162.         return HXR_INVALID_PARAMETER;
  163.     }
  164.     /* Check the state */
  165.     if (m_ulState != kStateConstructed)
  166.     {
  167.         return HXR_UNEXPECTED;
  168.     }
  169.     /*
  170.      * We're either right at an Image Descriptor or a Graphic Control Extension.
  171.      * If we're at an 
  172.      */
  173.     BYTE *pBufPtr = pBuffer;
  174.     if (*pBufPtr == CGIFCodec::kExtension)
  175.     {
  176.         /* Advance the pointer to the extension type */
  177.         pBufPtr++;
  178.         /* Verify the extension is a GCE */
  179.         UINT32 ulExtension = *pBufPtr++;
  180.         if (ulExtension != CGIFCodec::kGraphicControlExtension)
  181.         {
  182.             return HXR_UNEXPECTED;
  183.         }
  184.         /* Note the presence of the GCE - this means we're GIF89a */
  185.         m_bGCEPresent = TRUE;
  186.         UINT32 ulBlockSize;
  187.         do
  188.         {
  189.             /* Get the block size */
  190.             ulBlockSize = *pBufPtr++;
  191.             /* Initialize the GCE */
  192.             if (ulBlockSize >= 4)
  193.             {
  194.                 ParseGraphicControlExtension(pBufPtr, m_cGCE);
  195.             }
  196.             /* Advance by the block size */
  197.             pBufPtr += ulBlockSize;
  198.         }
  199.         while (ulBlockSize > 0);
  200.     }
  201.     // Skip forward to the image descriptor
  202. //    if (*pBuffer != CGIFCodec::kImageDescriptor)
  203. //    {
  204. //        return HXR_UNEXPECTED;
  205. //    }
  206.     while (*pBufPtr != CGIFCodec::kImageDescriptor && pBufPtr < pBuffer + ulLen)
  207.     {
  208.         // We assume here that these can only be extensions
  209.         pBufPtr += 2;
  210.         CGIFCodec::SkipBlocks(pBufPtr);
  211.     }
  212.     if (pBufPtr >= pBuffer + ulLen)
  213.     {
  214.         return HXR_FAIL;
  215.     }
  216.     /* Advance the pointer */
  217.     pBufPtr++;
  218.     /* Parse the Image Descriptor */
  219.     ParseImageDescriptor(pBufPtr, m_cID);
  220.     pBufPtr += 9;
  221.     /* Get the local colormap (if present) */
  222.     if (m_cID.m_bLocalColorTablePresent == TRUE)
  223.     {
  224.         /* Allocate memory for the local color table */
  225.         if (m_pucLocalColorMap)
  226.         {
  227.             delete [] m_pucLocalColorMap;
  228.             m_pucLocalColorMap = NULL;
  229.         }
  230.         UINT32 ulNumBytes  = m_cID.m_ulLocalColorTableNumEntries * 3;
  231.         m_pucLocalColorMap = new BYTE [ulNumBytes];
  232.         if (!m_pucLocalColorMap)
  233.         {
  234.             return HXR_OUTOFMEMORY;
  235.         }
  236.         /* Read in the local color table */
  237.         memcpy(m_pucLocalColorMap, pBufPtr, ulNumBytes); /* Flawfinder: ignore */
  238.         /* Advance the pointer */
  239.         pBufPtr += ulNumBytes;
  240.     }
  241.     /* Allocate an output buffer */
  242.     if (m_pOutputBuffer)
  243.     {
  244.         delete [] m_pOutputBuffer;
  245.         m_pOutputBuffer = NULL;
  246.     }
  247.     m_ulOutputBufferSize = m_cID.m_ulImageWidth * m_cID.m_ulImageHeight;
  248.     m_pOutputBuffer      = new BYTE [m_ulOutputBufferSize];
  249.     if (!m_pOutputBuffer)
  250.     {
  251.         if (m_pucLocalColorMap)
  252.         {
  253.             delete [] m_pucLocalColorMap;
  254.             m_pucLocalColorMap = NULL;
  255.         }
  256.         return HXR_OUTOFMEMORY;
  257.     }
  258.     /* Clear the output buffer */
  259.     memset(m_pOutputBuffer, 0, m_ulOutputBufferSize);
  260.     /* Allocate an LZW Codec */
  261.     HX_DELETE(m_pLZWCodec);
  262.     m_pLZWCodec = new LZWCodec();
  263.     if (!m_pLZWCodec)
  264.     {
  265.         if (m_pucLocalColorMap)
  266.         {
  267.             delete [] m_pucLocalColorMap;
  268.             m_pucLocalColorMap = NULL;
  269.         }
  270.         if (m_pOutputBuffer)
  271.         {
  272.             delete [] m_pOutputBuffer;
  273.             m_pOutputBuffer = NULL;
  274.         }
  275.         return HXR_OUTOFMEMORY;
  276.     }
  277.     /* Set the state */
  278.     m_ulState = kStateDecoInitialized;
  279.     return HXR_OK;
  280. }
  281. HX_RESULT CGIFImage::Decompress(BYTE *pBuffer, UINT32 ulLen)
  282. {
  283.     /* Check for input error conditions */
  284.     if (pBuffer == NULL || ulLen == 0)
  285.     {
  286.         return HXR_INVALID_PARAMETER;
  287.     }
  288.     /* Check state */
  289.     if (m_ulState != kStateDecoInitialized &&
  290.         m_ulState != kStateDecoInProgress)
  291.     {
  292.         return HXR_UNEXPECTED;
  293.     }
  294.     /* If the state is kStateDecoInitialized, then 
  295.      * this is the first time in Decompress(). Therefore,
  296.      * we need to initialize the LZWCodec.
  297.      */
  298.     HX_RESULT retVal;
  299.     if (m_ulState == kStateDecoInitialized)
  300.     {
  301.         /*
  302.          * To initialize, we have to extract the first byte of the buffer, 
  303.          * which is the minimum LZW code size.
  304.          */
  305.         INT32 lSize = *pBuffer++;
  306.         /* Decrement the length */
  307.         ulLen--;
  308.         /* Intialize the LZW Codec */
  309.         retVal = m_pLZWCodec->InitDecompress(lSize);
  310.         if (retVal != HXR_OK)
  311.         {
  312.             return retVal;
  313.         }
  314.         /* Intialize the current x and y */
  315.         m_ulCurX  = 0;
  316.         m_ulCurY  = 0;
  317.         m_ulPass  = 0;
  318.         m_pOutPtr = m_pOutputBuffer;
  319.         /* Set the state so we won't call LZWCodec::InitDecompress() again. */
  320.         m_ulState = kStateDecoInProgress;
  321.     }
  322.     /*
  323.      * Now what we have to do is parse our buffer, sending only actual LZW
  324.      * data to the GIF codec - NOT the GIF block sizes.
  325.      */
  326.     UINT32 ulLZWBlockSize;
  327.     do
  328.     {
  329.         /* Read the block size */
  330.         ulLZWBlockSize = *pBuffer++;
  331.         /* Decrement the length */
  332.         ulLen--;
  333.         /* Do we have the amount of data we think we do? */
  334.         if (ulLen < ulLZWBlockSize)
  335.         {
  336.             /* Something's wrong we don't have the amount of data we thought we would */
  337.             return HXR_FAILED;
  338.         }
  339.         /* If we have data, send the LZW compressed data to the LZW codec */
  340.         if (ulLZWBlockSize > 0)
  341.         {
  342.             retVal = m_pLZWCodec->AppendCompressedBuffer(pBuffer, (INT32) ulLZWBlockSize);
  343.             if (retVal != HXR_OK)
  344.             {
  345.                 return retVal;
  346.             }
  347.             /* Update the pointer and decrement the length */
  348.             pBuffer += ulLZWBlockSize;
  349.             ulLen   -= ulLZWBlockSize;
  350.         }
  351.     }
  352.     while (ulLZWBlockSize > 0 && ulLen > 0);
  353.     /*
  354.      * We've now sent all the data in this buffer, so now decompress until 
  355.      * we run out of data.
  356.      */
  357.     for (;;)
  358.     {
  359.         /* Get a color index */
  360.         INT32 lColorIndex = -1;
  361.         retVal = m_pLZWCodec->LZWReadByte(lColorIndex);
  362.         if (retVal != HXR_OK)
  363.         {
  364.             return retVal;
  365.         }
  366.         /* Did we finish? */
  367.         if (m_pLZWCodec->Finished() == TRUE)
  368.         {
  369.             m_ulState = kStateDecoFinished;
  370.             break;
  371.         }
  372.         // Some GIF encoders don't seem to properly terminate the LZW stream.
  373.         // Therefore, we have to check to make sure we're not about
  374.         // to write off the end of the image
  375.         if (m_ulCurY >= m_cID.m_ulImageHeight || m_ulCurX >= m_cID.m_ulImageWidth)
  376.         {
  377.             m_ulState = kStateDecoFinished;
  378.             break;
  379.         }
  380.         /* If we suspended AND don't have a valid index, then get out */
  381.         if (lColorIndex == -1 && m_pLZWCodec->Suspended() == TRUE)
  382.         {
  383.             break;
  384.         }
  385.         /* Place the index in the output buffer */
  386.         m_pOutputBuffer[m_ulCurY * m_cID.m_ulImageWidth + m_ulCurX] = (BYTE) lColorIndex;
  387.         /* Now update the location of the next pixel value */
  388.         BumpPixel();
  389.     }
  390.     return HXR_OK;
  391. }
  392. HX_RESULT CGIFImage::GetIndexImage(BYTE *pLogicalScreen, UINT32 ulWidth, UINT32 ulHeight,
  393.                                    UINT32 ulPadWidth, BOOL bRowsInverted)
  394. {
  395.     if (m_cID.m_ulImageLeft + m_cID.m_ulImageWidth  >  ulWidth  ||
  396.         m_cID.m_ulImageTop  + m_cID.m_ulImageHeight >  ulHeight ||
  397.         m_cID.m_bLocalColorTablePresent             == TRUE)
  398.     {
  399.         return HXR_INVALID_PARAMETER;
  400.     }
  401.     BYTE *pSrc = m_pOutputBuffer;
  402.     BYTE *pDst;
  403.     INT32 lRowStride;
  404.     if (bRowsInverted)
  405.     {
  406.         pDst       = pLogicalScreen + (ulHeight - 1 - m_cID.m_ulImageTop) * ulPadWidth + m_cID.m_ulImageLeft;
  407.         lRowStride = - ((INT32) ulPadWidth);
  408.     }
  409.     else
  410.     {
  411.         pDst       = pLogicalScreen + m_cID.m_ulImageTop * ulPadWidth + m_cID.m_ulImageLeft;
  412.         lRowStride = (INT32) ulPadWidth;
  413.     }
  414.     if (m_bGCEPresent && m_cGCE.m_bTransparentIndexGiven)
  415.     {
  416.         UINT32 ulX;
  417.         UINT32 ulY;
  418.         INT32  lDstJump = lRowStride - m_cID.m_ulImageWidth;
  419.         for (ulY = m_cID.m_ulImageHeight; ulY; ulY--)
  420.         {
  421.             for (ulX = m_cID.m_ulImageWidth; ulX; ulX--)
  422.             {
  423.                 if (*pSrc != m_cGCE.m_ulTransparentColorIndex)
  424.                 {
  425.                     *pDst = *pSrc;
  426.                 }
  427.                 pSrc++;
  428.                 pDst++;
  429.             }
  430.             pDst += lDstJump;
  431.         }
  432.     }
  433.     else
  434.     {
  435.         UINT32 ulRow;
  436.         for (ulRow = m_cID.m_ulImageHeight; ulRow; ulRow--)
  437.         {
  438.             memcpy(pDst, pSrc, m_cID.m_ulImageWidth); /* Flawfinder: ignore */
  439.             pSrc += m_cID.m_ulImageWidth;
  440.             pDst += lRowStride;
  441.         }
  442.     }
  443.     return HXR_OK;
  444. }
  445. HX_RESULT CGIFImage::GetRGBImage(BYTE *pLogicalScreen, UINT32 ulWidth, UINT32 ulHeight, UINT32 ulPadWidth,
  446.                                  UINT32 ulBytesPerPixel, BOOL bRowsInverted, BOOL bRGBOrdering,
  447.                                  BYTE ucBackRed, BYTE ucBackGreen, BYTE ucBackBlue,
  448.                                  BYTE ucBackAlpha)
  449. {
  450.     if (m_cID.m_ulImageLeft + m_cID.m_ulImageWidth  >  ulWidth  ||
  451.         m_cID.m_ulImageTop  + m_cID.m_ulImageHeight >  ulHeight ||
  452.         (m_cID.m_bLocalColorTablePresent == FALSE &&
  453.          m_bGlobalColorMapPresent        == FALSE))
  454.     {
  455.         return HXR_INVALID_PARAMETER;
  456.     }
  457.     BYTE *pSrc = m_pOutputBuffer;
  458.     BYTE *pDst;
  459.     INT32 lRowStride;
  460.     if (bRowsInverted)
  461.     {
  462.         pDst       = pLogicalScreen + (ulHeight - 1 - m_cID.m_ulImageTop) * ulPadWidth + m_cID.m_ulImageLeft * ulBytesPerPixel;
  463.         lRowStride = - ((INT32) ulPadWidth);
  464.     }
  465.     else
  466.     {
  467.         pDst       = pLogicalScreen + m_cID.m_ulImageTop * ulPadWidth + m_cID.m_ulImageLeft * ulBytesPerPixel;
  468.         lRowStride = ulPadWidth;
  469.     }
  470.     BYTE *pColorMap = m_pucGlobalColorMap;
  471.     if (m_cID.m_bLocalColorTablePresent)
  472.     {
  473.         pColorMap = m_pucLocalColorMap;
  474.     }
  475.     UINT32 ulRedIndex;
  476.     UINT32 ulGreenIndex;
  477.     UINT32 ulBlueIndex;
  478.     UINT32 ulAlphaIndex;
  479.     if (bRGBOrdering)
  480.     {
  481.         ulAlphaIndex = 0;
  482.         ulRedIndex   = 1;
  483.         ulGreenIndex = 2;
  484.         ulBlueIndex  = 3;
  485.     }
  486.     else
  487.     {
  488.         ulAlphaIndex = 3;
  489.         ulRedIndex   = 2;
  490.         ulGreenIndex = 1;
  491.         ulBlueIndex  = 0;
  492.     }
  493.     if (m_bGCEPresent && m_cGCE.m_bTransparentIndexGiven)
  494.     {
  495.         // Here we take care of a special case: when the current frame is a subimage and
  496.         // the disposal method for this frame is restore to background. Then we have to
  497.         // go to all the pixels in the logical screen outside the subimage and also restore
  498.         // them to the background color. This fixes PR6182.
  499.         if (m_cGCE.m_ulDisposalMethod == kDisposalMethodRestoreToBackground &&
  500.             (m_cID.m_ulImageWidth < ulWidth || m_cID.m_ulImageHeight < ulHeight))
  501.         {
  502.             for (UINT32 ulLogY = 0; ulLogY < ulHeight; ulLogY++)
  503.             {
  504.                 BYTE *pLogRow = pLogicalScreen + ulLogY * ulPadWidth;
  505.                 for (UINT32 ulLogX = ulWidth; ulLogX; ulLogX--)
  506.                 {
  507.                     pLogRow[ulRedIndex]   = ucBackRed;
  508.                     pLogRow[ulGreenIndex] = ucBackGreen;
  509.                     pLogRow[ulBlueIndex]  = ucBackBlue;
  510.                     pLogRow[ulAlphaIndex] = ucBackAlpha;
  511.                     pLogRow              += ulBytesPerPixel;
  512.                 }
  513.             }
  514.         }
  515.         UINT32 ulX;
  516.         UINT32 ulY;
  517.         INT32  lDstJump = lRowStride - ((INT32) (m_cID.m_ulImageWidth * ulBytesPerPixel));
  518.         BYTE  *pMap;
  519.         for (ulY = m_cID.m_ulImageHeight; ulY; ulY--)
  520.         {
  521.             for (ulX = m_cID.m_ulImageWidth; ulX; ulX--)
  522.             {
  523.                 UINT32 ulColorIndex = *pSrc++;
  524.                 if (ulColorIndex != m_cGCE.m_ulTransparentColorIndex)
  525.                 {
  526.                     pMap               = pColorMap + (ulColorIndex * 3);
  527.                     pDst[ulRedIndex]   = pMap[0];
  528.                     pDst[ulGreenIndex] = pMap[1];
  529.                     pDst[ulBlueIndex]  = pMap[2];
  530.                 }
  531.                 else
  532.                 {
  533.                     if (m_cGCE.m_ulDisposalMethod == kDisposalMethodRestoreToBackground)
  534.                     {
  535.                        pDst[ulRedIndex]   = ucBackRed;
  536.                        pDst[ulGreenIndex] = ucBackGreen;
  537.                        pDst[ulBlueIndex]  = ucBackBlue;
  538.                        pDst[ulAlphaIndex] = ucBackAlpha;
  539.                     }
  540.                 }
  541.                 pDst += ulBytesPerPixel;
  542.             }
  543.             pDst += lDstJump;
  544.         }
  545.     }
  546.     else
  547.     {
  548.         UINT32 ulX;
  549.         UINT32 ulY;
  550.         INT32  lDstJump = lRowStride - ((INT32) (m_cID.m_ulImageWidth * ulBytesPerPixel));
  551.         BYTE  *pMap;
  552.         for (ulY = m_cID.m_ulImageHeight; ulY; ulY--)
  553.         {
  554.             for (ulX = m_cID.m_ulImageWidth; ulX; ulX--)
  555.             {
  556.                 UINT32 ulColorIndex = *pSrc++;
  557.                 pMap                = pColorMap + (ulColorIndex * 3);
  558.                 pDst[ulRedIndex]    = pMap[0];
  559.                 pDst[ulGreenIndex]  = pMap[1];
  560.                 pDst[ulBlueIndex]   = pMap[2];
  561.                 pDst               += ulBytesPerPixel;
  562.             }
  563.             pDst += lDstJump;
  564.         }
  565.     }
  566.     return HXR_OK;
  567. }
  568. HX_RESULT CGIFImage::GetRGBImageEx(BYTE *pLogicalScreen, UINT32 ulWidth, UINT32 ulHeight, UINT32 ulPadWidth,
  569.                                    UINT32 ulBytesPerPixel, BOOL bRowsInverted, BOOL bRGBOrdering,
  570.                                    UINT32 ulBgColor, BOOL bMediaOpacity, UINT32 ulMediaOpacity,
  571.                                    BOOL bChromaKey, UINT32 ulChromaKey, UINT32 ulChromaKeyTol, UINT32 ulChromaKeyOpacity)
  572. {
  573.     HX_RESULT retVal = HXR_OK;
  574.     if (pLogicalScreen && 
  575.         m_cID.m_ulImageLeft + m_cID.m_ulImageWidth  <= ulWidth &&
  576.         m_cID.m_ulImageTop  + m_cID.m_ulImageHeight <= ulHeight &&
  577.         (m_cID.m_bLocalColorTablePresent || m_bGlobalColorMapPresent))
  578.     {
  579.         BYTE *pSrc       = m_pOutputBuffer;
  580.         BYTE *pDst       = NULL;
  581.         INT32 lRowStride = 0;
  582.         if (bRowsInverted)
  583.         {
  584.             pDst       = pLogicalScreen + (ulHeight - 1 - m_cID.m_ulImageTop) * ulPadWidth +
  585.                          m_cID.m_ulImageLeft * ulBytesPerPixel;
  586.             lRowStride = - ((INT32) ulPadWidth);
  587.         }
  588.         else
  589.         {
  590.             pDst       = pLogicalScreen + m_cID.m_ulImageTop * ulPadWidth +
  591.                          m_cID.m_ulImageLeft * ulBytesPerPixel;
  592.             lRowStride = ulPadWidth;
  593.         }
  594.         BYTE *pColorMap = m_pucGlobalColorMap;
  595.         if (m_cID.m_bLocalColorTablePresent)
  596.         {
  597.             pColorMap = m_pucLocalColorMap;
  598.         }
  599.         UINT32 ulRedIndex;
  600.         UINT32 ulGreenIndex;
  601.         UINT32 ulBlueIndex;
  602.         UINT32 ulAlphaIndex;
  603.         if (bRGBOrdering)
  604.         {
  605.             ulAlphaIndex = 0;
  606.             ulRedIndex   = 1;
  607.             ulGreenIndex = 2;
  608.             ulBlueIndex  = 3;
  609.         }
  610.         else
  611.         {
  612.             ulAlphaIndex = 3;
  613.             ulRedIndex   = 2;
  614.             ulGreenIndex = 1;
  615.             ulBlueIndex  = 0;
  616.         }
  617.         BYTE ucBackAlpha = (BYTE) ((ulBgColor & 0xFF000000) >> 24);
  618.         BYTE ucBackRed   = (BYTE) ((ulBgColor & 0x00FF0000) >> 16);
  619.         BYTE ucBackGreen = (BYTE) ((ulBgColor & 0x0000FF00) >>  8);
  620.         BYTE ucBackBlue  = (BYTE)  (ulBgColor & 0x000000FF);
  621.         // Compute the media alpha
  622.         BYTE ucMediaAlpha = 0;
  623.         if (bMediaOpacity)
  624.         {
  625.             INT32 lAlpha = (INT32) (255 - ulMediaOpacity);
  626.             if (lAlpha < 0)   lAlpha = 0;
  627.             if (lAlpha > 255) lAlpha = 255;
  628.             ucMediaAlpha = (BYTE) lAlpha;
  629.         }
  630.         // Compute the chroma key alpha
  631.         BYTE ucChromaAlpha = 255;
  632.         if (bChromaKey)
  633.         {
  634.             // We need to adjust the chroma key opacity by the media
  635.             // opacity
  636.             UINT32 ulNewChromaKeyOpacity = ulChromaKeyOpacity * ulMediaOpacity / 255;
  637.             INT32 lAlpha = (INT32) (255 - ulNewChromaKeyOpacity);
  638.             if (lAlpha < 0)   lAlpha = 0;
  639.             if (lAlpha > 255) lAlpha = 255;
  640.             ucChromaAlpha = (BYTE) lAlpha;
  641.         }
  642.         if (m_bGCEPresent && m_cGCE.m_bTransparentIndexGiven)
  643.         {
  644.             // Here we take care of a special case: when the current frame is a subimage and
  645.             // the disposal method for this frame is restore to background. Then we have to
  646.             // go to all the pixels in the logical screen outside the subimage and also restore
  647.             // them to the background color. This fixes PR6182.
  648.             if (m_cGCE.m_ulDisposalMethod == kDisposalMethodRestoreToBackground &&
  649.                 (m_cID.m_ulImageWidth < ulWidth || m_cID.m_ulImageHeight < ulHeight))
  650.             {
  651.                 for (UINT32 ulLogY = 0; ulLogY < ulHeight; ulLogY++)
  652.                 {
  653.                     BYTE *pLogRow = pLogicalScreen + ulLogY * ulPadWidth;
  654.                     for (UINT32 ulLogX = ulWidth; ulLogX; ulLogX--)
  655.                     {
  656.                         pLogRow[ulRedIndex]   = ucBackRed;
  657.                         pLogRow[ulGreenIndex] = ucBackGreen;
  658.                         pLogRow[ulBlueIndex]  = ucBackBlue;
  659.                         pLogRow[ulAlphaIndex] = ucBackAlpha;
  660.                         pLogRow              += ulBytesPerPixel;
  661.                     }
  662.                 }
  663.             }
  664.             UINT32 ulX;
  665.             UINT32 ulY;
  666.             INT32  lDstJump = lRowStride - ((INT32) (m_cID.m_ulImageWidth * ulBytesPerPixel));
  667.             BYTE  *pMap;
  668.             for (ulY = m_cID.m_ulImageHeight; ulY; ulY--)
  669.             {
  670.                 for (ulX = m_cID.m_ulImageWidth; ulX; ulX--)
  671.                 {
  672.                     UINT32 ulColorIndex = *pSrc++;
  673.                     if (ulColorIndex != m_cGCE.m_ulTransparentColorIndex)
  674.                     {
  675.                         pMap               = pColorMap + (ulColorIndex * 3);
  676.                         pDst[ulRedIndex]   = pMap[0];
  677.                         pDst[ulGreenIndex] = pMap[1];
  678.                         pDst[ulBlueIndex]  = pMap[2];
  679.                         pDst[ulAlphaIndex] = ucMediaAlpha;
  680.                         if (bChromaKey)
  681.                         {
  682.                             UINT32 ulMapColor = (pMap[0] << 16) | (pMap[1] << 8) | pMap[2];
  683.                             if (DoesChromaKeyMatch(ulMapColor, ulChromaKey, ulChromaKeyTol))
  684.                             {
  685.                                 pDst[ulAlphaIndex] = ucChromaAlpha;
  686.                             }
  687.                         }
  688.                     }
  689.                     else
  690.                     {
  691.                         if (m_cGCE.m_ulDisposalMethod == kDisposalMethodRestoreToBackground)
  692.                         {
  693.                            pDst[ulRedIndex]   = ucBackRed;
  694.                            pDst[ulGreenIndex] = ucBackGreen;
  695.                            pDst[ulBlueIndex]  = ucBackBlue;
  696.                            pDst[ulAlphaIndex] = ucBackAlpha;
  697.                         }
  698.                     }
  699.                     pDst += ulBytesPerPixel;
  700.                 }
  701.                 pDst += lDstJump;
  702.             }
  703.         }
  704.         else
  705.         {
  706.             UINT32 ulX;
  707.             UINT32 ulY;
  708.             INT32  lDstJump = lRowStride - ((INT32) (m_cID.m_ulImageWidth * ulBytesPerPixel));
  709.             BYTE  *pMap;
  710.             for (ulY = m_cID.m_ulImageHeight; ulY; ulY--)
  711.             {
  712.                 for (ulX = m_cID.m_ulImageWidth; ulX; ulX--)
  713.                 {
  714.                     UINT32 ulColorIndex = *pSrc++;
  715.                     pMap                = pColorMap + (ulColorIndex * 3);
  716.                     pDst[ulRedIndex]    = pMap[0];
  717.                     pDst[ulGreenIndex]  = pMap[1];
  718.                     pDst[ulBlueIndex]   = pMap[2];
  719.                     pDst[ulAlphaIndex]  = ucMediaAlpha;
  720.                     if (bChromaKey)
  721.                     {
  722.                         UINT32 ulMapColor = (pMap[0] << 16) | (pMap[1] << 8) | pMap[2];
  723.                         if (DoesChromaKeyMatch(ulMapColor, ulChromaKey, ulChromaKeyTol))
  724.                         {
  725.                             pDst[ulAlphaIndex] = ucChromaAlpha;
  726.                         }
  727.                     }
  728.                     pDst               += ulBytesPerPixel;
  729.                 }
  730.                 pDst += lDstJump;
  731.             }
  732.         }
  733.     }
  734.     else
  735.     {
  736.         retVal = HXR_FAIL;
  737.     }
  738.     return retVal;
  739. }
  740. HX_RESULT CGIFImage::GetRGB32(BYTE *pBuffer, UINT32 ulRowStride, BOOL bRowsInverted)
  741. {
  742.     HX_RESULT retVal = HXR_OK;
  743.     if (pBuffer)
  744.     {
  745.         if (m_pOutputBuffer)
  746.         {
  747.             BYTE* pColorMap = NULL;
  748.             if (m_cID.m_bLocalColorTablePresent)
  749.             {
  750.                 pColorMap = m_pucLocalColorMap;
  751.             }
  752.             else if (m_bGlobalColorMapPresent)
  753.             {
  754.                 pColorMap = m_pucGlobalColorMap;
  755.             }
  756.             else
  757.             {
  758.                 retVal = HXR_FAIL;
  759.             }
  760.             if (SUCCEEDED(retVal))
  761.             {
  762.                 BYTE*   pSrc     = m_pOutputBuffer;
  763.                 UINT32* pDstRow  = NULL;
  764.                 INT32   lRowJump = 0;
  765.                 if (bRowsInverted)
  766.                 {
  767.                     pDstRow  = (UINT32*) (pBuffer + (m_cID.m_ulImageHeight - 1) * ulRowStride);
  768.                     lRowJump = - (INT32) (ulRowStride >> 2);
  769.                 }
  770.                 else
  771.                 {
  772.                     pDstRow  = (UINT32*) pBuffer;
  773.                     lRowJump = ulRowStride >> 2;
  774.                 }
  775.                 if (m_bGCEPresent && m_cGCE.m_bTransparentIndexGiven)
  776.                 {
  777.                     UINT32 ulTransparentPixel = 0xFF000000;
  778.                     for (UINT32 ulY = m_cID.m_ulImageHeight; ulY; ulY--)
  779.                     {
  780.                         UINT32* pDst = pDstRow;
  781.                         for (UINT32 ulX = m_cID.m_ulImageWidth; ulX; ulX--)
  782.                         {
  783.                             UINT32 ulColorIndex = *pSrc++;
  784.                             if (ulColorIndex == m_cGCE.m_ulTransparentColorIndex)
  785.                             {
  786.                                 *pDst++ = ulTransparentPixel;
  787.                             }
  788.                             else
  789.                             {
  790.                                 BYTE* pMap = pColorMap + (ulColorIndex * 3);
  791.                                 *pDst++    = (pMap[0] << 16) | (pMap[1] << 8) | pMap[2];
  792.                             }
  793.                         }
  794.                         pDstRow += lRowJump;
  795.                     }
  796.                 }
  797.                 else
  798.                 {
  799.                     for (UINT32 ulY = m_cID.m_ulImageHeight; ulY; ulY--)
  800.                     {
  801.                         UINT32* pDst = pDstRow;
  802.                         for (UINT32 ulX = m_cID.m_ulImageWidth; ulX; ulX--)
  803.                         {
  804.                             UINT32 ulColorIndex = *pSrc++;
  805.                             BYTE*  pMap         = pColorMap + (ulColorIndex * 3);
  806.                             *pDst++             = (pMap[0] << 16) | (pMap[1] << 8) | pMap[2];
  807.                         }
  808.                         pDstRow += lRowJump;
  809.                     }
  810.                 }
  811.             }
  812.         }
  813.         else
  814.         {
  815.             retVal = HXR_UNEXPECTED;
  816.         }
  817.     }
  818.     else
  819.     {
  820.         retVal = HXR_INVALID_PARAMETER;
  821.     }
  822.     return retVal;
  823. }
  824. void CGIFImage::BumpPixel()
  825. {
  826.     /* Bump the current X position */
  827.     m_ulCurX++;
  828.     /*
  829.      * If we are at the end of a scan line, set current x back to the beginning
  830.      * If we are interlaced, bump the current y to the appropriate spot,
  831.      * Otherwise, just increment it.
  832.      */
  833.     if(m_ulCurX == m_cID.m_ulImageWidth)
  834.     {
  835.         m_ulCurX = 0;
  836.         if(m_cID.m_bInterlaced == FALSE)
  837.         {
  838.             ++m_ulCurY;
  839.         }
  840.         else
  841.         {
  842.             switch(m_ulPass)
  843.             {
  844.                 case 0:
  845.                     m_ulCurY += 8;
  846.                     if(m_ulCurY >= m_cID.m_ulImageHeight)
  847.                     {
  848.                         ++m_ulPass;
  849.                         m_ulCurY = 4;
  850.                     }
  851.                     break;
  852.                 case 1:
  853.                     m_ulCurY += 8;
  854.                     if(m_ulCurY >= m_cID.m_ulImageHeight)
  855.                     {
  856.                         ++m_ulPass;
  857.                         m_ulCurY = 2;
  858.                     }
  859.                     break;
  860.                 case 2:
  861.                     m_ulCurY += 4;
  862.                     if(m_ulCurY >= m_cID.m_ulImageHeight)
  863.                     {
  864.                         ++m_ulPass;
  865.                         m_ulCurY = 1;
  866.                     }
  867.                     break;
  868.                 case 3:
  869.                     m_ulCurY += 2;
  870.                     break;
  871.             }
  872.         }
  873.     }
  874. }