📄 gifcodec.cpp
字号:
{ return retVal; } // Add the delay time to the delay time sum m_ulDelayTimeSum += m_pImage[ulImageNum].GetDelayTime() * 10; retVal = m_pImage[ulImageNum].SetCompressedBufferSize(m_pCompressedBufferSize[ulImageNum]); if (retVal != HXR_OK) { return retVal; } pBuffer += m_pImageHeaderSize[ulImageNum]; ulImageNum++; } else if (pBuffer[1] == kApplicationExtension) { ParseApplicationExtension(pBuffer); } else { /* Skip the extension marker and type */ pBuffer += 2; /* Now skip the extension itself */ SkipBlocks(pBuffer); } break; case kTrailer: default: /* Something went wrong */ return HXR_INVALID_OPERATION; break; } /* If we've gotten all intialized all images, then we're done */ if (ulImageNum >= m_ulNumImages) { break; } } return HXR_OK;}void CGIFCodec::SkipBlocks(BYTE * &pBuffer, BYTE* pBufLimit){ // If pBufLimit is NULL, then we won't use it at all. // If pBufLimit is not NULL, then we will make sure // we don't go past the end of the buffer UINT32 ulBlockSize; do { /* Get the block size */ ulBlockSize = *pBuffer++; /* Skip that amount of bytes */ pBuffer += ulBlockSize; } while (ulBlockSize > 0 && (!pBufLimit || (pBufLimit && pBuffer < pBufLimit)));}HX_RESULT CGIFCodec::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; } /* Get the master header length */ UINT32 ulHeaderLength = UnPack32(pBuffer); pBuffer += 4; /* Get the number of images */ m_ulNumImages = UnPack32(pBuffer); pBuffer += 4; if (m_ulNumImages == 0) { return HXR_UNEXPECTED; } /* Allocate array of images */ if (m_pImage) { delete [] m_pImage; m_pImage = NULL; } m_pImage = new CGIFImage [m_ulNumImages]; if (!m_pImage) { return HXR_OUTOFMEMORY; } /* Allocate array for image header sizes */ if (m_pImageHeaderSize) { delete [] m_pImageHeaderSize; m_pImageHeaderSize = NULL; } m_pImageHeaderSize = new UINT32 [m_ulNumImages]; if (!m_pImageHeaderSize) { if (m_pImage) { delete [] m_pImage; m_pImage = NULL; } return HXR_OUTOFMEMORY; } /* Allocate array for image header sizes */ if (m_pCompressedBufferSize) { delete [] m_pCompressedBufferSize; m_pCompressedBufferSize = NULL; } m_pCompressedBufferSize = new UINT32 [m_ulNumImages]; if (!m_pCompressedBufferSize) { if (m_pImage) { delete [] m_pImage; m_pImage = NULL; } if (m_pImageHeaderSize) { delete [] m_pImageHeaderSize; m_pImageHeaderSize = NULL; } return HXR_OUTOFMEMORY; } /* Now set the compressed buffer size for each image */ HX_RESULT retVal; UINT32 i; for (i = 0; i < m_ulNumImages; i++) { /* Get the image header size */ m_pImageHeaderSize[i] = UnPack32(pBuffer); pBuffer += 4; /* Get a compressed buffer size */ m_pCompressedBufferSize[i] = UnPack32(pBuffer); pBuffer += 4; } /* Now parse the container header */ retVal = ParseContainerHeader(pBuffer); if (retVal != HXR_OK) { if (m_pImage) { delete [] m_pImage; m_pImage = NULL; } if (m_pImageHeaderSize) { delete [] m_pImageHeaderSize; m_pImageHeaderSize = NULL; } return retVal; } /* Set the current image */ m_ulCurrentImageIndex = 0; /* Set the new state */ m_ulState = kStateDecoInitialized; return HXR_OK;}HX_RESULT CGIFCodec::Decompress(BYTE *pBuffer, UINT32 ulLen, BOOL bNewImage){ /* Check for input error conditions */ if (pBuffer == NULL || ulLen == 0) { return HXR_INVALID_PARAMETER; } /* Check the state */ if (m_ulState != kStateDecoInitialized && m_ulState != kStateDecoInProgress) { return HXR_UNEXPECTED; } /* Check to see if the we lost a packet on this image */ if (m_pImage[m_ulCurrentImageIndex].GetValid() == FALSE) { /* This image was declared invalid due to a lost packet */ if (bNewImage == FALSE) { // We're still on the same image, so we can't do anything return HXR_OK; } // We've moved on to a new image, so we can begin decompressing again m_ulCurrentImageIndex++; } /* All we have to do is pass this data on to the current image */ HX_RESULT retVal = m_pImage[m_ulCurrentImageIndex].Decompress(pBuffer, ulLen); if (retVal != HXR_OK) { return retVal; } /* Set the state */ m_ulState = kStateDecoInProgress; /* Are we finished with this image? */ if (m_pImage[m_ulCurrentImageIndex].Finished() == TRUE) { /* Move on to the next image */ m_ulCurrentImageIndex++; /* If we've done all images, then we're done */ if (m_ulCurrentImageIndex >= m_ulNumImages) { m_ulState = kStateDecoFinished; } } return HXR_OK;}INT32 CGIFCodec::ComputeStartingImageIndex(INT32 lCurIndex, INT32 lDesiredIndex){ // Does the buffer currently hold any image now? INT32 lStartIndex; INT32 lBaseIndex; if (lCurIndex == -1 || lCurIndex > lDesiredIndex) { // The buffer doesn't have anything in it now, so we must build // from the last full screen image before or equal to ulImgIndex // all the way back to 0. lBaseIndex = 0; } else { // The buffer currently has a valid image in it, so we only need // to go back to the first full screen image greater than lCurIndex. lBaseIndex = lCurIndex + 1; } // Find the index of the first image we need to do for (lStartIndex = lDesiredIndex; lStartIndex >= lBaseIndex; lStartIndex--) { if (m_pImage[lStartIndex].GetImageWidth() == m_cLSD.m_ulLogicalScreenWidth && m_pImage[lStartIndex].GetImageHeight() == m_cLSD.m_ulLogicalScreenHeight) { break; } } if (lStartIndex < lBaseIndex) { lStartIndex = 0; } return lStartIndex;}HX_RESULT CGIFCodec::GetIndexImage(INT32 lCurIndex, UINT32 ulImgIndex, BYTE *pBuffer, UINT32 ulWidth, UINT32 ulHeight, UINT32 ulPadWidth, BOOL bRowsInverted){ // Check for input error if (lCurIndex < -1 || lCurIndex >= (INT32) m_ulNumImages || ulImgIndex >= m_ulNumImages || pBuffer == NULL || ulWidth == 0 || ulHeight == 0 || ulPadWidth == 0) { return HXR_INVALID_PARAMETER; } // Since frames of a GIF can be dependent upon prior frames, we need to // determine which frame we need to go back to INT32 lStartIndex = ComputeStartingImageIndex(lCurIndex, (INT32) ulImgIndex); // Now do the images from lStartIndex to ulImgIndex INT32 i; for (i = lStartIndex; i <= (INT32) ulImgIndex; i++) { HX_RESULT retVal = m_pImage[i].GetIndexImage(pBuffer, ulWidth, ulHeight, ulPadWidth, bRowsInverted); if (retVal != HXR_OK) { return retVal; } } return HXR_OK;}HX_RESULT CGIFCodec::GetRGBImage(INT32 lCurIndex, UINT32 ulImgIndex, BYTE *pBuffer, UINT32 ulWidth, UINT32 ulHeight, UINT32 ulPadWidth, UINT32 ulBytesPerPixel, BOOL bRowsInverted, BOOL bRGBOrdering, BYTE ucBackRed, BYTE ucBackGreen, BYTE ucBackBlue, BYTE ucBackAlpha){ // Check for input error if (lCurIndex < -1 || lCurIndex >= (INT32) m_ulNumImages || ulImgIndex >= m_ulNumImages || pBuffer == NULL || ulWidth == 0 || ulHeight == 0 || ulPadWidth == 0 || ulBytesPerPixel == 0) { return HXR_INVALID_PARAMETER; } // Since frames of a GIF can be dependent upon prior frames, we need to // determine which frame we need to go back to INT32 lStartIndex = ComputeStartingImageIndex(lCurIndex, (INT32) ulImgIndex); // Now do the images from lStartIndex to ulImgIndex INT32 i; for (i = lStartIndex; i <= (INT32) ulImgIndex; i++) { HX_RESULT retVal = m_pImage[i].GetRGBImage(pBuffer, ulWidth, ulHeight, ulPadWidth, ulBytesPerPixel, bRowsInverted, bRGBOrdering, ucBackRed, ucBackGreen, ucBackBlue, ucBackAlpha); if (retVal != HXR_OK) { return retVal; } } return HXR_OK;}HX_RESULT CGIFCodec::GetRGBImageEx(INT32 lCurIndex, UINT32 ulImgIndex, BYTE *pBuffer, 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 (lCurIndex >= -1 && lCurIndex < (INT32) m_ulNumImages && ulImgIndex < m_ulNumImages && pBuffer && ulWidth && ulHeight && ulPadWidth && ulBytesPerPixel) { // Since frames of a GIF can be dependent upon prior frames, we need to // determine which frame we need to go back to INT32 lStartIndex = ComputeStartingImageIndex(lCurIndex, (INT32) ulImgIndex); // Now do the images from lStartIndex to ulImgIndex INT32 i = 0; for (i = lStartIndex; i <= (INT32) ulImgIndex; i++) { retVal = m_pImage[i].GetRGBImageEx(pBuffer, ulWidth, ulHeight, ulPadWidth, ulBytesPerPixel, bRowsInverted, bRGBOrdering, ulBgColor, bMediaOpacity, ulMediaOpacity, bChromaKey, ulChromaKey, ulChromaKeyTol, ulChromaKeyOpacity); if (FAILED(retVal)) { break; } } } else { retVal = HXR_INVALID_PARAMETER; } return retVal;}HX_RESULT CGIFCodec::GetRGB32(UINT32 ulImageNum, BYTE *pBuffer, UINT32 ulRowStride, BOOL bRowsInverted){ HX_RESULT retVal = HXR_OK; if (pBuffer) { if (ulImageNum < m_ulNumImages && m_pImage) { retVal = m_pImage[ulImageNum].GetRGB32(pBuffer, ulRowStride, bRowsInverted); } else { retVal = HXR_UNEXPECTED; } } else { retVal = HXR_INVALID_PARAMETER; } return retVal;}void CGIFCodec::PacketLost(){ // Clear the valid flag for the current image m_pImage[m_ulCurrentImageIndex].SetValid(FALSE); // Set the finished flag for this image m_pImage[m_ulCurrentImageIndex].SetFinished();}BOOL CGIFCodec::LocalColorMapsPresent(){ UINT32 i; for (i = 0; i < m_ulNumImages; i++) { if (m_pImage[i].LocalColorMapPresent()) { return TRUE; } } return FALSE;}void CGIFCodec::ParseApplicationExtension(BYTE * &pBuf){ pBuf += 2; // skip the extension introducer and the application extension label // The next block should always be 11 bytes - 8 bytes for application identifier // and 3 bytes for the application authentication code. If it's not then just // skip these blocks if (pBuf[0] == 11) { // Now we check to see if this is a NETSCAPE2.0 application extension. // If it is, then it contains the loop count for the animation. if (!strncmp((const char *) pBuf + 1, "NETSCAPE2.0", 11)) { // Yep, we've got a NETSCAPE2.0 application extension, // so attempt to extract the loop count if (pBuf[12] == 0x03 && pBuf[13] == 0x01 && pBuf[16] == 0x00) { UINT32 ulCount = (pBuf[15] << 8) | pBuf[14]; if (ulCount == 0) { m_ulLoopCount = 0; } else { m_ulLoopCount = ulCount + 1; } pBuf += 17; } else { SkipBlocks(pBuf); } } else { SkipBlocks(pBuf); } } else { SkipBlocks(pBuf); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -