📄 gifcodec.cpp
字号:
/* ***** BEGIN LICENSE BLOCK ***** * Source last modified: $Id: gifcodec.cpp,v 1.2.24.1 2004/07/09 01:54:29 hubbe Exp $ * * Portions Copyright (c) 1995-2004 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 (the "RPSL") available at * http://www.helixcommunity.org/content/rpsl unless you have licensed * the file under the current version of the RealNetworks Community * Source License (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. * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL") in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your version of * this file only under the terms of the GPL, and not to allow others * to use your version of this file under the terms of either the RPSL * or RCSL, indicate your decision by deleting the provisions above * and replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient may * use your version of this file under the terms of any one of the * RPSL, the RCSL or the GPL. * * 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 "glist.h"// pxgiflib#include "gifimage.h"#include "gifcodec.h"// pndebug#include "hxheap.h"#ifdef _DEBUG#undef HX_THIS_FILE static char HX_THIS_FILE[] = __FILE__;#endifBEGIN_INTERFACE_LIST(CGIFCodec)END_INTERFACE_LISTCGIFCodec::CGIFCodec(){ ResetParse(); ResetDecompress();};CGIFCodec::~CGIFCodec(){ TermParse(); TermDecompress();};void CGIFCodec::ResetParse(){ m_ulParseState = kStateConstructed; m_pParseBuffer = NULL; m_ulParseBufferLength = 0; m_pSegment = NULL; m_ulDelayTimeSum = 0; m_ulNumSegmentsAllocated = 0; m_ulNumSegments = 0; m_ulNumImages = 0; m_ulCurSegIndex = 0; m_ulCurSegOffset = 0; m_ulLoopCount = 1;}void CGIFCodec::ResetDecompress(){ m_cLSD.m_ulLogicalScreenWidth = 0; m_cLSD.m_ulLogicalScreenHeight = 0; m_cLSD.m_bGlobalColorTablePresent = FALSE; m_cLSD.m_ulOriginalColorBits = 0; m_cLSD.m_bColorsSorted = FALSE; m_cLSD.m_ulColorTableBits = 0; m_cLSD.m_ulColorTableNumEntries = 0; m_cLSD.m_ulBackgroundColorIndex = 0; m_cLSD.m_ulPixelAspectRatio = 0; m_cLSD.m_fPixelAspectRatio = 0.0F; m_bIsGIF89a = FALSE; m_pucGlobalColorMap = NULL; m_ulNumImages = 0; m_pImageHeaderSize = NULL; m_pCompressedBufferSize = NULL; m_pImage = NULL; m_ulCurrentImageIndex = 0; m_bNeedPacket = TRUE; m_ulState = kStateConstructed; m_bValid = TRUE; m_ulLoopCount = 1;}void CGIFCodec::TermParse(){ if (m_pSegment) { delete [] m_pSegment; m_pSegment = NULL; } ResetParse();}void CGIFCodec::TermDecompress(){ if (m_pucGlobalColorMap) { delete [] m_pucGlobalColorMap; m_pucGlobalColorMap = NULL; } if (m_pImageHeaderSize) { delete [] m_pImageHeaderSize; m_pImageHeaderSize = NULL; } if (m_pCompressedBufferSize) { delete [] m_pCompressedBufferSize; m_pCompressedBufferSize = NULL; } if (m_pImage) { delete [] m_pImage; m_pImage = NULL; } ResetDecompress();}UINT32 CGIFCodec::GetMaxNumPackets(BYTE* pBuf, UINT32 ulLen){ UINT32 ulNumPackets = 0; if (pBuf && ulLen) { BYTE* pBufLimit = pBuf + ulLen; if (pBuf[0] == 'G' && pBuf[1] == 'I' && pBuf[2] == 'F' && pBuf[3] == '8' && pBuf[5] == 'a') { // Advance past the signature pBuf += 6; // Parse the logical screen descriptor LogicalScreenDescriptor cLSD; ParseLogicalScreenDescriptor(pBuf, cLSD); pBuf += 7; // Skip the color table if (cLSD.m_bGlobalColorTablePresent == TRUE) { // Advance that number of bytes pBuf += (UINT32) (cLSD.m_ulColorTableNumEntries * 3); } // We count this as the first packet ulNumPackets++; // Loop through the GIF blocks - we know that the max number // of packets would be if each GIF block were its own packet, // so we simply need to count the GIF blocks while (pBuf < pBufLimit) { if (pBuf[0] == kImageDescriptor) { // Skip the Image Descriptor marker pBuf++; // Parse the image descriptor struct CGIFImage::ImageDescriptor cID; CGIFImage::ParseImageDescriptor(pBuf, cID); pBuf += 9; // If a local color table IS present, then skip it if (cID.m_bLocalColorTablePresent == TRUE) { pBuf += cID.m_ulLocalColorTableNumEntries * 3; } // Skip the minimum LZW code size pBuf++; // We count the image descriptor as a packet ulNumPackets++; // Now skip the LZW blocks UINT32 ulBlockSize = 0; do { // Get the block size ulBlockSize = *pBuf++; // Skip that amount of bytes pBuf += ulBlockSize; // Count this as a packet ulNumPackets++; } while (ulBlockSize); } else if (pBuf[0] == kExtension) { // Skip the extension marker and type pBuf += 2; // Count the blocks in this extension UINT32 ulBlockSize = 0; do { // Get the block size ulBlockSize = *pBuf++; // Skip that amount of bytes pBuf += ulBlockSize; // Count this as a packet ulNumPackets++; } while (ulBlockSize); } else if (pBuf[0] == kTrailer) { // We found a GIF trailer - we should be at the end of the file pBuf++; // Go ahead and count it as a packet ulNumPackets++; } else { // Sometimes extra 0 blocks get stuck in GIFs. Check for them // here - if the current byte is 0, then it's OK. If it's not, // then we've gotten lost somewhere. if (pBuf[0] == 0x00) { pBuf++; } else { // Something is wrong with the GIF file. break; } } } } } return ulNumPackets;}HX_RESULT CGIFCodec::InitParseWireFormat(BYTE *pBuffer, UINT32 ulLen){ /* Check for input error conditions */ if (pBuffer == NULL || ulLen == 0) { return HXR_INVALID_PARAMETER; } /* Check state */ if (m_ulParseState != kStateConstructed) { return HXR_UNEXPECTED; } /* Save copy of the buffer pointer and length */ m_pParseBuffer = pBuffer; m_ulParseBufferLength = ulLen; /* * We have to make a pass through the image to determine the mark points. * Will store these mark points (BYTE pointers) in cMarkList. The first * mark point is, of course, the beginning of the file. */ GList cMarkList; cMarkList.PushBack((void *) m_pParseBuffer); /* Get local copy of buffer */ BYTE *pBuf = m_pParseBuffer; BYTE *pBufLimit = pBuf + m_ulParseBufferLength; /* Check the signature */ if (pBuf[0] != 'G' || pBuf[1] != 'I' || pBuf[2] != 'F') { return HXR_INVALID_OPERATION; } pBuf += 3; /* Check the version */ if (pBuf[0] == '8' && pBuf[1] == '9' && pBuf[2] == 'a') { m_bIsGIF89a = TRUE; } else if (pBuf[0] == '8' && pBuf[1] == '7' && pBuf[2] == 'a') { m_bIsGIF89a = FALSE; } else { return HXR_INVALID_OPERATION; } pBuf += 3; /* Get the logical screen descriptor */ ParseLogicalScreenDescriptor(pBuf, m_cLSD); pBuf += 7; /* Skip the color table */ if (m_cLSD.m_bGlobalColorTablePresent == TRUE) { /* Calculate the number of bytes for the global color table */ UINT32 ulNumBytes = m_cLSD.m_ulColorTableNumEntries * 3; /* Advance that number of bytes */ pBuf += ulNumBytes; } /* * Parse the file and enter marks in the mark list. We're looking for: * a) Beginnings of GCEs and IDs (although if a ID immediately follows * a GCE, we only mark the beginning of the GCE; * b) Beginnings of LZW data for each image. */ BOOL bMarkImageDescriptor = TRUE; m_ulDelayTimeSum = 0; m_ulNumImages = 0; while (pBuf < pBufLimit) { if (pBuf[0] == kImageDescriptor) { /* * We've found an Image Descriptor (ID). If m_bMarkImageDescriptor is * FALSE, then this ID is one that immediately followed a GCE, so we * DON'T mark it. If m_bMarkImageDescriptor is TRUE, this is an * ID that was NOT preceded by a GCE - these usually happen in GIF87a's. */ if (bMarkImageDescriptor == TRUE) { cMarkList.PushBack((void *) pBuf); } else { bMarkImageDescriptor = TRUE; } /* Skip the Image Descriptor marker */ pBuf++; /* * Whether we mark it or not, we still have to parse it to find out * whether or not a local color table is present. */ CGIFImage::ImageDescriptor cID; CGIFImage::ParseImageDescriptor(pBuf, cID); pBuf += 9; // We make sure this frame's dimensions are within the dimensions // of the logical screen. If they are not, then we are probably // dealing with a corrupt GIF. That's really really bad, cause we probably // can't trust any of the data. Therefore, we will simply fail out of // parsing and rely on the app above us to do the right thing. if (cID.m_ulImageLeft + cID.m_ulImageWidth > m_cLSD.m_ulLogicalScreenWidth || cID.m_ulImageTop + cID.m_ulImageHeight > m_cLSD.m_ulLogicalScreenHeight) { return HXR_FAIL; } /* If a local color table IS present, then skip it */ if (cID.m_bLocalColorTablePresent == TRUE) { pBuf += cID.m_ulLocalColorTableNumEntries * 3; } /* Now we should be at the beginning of LZW data, so mark this pointer */ cMarkList.PushBack((void *) pBuf); /* Skip the minimum LZW code size */ UINT32 ulInitialCodeSize = *pBuf++; if (ulInitialCodeSize > 12) { // Code size can't be any bigger than 12. If we // do get one bigger than that, then we're dealing // with a corrupt file here. return HXR_FAIL; } /* Now skip the LZW blocks */ SkipBlocks(pBuf, pBufLimit); // Check to see if we went past the end of the buffer if (pBuf >= pBufLimit) { // This is really really bad if we get here. That almost certainly // means the GIF is corrupt, cause we were happily parsing LZW blocks // and went off the end of the file. In reality it probably means that // the GIF was corrupt earlier. We will simply fail here. We cannot // reliably parse any of this image. return HXR_FAIL; } /* We've just seen an image */ m_ulNumImages++; } else if (pBuf[0] == kExtension) { /* This is an extension, but what type? */ switch(pBuf[1]) { case kGraphicControlExtension: /* We've found a GCE - mark it but don't mark the ID */ cMarkList.PushBack((void *) pBuf); bMarkImageDescriptor = FALSE; pBuf += 2; UINT32 ulBlockSize; do { /* Get the block size */ ulBlockSize = *pBuf++; /* Initialize the GCE */ CGIFImage::GraphicControlExtension cGCE; if (ulBlockSize >= 4) { CGIFImage::ParseGraphicControlExtension(pBuf, cGCE); /* Add the delay time */ m_ulDelayTimeSum += cGCE.m_ulDelayTime * 10; } /* Advance by the block size */ pBuf += ulBlockSize;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -