CodecError CCodec_DXT5::Decompress(CCodecBuffer& bufferIn, CCodecBuffer& bufferOut, Codec_Feedback_Proc pFeedbackProc, CMP_DWORD_PTR pUser1, CMP_DWORD_PTR pUser2) { assert(bufferIn.GetWidth() == bufferOut.GetWidth()); assert(bufferIn.GetHeight() == bufferOut.GetHeight()); if(bufferIn.GetWidth() != bufferOut.GetWidth() || bufferIn.GetHeight() != bufferOut.GetHeight()) return CE_Unknown; const CMP_DWORD dwBlocksX = ((bufferIn.GetWidth() + 3) >> 2); const CMP_DWORD dwBlocksY = ((bufferIn.GetHeight() + 3) >> 2); const CMP_DWORD dwBlocksXY = dwBlocksX*dwBlocksY; bool bUseFixed = (!bufferOut.IsFloat() && bufferOut.GetChannelDepth() == 8 && !m_bUseFloat); for(CMP_DWORD j = 0; j < dwBlocksY; j++) { for(CMP_DWORD i = 0; i < dwBlocksX; i++) { CMP_DWORD compressedBlock[4]; bufferIn.ReadBlock(i*4, j*4, compressedBlock, 4); if(bUseFixed) { CMP_BYTE destBlock[BLOCK_SIZE_4X4X4]; DecompressRGBABlock(destBlock, compressedBlock); bufferOut.WriteBlockRGBA(i*4, j*4, 4, 4, destBlock); } else { float destBlock[BLOCK_SIZE_4X4X4]; DecompressRGBABlock(destBlock, compressedBlock); bufferOut.WriteBlockRGBA(i*4, j*4, 4, 4, destBlock); } } if (pFeedbackProc) { float fProgress = 100.f * (j * dwBlocksX) / dwBlocksXY; if (pFeedbackProc(fProgress, pUser1, pUser2)) { return CE_Aborted; } } } return CE_OK; }
CodecError CCodec_ATC_RGBA_Interpolated::Decompress(CCodecBuffer& bufferIn, CCodecBuffer& bufferOut, Codec_Feedback_Proc pFeedbackProc, CMP_DWORD_PTR pUser1, CMP_DWORD_PTR pUser2) { assert(bufferIn.GetWidth() == bufferOut.GetWidth()); assert(bufferIn.GetHeight() == bufferOut.GetHeight()); if(bufferIn.GetWidth() != bufferOut.GetWidth() || bufferIn.GetHeight() != bufferOut.GetHeight()) return CE_Unknown; const CMP_DWORD dwBlocksX = ((bufferIn.GetWidth() + 3) >> 2); const CMP_DWORD dwBlocksY = ((bufferIn.GetHeight() + 3) >> 2); const CMP_DWORD dwBlocksXY = dwBlocksX*dwBlocksY; CMP_DWORD compressedBlock[4]; CMP_BYTE destBlock[BLOCK_SIZE_4X4X4]; for(CMP_DWORD j = 0; j < dwBlocksY; j++) { for(CMP_DWORD i = 0; i < dwBlocksX; i++) { bufferIn.ReadBlock(i*4, j*4, compressedBlock, 4); DecompressRGBABlock_InterpolatedAlpha(destBlock, compressedBlock); bufferOut.WriteBlockRGBA(i*4, j*4, 4, 4, destBlock); } if (pFeedbackProc) { float fProgress = 100.f * (j * dwBlocksX) / dwBlocksXY; if (pFeedbackProc(fProgress, pUser1, pUser2)) { return CE_Aborted; } } } return CE_OK; }
CodecError CCodec_GT::Decompress(CCodecBuffer& bufferIn, CCodecBuffer& bufferOut, Codec_Feedback_Proc pFeedbackProc, DWORD_PTR pUser1, DWORD_PTR pUser2) { assert(bufferIn.GetWidth() == bufferOut.GetWidth()); assert(bufferIn.GetHeight() == bufferOut.GetHeight()); CodecError err = InitializeGTLibrary(); if (err != CE_OK) return err; if(bufferIn.GetWidth() != bufferOut.GetWidth() || bufferIn.GetHeight() != bufferOut.GetHeight()) return CE_Unknown; const CMP_DWORD dwBlocksX = ((bufferIn.GetWidth() + 3) >> 2); const CMP_DWORD dwBlocksY = ((bufferIn.GetHeight() + 3) >> 2); const CMP_DWORD dwBlocksXY = dwBlocksX*dwBlocksY; for(CMP_DWORD j = 0; j < dwBlocksY; j++) { for(CMP_DWORD i = 0; i < dwBlocksX; i++) { union FBLOCKS { BYTE decodedBlock[16][4]; BYTE destBlock[BLOCK_SIZE_4X4X4]; } DecData; union BBLOCKS { CMP_DWORD compressedBlock[4]; BYTE out[16]; BYTE in[16]; } CompData; CMP_BYTE destBlock[BLOCK_SIZE_4X4X4]; bufferIn.ReadBlock(i*4, j*4, CompData.compressedBlock, 4); // Encode to the appropriate location in the compressed image m_decoder->DecompressBlock(DecData.decodedBlock,CompData.in); // Create the block for decoding int srcIndex = 0; for(int row=0; row < BLOCK_SIZE_4; row++) { for(int col=0; col<BLOCK_SIZE_4; col++) { destBlock[srcIndex] = (CMP_BYTE)DecData.decodedBlock[row*BLOCK_SIZE_4+col][BC_COMP_RED]; destBlock[srcIndex+1] = (CMP_BYTE)DecData.decodedBlock[row*BLOCK_SIZE_4+col][BC_COMP_GREEN]; destBlock[srcIndex+2] = (CMP_BYTE)DecData.decodedBlock[row*BLOCK_SIZE_4+col][BC_COMP_BLUE]; destBlock[srcIndex+3] = (CMP_BYTE)DecData.decodedBlock[row*BLOCK_SIZE_4+col][BC_COMP_ALPHA]; srcIndex+=4; } } bufferOut.WriteBlockRGBA(i*4, j*4, 4, 4, destBlock); } if (pFeedbackProc) { float fProgress = 100.f * (j * dwBlocksX) / dwBlocksXY; if (pFeedbackProc(fProgress, pUser1, pUser2)) { #ifdef GT_COMPDEBUGGER g_CompClient.disconnect(); #endif return CE_Aborted; } } } return CE_OK; }
// notes: // Slow CPU based decompression : Should look into also using HW based decompression with this interface // CodecError CCodec_ASTC::Decompress(CCodecBuffer& bufferIn, CCodecBuffer& bufferOut, Codec_Feedback_Proc pFeedbackProc, CMP_DWORD_PTR pUser1, CMP_DWORD_PTR pUser2) { m_xdim = bufferIn.GetBlockWidth(); m_ydim = bufferIn.GetBlockHeight(); m_zdim = 1; CodecError err = InitializeASTCLibrary(); if (err != CE_OK) return err; // Our Compressed data Blocks are always 128 bit long (4x4 blocks) const CMP_DWORD imageWidth = bufferIn.GetWidth(); const CMP_DWORD imageHeight = bufferIn.GetHeight(); const CMP_DWORD imageDepth = 1; const BYTE bitness = 8; const CMP_DWORD CompBlockX = bufferIn.GetBlockWidth(); const CMP_DWORD CompBlockY = bufferIn.GetBlockHeight(); CMP_BYTE Block_Width = bufferIn.GetBlockWidth(); CMP_BYTE Block_Height = bufferIn.GetBlockHeight(); const CMP_DWORD dwBlocksX = ((bufferIn.GetWidth() + (CompBlockX - 1)) / CompBlockX); const CMP_DWORD dwBlocksY = ((bufferIn.GetHeight()+ (CompBlockY - 1)) / CompBlockY); const CMP_DWORD dwBlocksZ = 1; const CMP_DWORD dwBufferInDepth = 1; // Override the current input buffer Pitch size (Since it will be set according to the Compressed Block Sizes // and not to the Compressed Codec data which is for ASTC 16 Bytes per block x Number of blocks per row bufferIn.SetPitch(16 * dwBlocksX); // Output data size Pitch CMP_DWORD dwPitch = bufferOut.GetPitch(); // Output Buffer BYTE *pDataOut = bufferOut.GetData(); const CMP_DWORD dwBlocksXY = dwBlocksX*dwBlocksY; for(CMP_DWORD cmpRowY = 0; cmpRowY < dwBlocksY; cmpRowY++) // Compressed images row = height { for(CMP_DWORD cmpColX = 0; cmpColX < dwBlocksX; cmpColX++) // Compressed images Col = width { union FBLOCKS { float decodedBlock[144][4]; // max 12x12 block size float destBlock[576]; // max 12x12x4 } DecData; union BBLOCKS { CMP_DWORD compressedBlock[4]; BYTE out[16]; BYTE in[16]; } CompData; bufferIn.ReadBlock(cmpColX*4, cmpRowY*4, CompData.compressedBlock, 4); // Encode to the appropriate location in the compressed image m_decoder->DecompressBlock(Block_Width, Block_Height, bitness, DecData.decodedBlock,CompData.in); // Now that we have a decoded block lets copy that data over to the target image buffer CMP_DWORD outCol = cmpColX*Block_Width; CMP_DWORD outRow = cmpRowY*Block_Height; CMP_DWORD outImgRow = outRow; CMP_DWORD outImgCol = outCol; for (int row = 0; row < Block_Height; row++) { CMP_DWORD nextRowCol = (outRow+row)*dwPitch + (outCol * 4); CMP_BYTE* pData = (CMP_BYTE*)(pDataOut + nextRowCol); if ((outImgRow + row) < imageHeight) { outImgCol = outCol; for (int col = 0; col < Block_Width; col++) { CMP_DWORD w = outImgCol + col; if (w < imageWidth) { int index = row*Block_Width + col; *pData++ = (CMP_BYTE)DecData.decodedBlock[index][BC_COMP_RED]; *pData++ = (CMP_BYTE)DecData.decodedBlock[index][BC_COMP_GREEN]; *pData++ = (CMP_BYTE)DecData.decodedBlock[index][BC_COMP_BLUE]; *pData++ = (CMP_BYTE)DecData.decodedBlock[index][BC_COMP_ALPHA]; } else break; } } } } if (pFeedbackProc) { float fProgress = 100.f * (cmpRowY * dwBlocksX) / dwBlocksXY; if (pFeedbackProc(fProgress, pUser1, pUser2)) { return CE_Aborted; } } } return CE_OK; }