gifimage.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:32k
源码类别:

Symbian

开发平台:

Visual C++

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