📄 pxpngdec.cpp
字号:
// We handle transformations on a per-color-type basis if (ulColorType == PNG_COLOR_TYPE_GRAY) { // All bit depths (1, 2, 4, 8, 16) are allowed for PNG_COLOR_TYPE_GRAY, so // if it's less than 8bpp, we need to expand to 8bpp if (ulBitDepth < 8 || png_get_valid(png_ptr, info, PNG_INFO_tRNS)) { png_set_expand(png_ptr); } // If it's 16bpp, we need to go down to 8bpp if (ulBitDepth > 8) { png_set_strip_16(png_ptr); } // Convert gray to RGB png_set_gray_to_rgb(png_ptr); // If we have a tRNS chunk, then we will have expanded it // to a full alpha channel in png_set_expand(), so we // have to check so we can deal with alpha if (png_get_valid(png_ptr, info, PNG_INFO_tRNS)) { // If we are big-endan we want ARGB, if we are little endian, we need BGRA. // However, we don't need to worry about RGB vs. BGR since we are converting // from gray so R = G = B. if (bBigEndian) { png_set_swap_alpha(png_ptr); } // PNG thinks that A = 0 is fully transparent and A = 255 is fully // opaque. We want the opposite (A = 0 is fully opaque and A = 255 is // fully transparent). So we call png_set_invert_alpha(). png_set_invert_alpha(png_ptr); } else { // We DON'T have a tRNS chunk, so we must fill the alpha // byte with 0, either before or after the RGB triplet. png_set_filler(png_ptr, 0, (bBigEndian ? PNG_FILLER_BEFORE : PNG_FILLER_AFTER)); } } else if (ulColorType == PNG_COLOR_TYPE_GRAY_ALPHA) { // Only bit depths 8 and 16 are allowed, so we need to just chop 16 down to 8 if (ulBitDepth > 8) { png_set_strip_16(png_ptr); } // Convert gray to RGB png_set_gray_to_rgb(png_ptr); // If we are big-endan we want ARGB, if we are little endian, we need BGRA. // However, we don't need to worry about RGB vs. BGR since we are converting // from gray so R = G = B. if (bBigEndian) { png_set_swap_alpha(png_ptr); } // PNG thinks that A = 0 is fully transparent and A = 255 is fully // opaque. We want the opposite (A = 0 is fully opaque and A = 255 is // fully transparent). So we call png_set_invert_alpha(). png_set_invert_alpha(png_ptr); } else if (ulColorType == PNG_COLOR_TYPE_PALETTE) { // Convert palettized to RGB png_set_expand(png_ptr); // If we are not big endian we need BGR instead of RGB if (!bBigEndian) { png_set_bgr(png_ptr); } // If we DID expand a tRNS chunk to a full alpha channel, then // we need to set how we read alpha. If we did NOT, then we need to // set the filler value. if (png_get_valid(png_ptr, info, PNG_INFO_tRNS)) { // If we are big-endan we want ARGB, if we are little endian, we need BGRA. if (bBigEndian) { png_set_swap_alpha(png_ptr); } // PNG thinks that A = 0 is fully transparent and A = 255 is fully // opaque. We want the opposite (A = 0 is fully opaque and A = 255 is // fully transparent). So we call png_set_invert_alpha(). png_set_invert_alpha(png_ptr); } else { png_set_filler(png_ptr, 0, (bBigEndian ? PNG_FILLER_BEFORE : PNG_FILLER_AFTER)); } } else if (ulColorType == PNG_COLOR_TYPE_RGB) { // Only bit depths 8 and 16 are allowed, so we need to just chop 16 down to 8 if (ulBitDepth > 8) { png_set_strip_16(png_ptr); } // Set BGR vs. RGB if (!bBigEndian) { png_set_bgr(png_ptr); } // If there is a tRNS chunk, we need to expand to full alpha channel if (png_get_valid(png_ptr, info, PNG_INFO_tRNS)) { // Expand tRNS chunk to full alpha channel png_set_expand(png_ptr); // If we are big-endan we want ARGB, if we are little endian, we need BGRA. if (bBigEndian) { png_set_swap_alpha(png_ptr); } // PNG thinks that A = 0 is fully transparent and A = 255 is fully // opaque. We want the opposite (A = 0 is fully opaque and A = 255 is // fully transparent). So we call png_set_invert_alpha(). png_set_invert_alpha(png_ptr); } else { // There will not be an alpha channel, so we need to set the filler png_set_filler(png_ptr, 0, (bBigEndian ? PNG_FILLER_BEFORE : PNG_FILLER_AFTER)); } } else if (ulColorType == PNG_COLOR_TYPE_RGB_ALPHA) { // Only bit depths 8 and 16 are allowed, so we need to just chop 16 down to 8 if (ulBitDepth > 8) { png_set_strip_16(png_ptr); } // Now we know we have 32bpp with alpha, we we just need // to get the ordering right. Right now, we will get RGBA. if (bBigEndian) { // Get ARGB instead of RGBA png_set_swap_alpha(png_ptr); } else { // Get BGRA instead of RGBA png_set_bgr(png_ptr); } // PNG thinks that A = 0 is fully transparent and A = 255 is fully // opaque. We want the opposite (A = 0 is fully opaque and A = 255 is // fully transparent). So we call png_set_invert_alpha(). png_set_invert_alpha(png_ptr); } // Tell libpng to handle the interlacing details INT32 lNumPasses = png_set_interlace_handling(png_ptr); // Update the info struct png_read_update_info(png_ptr, info); }}HX_RESULT PXPNGDecode::SetupRowPointers(UINT32 ulHeight, IHXBuffer* pBuffer, UINT32 ulRowStride, BOOL bRowsInverted){ HX_RESULT retVal = HXR_FAIL; if (ulHeight) { HX_VECTOR_DELETE(m_ppImageRow); m_ppImageRow = new BYTE* [ulHeight]; if (m_ppImageRow) { for (UINT32 i = 0; i < ulHeight; i++) { UINT32 ulRow = (bRowsInverted ? ulHeight - 1 - i : i); m_ppImageRow[i] = pBuffer->GetBuffer() + ulRow * ulRowStride; } retVal = HXR_OK; } } return retVal;}void PXPNGDecode::SingleBufferRead(png_structp png_ptr, png_bytep data, png_size_t length){ HX_RESULT retVal = HXR_FAIL; if (png_ptr && data && length) { PXUserIOSingle* pUserIO = (PXUserIOSingle*) png_get_io_ptr(png_ptr); if (pUserIO && pUserIO->m_pBuffer) { UINT32 ulNumBytes = (UINT32) length; if (pUserIO->m_ulOffset + ulNumBytes > pUserIO->m_pBuffer->GetSize()) { ulNumBytes = pUserIO->m_pBuffer->GetSize() - pUserIO->m_ulOffset; } // Copy the data memcpy(data, /* Flawfinder: ignore */ pUserIO->m_pBuffer->GetBuffer() + pUserIO->m_ulOffset, ulNumBytes); // Update the offset pUserIO->m_ulOffset += ulNumBytes; // Clear the error return retVal = HXR_OK; } } if (FAILED(retVal)) { png_error(png_ptr, "read Error"); }}void PXPNGDecode::HandleError(png_structp png_ptr, png_const_charp message){ // Copy the error string into our custom error struct CopyErrorString(png_ptr, message); // longjmp back to the error location longjmp(png_ptr->jmpbuf, 1);}void PXPNGDecode::HandleWarning(png_structp png_ptr, png_const_charp message){ // Copy the error string into our custom error struct CopyErrorString(png_ptr, message);}void PXPNGDecode::CopyErrorString(png_structp png_ptr, png_const_charp message){ if (png_ptr && message) { PXUserError* pUserError = (PXUserError*) png_get_error_ptr(png_ptr); if (pUserError) { IUnknown* pContext = pUserError->m_pContext; if (pContext) { IHXCommonClassFactory* pFactory = NULL; HX_RESULT retVal = pContext->QueryInterface(IID_IHXCommonClassFactory, (void**) &pFactory); if (SUCCEEDED(retVal)) { IHXBuffer* pBuffer = NULL; retVal = pFactory->CreateInstance(CLSID_IHXBuffer, (void**) &pBuffer); if (SUCCEEDED(retVal)) { retVal = pBuffer->Set((const BYTE*) message, strlen(message) + 1); if (SUCCEEDED(retVal)) { HX_RELEASE(pUserError->m_pErrorStr); pUserError->m_pErrorStr = pBuffer; pUserError->m_pErrorStr->AddRef(); } } HX_RELEASE(pBuffer); } HX_RELEASE(pFactory); } } }}void PXPNGDecode::InfoCallback(png_structp png_ptr, png_infop info){ // Set the data state SetProgressiveDataState(png_ptr, kDataStateInfoCallback); // Set up the read transforms SetReadTransforms(png_ptr, info);#ifdef XXXMEH_DEBUG_LOG DEBUG_OUTF("c:\\pxpnglib.log", (s, "InfoCallback(0x%08X, 0x%08X)\n", png_ptr, info));#endif}void PXPNGDecode::RowCallback(png_structp png_ptr, png_bytep new_row, png_uint_32 row_num, int pass){ // Set the data state SetProgressiveDataState(png_ptr, kDataStateRowCallback); // We just need to combine the old row with the new row (if // interlaced) or copy the new row (if not interlaced) PXUserIOProgressive* pUserIO = (PXUserIOProgressive*) png_get_progressive_ptr(png_ptr); if (pUserIO && pUserIO->m_ppImageRow && row_num < pUserIO->m_ulNumRows) { png_progressive_combine_row(png_ptr, pUserIO->m_ppImageRow[row_num], new_row); }#ifdef XXXMEH_DEBUG_LOG DEBUG_OUTF("c:\\pxpnglib.log", (s, "RowCallback(0x%08X, %lu, %lu)\n", new_row, row_num, pass));#endif}void PXPNGDecode::EndCallback(png_structp png_ptr, png_infop info){ // Set the data state SetProgressiveDataState(png_ptr, kDataStateEndCallback);#ifdef XXXMEH_DEBUG_LOG DEBUG_OUTF("c:\\pxpnglib.log", (s, "EndCallback(0x%08X, 0x%08X)\n", png_ptr, info));#endif}void PXPNGDecode::SetProgressiveAppState(png_structp png_ptr, UINT32 ulState){ if (png_ptr) { PXUserIOProgressive* pUserIO = (PXUserIOProgressive*) png_get_progressive_ptr(png_ptr); if (pUserIO) { pUserIO->m_ulAppState = ulState; } }}void PXPNGDecode::SetProgressiveDataState(png_structp png_ptr, UINT32 ulState){ if (png_ptr) { PXUserIOProgressive* pUserIO = (PXUserIOProgressive*) png_get_progressive_ptr(png_ptr); if (pUserIO) { pUserIO->m_ulDataState = ulState; } }}BOOL PXPNGDecode::IsDataStateEqual(png_structp png_ptr, UINT32 ulState){ BOOL bRet = FALSE; if (png_ptr) { PXUserIOProgressive* pUserIO = (PXUserIOProgressive*) png_get_progressive_ptr(png_ptr); if (pUserIO && pUserIO->m_ulDataState == ulState) { bRet = TRUE; } } return bRet;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -