📄 pxpngdec.cpp
字号:
// Clear the return value retVal = HXR_OK; } } else { CopyErrorString(m_pPNGStruct, "Not enough data in first packet."); } } } } } } } return retVal;}HX_RESULT PXPNGDecode::SetDecompressParam(IHXBuffer* pOutputBuffer, UINT32 ulOutputWidth, UINT32 ulOutputHeight, UINT32 ulRowStride, UINT32 ulBitsPerPixel, UINT32 ulColorFormat, BOOL bRowsInverted, BOOL bTransparentIsZero){ HX_LOG_BLOCK( "PXPNGDecode::SetDecompressParam" ); HX_RESULT retVal = HXR_FAIL; if (pOutputBuffer && ulOutputWidth && ulOutputHeight && ulRowStride && ulBitsPerPixel == 32 && ulColorFormat == HX_RGB) { if (m_pPNGStruct && m_pPNGInfo) { // We either need to be in single-buffer mode (in which // case we know we've read up through the data) or be in // progressive-read mode and gotten the InfoCallback. if (m_bSingleBufferIO || (!m_bSingleBufferIO && IsDataStateEqual(m_pPNGStruct, kDataStateInfoCallback))) { // Set the error return jump if (setjmp(m_pPNGStruct->jmpbuf)) { // If we get here, then libpng threw an error and // we longjmp'd back here. return HXR_FAIL; } // Check for full size decode if (ulOutputWidth == (UINT32) png_get_image_width(m_pPNGStruct, m_pPNGInfo) && ulOutputHeight == (UINT32) png_get_image_height(m_pPNGStruct, m_pPNGInfo)) { if (m_bSingleBufferIO) { // Set up the transforms SetReadTransforms(m_pPNGStruct, m_pPNGInfo); } // libpng by default assumes that 0 is fully transparent and 255 is // fully opaque. PXPNGDecode by default outputs alpha in the opposite // sense (0 == fully opaque and 255 == fully transparent). The following // allows the application using PXPNGDecode to switch back to libpng's // default behavior. if (bTransparentIsZero) { png_clear_invert_alpha(m_pPNGStruct); } // Save a copy of the output buffer HX_RELEASE(m_pOutputBuffer); m_pOutputBuffer = pOutputBuffer; m_pOutputBuffer->AddRef(); // Set up the row pointers retVal = SetupRowPointers(ulOutputHeight, pOutputBuffer, ulRowStride, bRowsInverted); if (SUCCEEDED(retVal) && !m_bSingleBufferIO) { // We just need to copy the number of rows and the // m_ppImageRow pointer into progressive user i/o struct PXUserIOProgressive* pUserIO = (PXUserIOProgressive*) png_get_progressive_ptr(m_pPNGStruct); if (pUserIO) { pUserIO->m_ulNumRows = ulOutputHeight; HX_VECTOR_DELETE(pUserIO->m_ppImageRow); pUserIO->m_ppImageRow = m_ppImageRow; } } } } } } return retVal;}HX_RESULT PXPNGDecode::Decompress(IHXBuffer* pBuffer){ HX_LOG_BLOCK( "PXPNGDecode::Decompress" ); HX_RESULT retVal = HXR_OK; if (m_pPNGStruct && m_ppImageRow && m_pPNGEndInfo && !m_bFinished) { // Set the error return jump if (setjmp(m_pPNGStruct->jmpbuf)) { // If we get here, then libpng threw an error and // we longjmp'd back here. return HXR_FAIL; } // Are we in single-buffer or progressive-read mode? if (m_bSingleBufferIO) { // We are in single-buffer mode. Therefore, we // can now decompress the whole image. Note that // in this mode it doesn't matter whether they // duplicate the first buffer or not. png_read_image(m_pPNGStruct, m_ppImageRow); // Now read the end info (might have text or time info) png_read_end(m_pPNGStruct, m_pPNGEndInfo); // Set the finished flag m_bFinished = TRUE; } else { // If we had deferred processing of part of the // first buffer, then we need to do that now. if (m_bDeferFirstBuffer) { // Clear the flag m_bDeferFirstBuffer = FALSE;#ifdef XXXMEH_DEBUG_LOG DEBUG_OUTF("c:\\pxpnglib.log", (s, "Decompress(): deferred first buffer call to png_process_data()\n"));#endif // Process the rest of the first buffer png_process_data(m_pPNGStruct, m_pPNGInfo, (png_bytep) m_pFirstBuffer->GetBuffer() + m_ulFirstBufferOffset, (png_size_t) m_pFirstBuffer->GetSize() - m_ulFirstBufferOffset); // Release the first buffer HX_RELEASE(m_pFirstBuffer); m_ulFirstBufferOffset = 0; } // Make sure if the first buffer is duplicated, // that we are not passing it in twice. if (!(m_bFirstDecompress && m_bDupFirstBuffer)) {#ifdef XXXMEH_DEBUG_LOG DEBUG_OUTF("c:\\pxpnglib.log", (s, "Decompress(): normal call to png_process_data()\n"));#endif png_process_data(m_pPNGStruct, m_pPNGInfo, (png_bytep) pBuffer->GetBuffer(), (png_size_t) pBuffer->GetSize()); } // Check to see if the EndCallback has been // called. If so, then we are finished. if (IsDataStateEqual(m_pPNGStruct, kDataStateEndCallback)) { m_bFinished = TRUE; } } // Clear the first decompress flag m_bFirstDecompress = FALSE; } else { retVal = HXR_UNEXPECTED; } return retVal;}HX_RESULT PXPNGDecode::GetErrorString(REF(IHXBuffer*) rpErrStr){ HX_RESULT retVal = HXR_FAIL; if (m_pPNGStruct) { PXUserError* pUserError = (PXUserError*) png_get_error_ptr(m_pPNGStruct); if (pUserError && pUserError->m_pErrorStr) { HX_RELEASE(rpErrStr); rpErrStr = pUserError->m_pErrorStr; rpErrStr->AddRef(); } } return retVal;}void PXPNGDecode::DeallocateErrorHandling(png_structp png_ptr){ if (png_ptr) { PXUserError* pUserError = (PXUserError*) png_get_error_ptr(png_ptr); if (pUserError) { HX_RELEASE(pUserError->m_pContext); HX_RELEASE(pUserError->m_pErrorStr); } HX_DELETE(pUserError); }}void PXPNGDecode::DeallocateIOHandling(png_structp png_ptr){ if (png_ptr) { if (m_bSingleBufferIO) { // Deallocate any single-buffer IO PXUserIOSingle* pUserIOSingle = (PXUserIOSingle*) png_get_io_ptr(png_ptr); if (pUserIOSingle) { HX_RELEASE(pUserIOSingle->m_pBuffer); } HX_DELETE(pUserIOSingle); } else { // Deallocate any progressive-read IO PXUserIOProgressive* pUserIOProg = (PXUserIOProgressive*) png_get_progressive_ptr(png_ptr); HX_DELETE(pUserIOProg); } }}BOOL PXPNGDecode::IsChunkPresent(IHXBuffer* pBuffer, UINT32 ulChunkType, REF(UINT32) rulOffset, REF(UINT32) rulNumBytes, REF(BOOL) rbComplete){ BOOL bRet = FALSE; if (pBuffer) { BYTE* pBufStart = pBuffer->GetBuffer(); BYTE* pBufLimit = pBuffer->GetBuffer() + pBuffer->GetSize(); BYTE* pBuf = pBufStart; if (pBuf) { UINT32 ulSig0 = (pBuf[0] << 24) | (pBuf[1] << 16) | (pBuf[2] << 8) | (pBuf[3]); UINT32 ulSig1 = (pBuf[4] << 24) | (pBuf[5] << 16) | (pBuf[6] << 8) | (pBuf[7]); if (ulSig0 == kSig0 && ulSig1 == kSig1) { // We detected a signature, so we will skip it pBuf += 8; } // Scan the chunks while (pBuf < pBufLimit) { if (pBuf + 8 <= pBufLimit) { UINT32 ulLength = (pBuf[0] << 24) | (pBuf[1] << 16) | (pBuf[2] << 8) | (pBuf[3]); UINT32 ulType = (pBuf[4] << 24) | (pBuf[5] << 16) | (pBuf[6] << 8) | (pBuf[7]); UINT32 ulTotal = 8 + ulLength + 4; if (ulType == ulChunkType) { bRet = TRUE; rulOffset = pBuf - pBufStart; if (pBuf + ulTotal <= pBufLimit) { rbComplete = TRUE; rulNumBytes = ulTotal; } else { rbComplete = FALSE; rulNumBytes = pBufLimit - pBuf; } break; } pBuf += ulTotal; } else { pBuf += 8; } } } } return bRet;}BOOL PXPNGDecode::IsCompleteChunkPresent(IHXBuffer* pBuffer, UINT32 ulChunkType){ UINT32 ulOffset = 0; UINT32 ulNumBytes = 0; BOOL bComplete = FALSE; BOOL bPresent = IsChunkPresent(pBuffer, ulChunkType, ulOffset, ulNumBytes, bComplete); return (bPresent && bComplete ? TRUE : FALSE);}BOOL PXPNGDecode::GetIHDRInfo(IHXBuffer* pBuffer, REF(UINT32) rulWidth, REF(UINT32) rulHeight){ UINT32 ulOffset = 0; UINT32 ulNumBytes = 0; BOOL bComplete = FALSE; BOOL bPresent = IsChunkPresent(pBuffer, kIHDR, ulOffset, ulNumBytes, bComplete); if (bPresent && bComplete) { BYTE* pBuf = pBuffer->GetBuffer() + ulOffset + 8; rulWidth = (pBuf[0] << 24) | (pBuf[1] << 16) | (pBuf[2] << 8) | (pBuf[3]); rulHeight = (pBuf[4] << 24) | (pBuf[5] << 16) | (pBuf[6] << 8) | (pBuf[7]); } return (bPresent && bComplete ? TRUE : FALSE);}void PXPNGDecode::SetReadTransforms(png_structp png_ptr, png_infop info){ if (png_ptr && info) { UINT32 ulColorType = (UINT32) png_get_color_type(png_ptr, info); UINT32 ulBitDepth = (UINT32) png_get_bit_depth(png_ptr, info); BOOL bBigEndian = TestBigEndian();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -