//////////////////////////////////////////////////////// // Encode buffer of given size using bit plane coding. // A buffer contains bufferLen UINT32 values, thus, bufferSize bits per bit plane. // Following coding scheme is used: // Buffer ::= <nPlanes>(5 bits) foreach(plane i): Plane[i] // Plane[i] ::= [ Sig1 | Sig2 ] [DWORD alignment] refBits // Sig1 ::= 1 <codeLen>(15 bits) codedSigAndSignBits // Sig2 ::= 0 <sigLen>(15 bits) [Sign1 | Sign2 ] [DWORD alignment] sigBits // Sign1 ::= 1 <codeLen>(15 bits) codedSignBits // Sign2 ::= 0 <signLen>(15 bits) [DWORD alignment] signBits void CEncoder::CMacroBlock::BitplaneEncode() { UINT8 nPlanes; UINT32 sigLen, codeLen = 0, wordPos, refLen, signLen; UINT32 sigBits[BufferLen] = { 0 }; UINT32 refBits[BufferLen] = { 0 }; UINT32 signBits[BufferLen] = { 0 }; UINT32 planeMask; UINT32 bufferSize = m_header.rbh.bufferSize; ASSERT(bufferSize <= BufferSize); bool useRL; #ifdef TRACE //printf("which thread: %d\n", omp_get_thread_num()); #endif // clear significance vector for (UINT32 k=0; k < bufferSize; k++) { m_sigFlagVector[k] = false; } m_sigFlagVector[bufferSize] = true; // sentinel // clear output buffer for (UINT32 k=0; k < bufferSize; k++) { m_codeBuffer[k] = 0; } m_codePos = 0; // compute number of bit planes and split buffer into separate bit planes nPlanes = NumberOfBitplanes(); // write number of bit planes to m_codeBuffer // <nPlanes> SetValueBlock(m_codeBuffer, 0, nPlanes, MaxBitPlanesLog); m_codePos += MaxBitPlanesLog; // loop through all bit planes if (nPlanes == 0) nPlanes = MaxBitPlanes + 1; planeMask = 1 << (nPlanes - 1); for (int plane = nPlanes - 1; plane >= 0; plane--) { // clear significant bitset for (UINT32 k=0; k < BufferLen; k++) { sigBits[k] = 0; } // split bitplane in significant bitset and refinement bitset sigLen = DecomposeBitplane(bufferSize, planeMask, m_codePos + RLblockSizeLen + 1, sigBits, refBits, signBits, signLen, codeLen); if (sigLen > 0 && codeLen <= MaxCodeLen && codeLen < AlignWordPos(sigLen) + AlignWordPos(signLen) + 2*RLblockSizeLen) { // set RL code bit // <1><codeLen> SetBit(m_codeBuffer, m_codePos++); // write length codeLen to m_codeBuffer SetValueBlock(m_codeBuffer, m_codePos, codeLen, RLblockSizeLen); m_codePos += RLblockSizeLen + codeLen; } else { #ifdef TRACE //printf("new\n"); //for (UINT32 i=0; i < bufferSize; i++) { // printf("%s", (GetBit(sigBits, i)) ? "1" : "_"); // if (i%120 == 119) printf("\n"); //} //printf("\n"); #endif // TRACE // run-length coding wasn't efficient enough // we don't use RL coding for sigBits // <0><sigLen> ClearBit(m_codeBuffer, m_codePos++); // write length sigLen to m_codeBuffer ASSERT(sigLen <= MaxCodeLen); SetValueBlock(m_codeBuffer, m_codePos, sigLen, RLblockSizeLen); m_codePos += RLblockSizeLen; if (m_encoder->m_favorSpeed || signLen == 0) { useRL = false; } else { // overwrite m_codeBuffer useRL = true; // run-length encode m_sign and append them to the m_codeBuffer codeLen = RLESigns(m_codePos + RLblockSizeLen + 1, signBits, signLen); } if (useRL && codeLen <= MaxCodeLen && codeLen < signLen) { // RL encoding of m_sign was efficient // <1><codeLen><codedSignBits>_ // write RL code bit SetBit(m_codeBuffer, m_codePos++); // write codeLen to m_codeBuffer SetValueBlock(m_codeBuffer, m_codePos, codeLen, RLblockSizeLen); // compute position of sigBits wordPos = NumberOfWords(m_codePos + RLblockSizeLen + codeLen); ASSERT(0 <= wordPos && wordPos < CodeBufferLen); } else { // RL encoding of signBits wasn't efficient // <0><signLen>_<signBits>_ // clear RL code bit ClearBit(m_codeBuffer, m_codePos++); // write signLen to m_codeBuffer ASSERT(signLen <= MaxCodeLen); SetValueBlock(m_codeBuffer, m_codePos, signLen, RLblockSizeLen); // write signBits to m_codeBuffer wordPos = NumberOfWords(m_codePos + RLblockSizeLen); ASSERT(0 <= wordPos && wordPos < CodeBufferLen); codeLen = NumberOfWords(signLen); for (UINT32 k=0; k < codeLen; k++) { m_codeBuffer[wordPos++] = signBits[k]; } } // write sigBits // <sigBits>_ ASSERT(0 <= wordPos && wordPos < CodeBufferLen); refLen = NumberOfWords(sigLen); for (UINT32 k=0; k < refLen; k++) { m_codeBuffer[wordPos++] = sigBits[k]; } m_codePos = wordPos << WordWidthLog; } // append refinement bitset (aligned to word boundary) // _<refBits> wordPos = NumberOfWords(m_codePos); ASSERT(0 <= wordPos && wordPos < CodeBufferLen); refLen = NumberOfWords(bufferSize - sigLen); for (UINT32 k=0; k < refLen; k++) { m_codeBuffer[wordPos++] = refBits[k]; } m_codePos = wordPos << WordWidthLog; planeMask >>= 1; } ASSERT(0 <= m_codePos && m_codePos <= CodeBufferBitLen); }
///////////////////////////////////////////////////////////////////// // Write encoded macro block into stream. // It might throw an IOException. void CEncoder::WriteMacroBlock(CMacroBlock* block) { ASSERT(block); #ifdef __PGFROISUPPORT__ ROIBlockHeader h = block->m_header; #endif UINT16 wordLen = UINT16(NumberOfWords(block->m_codePos)); ASSERT(wordLen <= CodeBufferLen); int count = sizeof(UINT16); #ifdef TRACE //UINT32 filePos = (UINT32)m_stream->GetPos(); //printf("EncodeBuffer: %d\n", filePos); #endif #ifdef PGF_USE_BIG_ENDIAN // write wordLen UINT16 wl = __VAL(wordLen); m_stream->Write(&count, &wl); ASSERT(count == sizeof(UINT16)); #ifdef __PGFROISUPPORT__ // write ROIBlockHeader if (m_roi) { count = sizeof(ROIBlockHeader); h.val = __VAL(h.val); m_stream->Write(&count, &h.val); ASSERT(count == sizeof(ROIBlockHeader)); } #endif // __PGFROISUPPORT__ // convert data for (int i=0; i < wordLen; i++) { block->m_codeBuffer[i] = __VAL(block->m_codeBuffer[i]); } #else // write wordLen m_stream->Write(&count, &wordLen); ASSERT(count == sizeof(UINT16)); #ifdef __PGFROISUPPORT__ // write ROIBlockHeader if (m_roi) { count = sizeof(ROIBlockHeader); m_stream->Write(&count, &h.val); ASSERT(count == sizeof(ROIBlockHeader)); } #endif // __PGFROISUPPORT__ #endif // PGF_USE_BIG_ENDIAN // write encoded data into stream count = wordLen*WordBytes; m_stream->Write(&count, block->m_codeBuffer); // store levelLength if (m_levelLength) { // store level length // EncodeBuffer has been called after m_lastLevelIndex has been updated ASSERT(m_currLevelIndex < m_nLevels); m_levelLength[m_currLevelIndex] += (UINT32)ComputeBufferLength(); m_currLevelIndex = block->m_lastLevelIndex + 1; } // prepare for next buffer SetBufferStartPos(); // reset values block->m_valuePos = 0; block->m_maxAbsValue = 0; }