00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00028
00029 #include "Encoder.h"
00030 #ifdef TRACE
00031 #include <stdio.h>
00032 #endif
00033
00035
00036
00037
00038
00039
00040
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 #define CodeBufferBitLen (CodeBufferLen*WordWidth)
00059 #define MaxCodeLen ((1 << RLblockSizeLen) - 1)
00060
00070 CEncoder::CEncoder(CPGFStream* stream, PGFPreHeader preHeader, PGFHeader header, const PGFPostHeader& postHeader, UINT64& userDataPos, bool useOMP) THROW_
00071 : m_stream(stream)
00072 , m_bufferStartPos(0)
00073 , m_currLevelIndex(0)
00074 , m_nLevels(header.nLevels)
00075 , m_favorSpeed(false)
00076 , m_forceWriting(false)
00077 #ifdef __PGFROISUPPORT__
00078 , m_roi(false)
00079 #endif
00080 {
00081 ASSERT(m_stream);
00082
00083 int count;
00084 m_lastMacroBlock = 0;
00085 m_levelLength = NULL;
00086
00087
00088 #ifdef LIBPGF_USE_OPENMP
00089 m_macroBlockLen = omp_get_num_procs();
00090 #else
00091 m_macroBlockLen = 1;
00092 #endif
00093
00094 if (useOMP && m_macroBlockLen > 1) {
00095 #ifdef LIBPGF_USE_OPENMP
00096 omp_set_num_threads(m_macroBlockLen);
00097 #endif
00098
00099 m_macroBlocks = new(std::nothrow) CMacroBlock*[m_macroBlockLen];
00100 if (!m_macroBlocks) ReturnWithError(InsufficientMemory);
00101 for (int i=0; i < m_macroBlockLen; i++) m_macroBlocks[i] = new CMacroBlock(this);
00102 m_currentBlock = m_macroBlocks[m_lastMacroBlock++];
00103 } else {
00104 m_macroBlocks = 0;
00105 m_macroBlockLen = 1;
00106 m_currentBlock = new CMacroBlock(this);
00107 }
00108
00109
00110 m_startPosition = m_stream->GetPos();
00111
00112
00113 preHeader.hSize = __VAL(preHeader.hSize);
00114 count = PreHeaderSize;
00115 m_stream->Write(&count, &preHeader);
00116
00117
00118 header.height = __VAL(header.height);
00119 header.width = __VAL(header.width);
00120 count = HeaderSize;
00121 m_stream->Write(&count, &header);
00122
00123
00124 if (header.mode == ImageModeIndexedColor) {
00125
00126 count = ColorTableSize;
00127 m_stream->Write(&count, (void *)postHeader.clut);
00128 }
00129
00130 userDataPos = m_stream->GetPos();
00131 if (postHeader.userDataLen) {
00132 if (postHeader.userData) {
00133
00134 count = postHeader.userDataLen;
00135 m_stream->Write(&count, postHeader.userData);
00136 } else {
00137 m_stream->SetPos(FSFromCurrent, count);
00138 }
00139 }
00140
00141
00142 m_levelLengthPos = m_stream->GetPos();
00143 }
00144
00146
00147 CEncoder::~CEncoder() {
00148 if (m_macroBlocks) {
00149 for (int i=0; i < m_macroBlockLen; i++) delete m_macroBlocks[i];
00150 delete[] m_macroBlocks;
00151 } else {
00152 delete m_currentBlock;
00153 }
00154 }
00155
00160 void CEncoder::UpdatePostHeaderSize(PGFPreHeader preHeader) THROW_ {
00161 UINT64 curPos = m_stream->GetPos();
00162 int count = PreHeaderSize;
00163
00164
00165 m_stream->SetPos(FSFromStart, m_startPosition);
00166 preHeader.hSize = __VAL(preHeader.hSize);
00167 m_stream->Write(&count, &preHeader);
00168
00169 m_stream->SetPos(FSFromStart, curPos);
00170 }
00171
00177 UINT32 CEncoder::WriteLevelLength(UINT32*& levelLength) THROW_ {
00178
00179 delete[] levelLength;
00180 levelLength = new(std::nothrow) UINT32[m_nLevels];
00181 if (!levelLength) ReturnWithError(InsufficientMemory);
00182 for (UINT8 l = 0; l < m_nLevels; l++) levelLength[l] = 0;
00183 m_levelLength = levelLength;
00184
00185
00186 m_levelLengthPos = m_stream->GetPos();
00187
00188
00189 int count = m_nLevels*WordBytes;
00190 m_stream->Write(&count, m_levelLength);
00191
00192
00193 SetBufferStartPos();
00194
00195 return count;
00196 }
00197
00202 UINT32 CEncoder::UpdateLevelLength() THROW_ {
00203 UINT64 curPos = m_stream->GetPos();
00204
00205
00206 m_stream->SetPos(FSFromStart, m_levelLengthPos);
00207
00208 if (m_levelLength) {
00209 #ifdef PGF_USE_BIG_ENDIAN
00210 UINT32 levelLength;
00211 int count = WordBytes;
00212
00213 for (int i=0; i < m_currLevelIndex; i++) {
00214 levelLength = __VAL(UINT32(m_levelLength[i]));
00215 m_stream->Write(&count, &levelLength);
00216 }
00217 #else
00218 int count = m_currLevelIndex*WordBytes;
00219
00220 m_stream->Write(&count, m_levelLength);
00221 #endif //PGF_USE_BIG_ENDIAN
00222 } else {
00223 int count = m_currLevelIndex*WordBytes;
00224 m_stream->SetPos(FSFromCurrent, count);
00225 }
00226
00227
00228 UINT32 retValue = UINT32(curPos - m_stream->GetPos());
00229
00230
00231 m_stream->SetPos(FSFromStart, curPos);
00232
00233 return retValue;
00234 }
00235
00246 void CEncoder::Partition(CSubband* band, int width, int height, int startPos, int pitch) THROW_ {
00247 ASSERT(band);
00248
00249 const div_t hh = div(height, LinBlockSize);
00250 const div_t ww = div(width, LinBlockSize);
00251 const int ws = pitch - LinBlockSize;
00252 const int wr = pitch - ww.rem;
00253 int pos, base = startPos, base2;
00254
00255
00256 for (int i=0; i < hh.quot; i++) {
00257
00258 base2 = base;
00259 for (int j=0; j < ww.quot; j++) {
00260 pos = base2;
00261 for (int y=0; y < LinBlockSize; y++) {
00262 for (int x=0; x < LinBlockSize; x++) {
00263 WriteValue(band, pos);
00264 pos++;
00265 }
00266 pos += ws;
00267 }
00268 base2 += LinBlockSize;
00269 }
00270
00271 pos = base2;
00272 for (int y=0; y < LinBlockSize; y++) {
00273 for (int x=0; x < ww.rem; x++) {
00274 WriteValue(band, pos);
00275 pos++;
00276 }
00277 pos += wr;
00278 base += pitch;
00279 }
00280 }
00281
00282 base2 = base;
00283 for (int j=0; j < ww.quot; j++) {
00284
00285 pos = base2;
00286 for (int y=0; y < hh.rem; y++) {
00287 for (int x=0; x < LinBlockSize; x++) {
00288 WriteValue(band, pos);
00289 pos++;
00290 }
00291 pos += ws;
00292 }
00293 base2 += LinBlockSize;
00294 }
00295
00296 pos = base2;
00297 for (int y=0; y < hh.rem; y++) {
00298
00299 for (int x=0; x < ww.rem; x++) {
00300 WriteValue(band, pos);
00301 pos++;
00302 }
00303 pos += wr;
00304 }
00305 }
00306
00310 void CEncoder::Flush() THROW_ {
00311 if (m_currentBlock->m_valuePos > 0) {
00312
00313 memset(&(m_currentBlock->m_value[m_currentBlock->m_valuePos]), 0, (BufferSize - m_currentBlock->m_valuePos)*DataTSize);
00314 m_currentBlock->m_valuePos = BufferSize;
00315
00316
00317 m_forceWriting = true;
00318 EncodeBuffer(ROIBlockHeader(m_currentBlock->m_valuePos, true));
00319 }
00320 }
00321
00323
00324
00325
00326 void CEncoder::WriteValue(CSubband* band, int bandPos) THROW_ {
00327 if (m_currentBlock->m_valuePos == BufferSize) {
00328 EncodeBuffer(ROIBlockHeader(BufferSize, false));
00329 }
00330 DataT val = m_currentBlock->m_value[m_currentBlock->m_valuePos++] = band->GetData(bandPos);
00331 UINT32 v = abs(val);
00332 if (v > m_currentBlock->m_maxAbsValue) m_currentBlock->m_maxAbsValue = v;
00333 }
00334
00336
00337
00338
00339
00340
00341 void CEncoder::EncodeBuffer(ROIBlockHeader h) THROW_ {
00342 ASSERT(m_currentBlock);
00343 #ifdef __PGFROISUPPORT__
00344 ASSERT(m_roi && h.rbh.bufferSize <= BufferSize || h.rbh.bufferSize == BufferSize);
00345 #else
00346 ASSERT(h.rbh.bufferSize == BufferSize);
00347 #endif
00348 m_currentBlock->m_header = h;
00349
00350
00351 if (m_macroBlockLen == 1) {
00352 m_currentBlock->BitplaneEncode();
00353 WriteMacroBlock(m_currentBlock);
00354 } else {
00355
00356 int lastLevelIndex = m_currentBlock->m_lastLevelIndex;
00357
00358 if (m_forceWriting || m_lastMacroBlock == m_macroBlockLen) {
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383 #ifdef LIBPGF_USE_OPENMP
00384 #pragma omp parallel for default(shared) //no declared exceptions in next block
00385 #endif
00386 for (int i=0; i < m_lastMacroBlock; i++) {
00387 m_macroBlocks[i]->BitplaneEncode();
00388 }
00389 for (int i=0; i < m_lastMacroBlock; i++) {
00390 WriteMacroBlock(m_macroBlocks[i]);
00391 }
00392
00393
00394 m_forceWriting = false;
00395 m_lastMacroBlock = 0;
00396 }
00397
00398 m_currentBlock = m_macroBlocks[m_lastMacroBlock++];
00399 m_currentBlock->Init(lastLevelIndex);
00400 }
00401 }
00402
00404
00405
00406 void CEncoder::WriteMacroBlock(CMacroBlock* block) THROW_ {
00407 ASSERT(block);
00408 #ifdef __PGFROISUPPORT__
00409 ROIBlockHeader h = block->m_header;
00410 #endif
00411 UINT16 wordLen = UINT16(NumberOfWords(block->m_codePos)); ASSERT(wordLen <= CodeBufferLen);
00412 int count = sizeof(UINT16);
00413
00414 #ifdef TRACE
00415
00416
00417 #endif
00418
00419 #ifdef PGF_USE_BIG_ENDIAN
00420
00421 UINT16 wl = __VAL(wordLen);
00422 m_stream->Write(&count, &wl); ASSERT(count == sizeof(UINT16));
00423
00424 #ifdef __PGFROISUPPORT__
00425
00426 if (m_roi) {
00427 h.val = __VAL(h.val);
00428 m_stream->Write(&count, &h.val); ASSERT(count == sizeof(UINT16));
00429 }
00430 #endif // __PGFROISUPPORT__
00431
00432
00433 for (int i=0; i < wordLen; i++) {
00434 block->m_codeBuffer[i] = __VAL(block->m_codeBuffer[i]);
00435 }
00436 #else
00437
00438 m_stream->Write(&count, &wordLen); ASSERT(count == sizeof(UINT16));
00439
00440 #ifdef __PGFROISUPPORT__
00441
00442 if (m_roi) {
00443 m_stream->Write(&count, &h.val); ASSERT(count == sizeof(UINT16));
00444 }
00445 #endif // __PGFROISUPPORT__
00446 #endif // PGF_USE_BIG_ENDIAN
00447
00448
00449 count = wordLen*WordBytes;
00450 m_stream->Write(&count, block->m_codeBuffer);
00451
00452
00453 if (m_levelLength) {
00454
00455
00456 ASSERT(m_currLevelIndex < m_nLevels);
00457 m_levelLength[m_currLevelIndex] += (UINT32)ComputeBufferLength();
00458 m_currLevelIndex = block->m_lastLevelIndex + 1;
00459
00460 }
00461
00462
00463 SetBufferStartPos();
00464
00465
00466 block->m_valuePos = 0;
00467 block->m_maxAbsValue = 0;
00468 }
00469
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480 void CEncoder::CMacroBlock::BitplaneEncode() {
00481 UINT8 nPlanes;
00482 UINT32 sigLen, codeLen = 0, wordPos, refLen, signLen;
00483 UINT32 sigBits[BufferLen] = { 0 };
00484 UINT32 refBits[BufferLen] = { 0 };
00485 UINT32 signBits[BufferLen] = { 0 };
00486 UINT32 planeMask;
00487 UINT32 bufferSize = m_header.rbh.bufferSize; ASSERT(bufferSize <= BufferSize);
00488 bool useRL;
00489
00490 #ifdef TRACE
00491
00492 #endif
00493
00494
00495 for (UINT32 k=0; k < bufferSize; k++) {
00496 m_sigFlagVector[k] = false;
00497 }
00498 m_sigFlagVector[bufferSize] = true;
00499
00500
00501 for (UINT32 k=0; k < bufferSize; k++) {
00502 m_codeBuffer[k] = 0;
00503 }
00504 m_codePos = 0;
00505
00506
00507 nPlanes = NumberOfBitplanes();
00508
00509
00510
00511 SetValueBlock(m_codeBuffer, 0, nPlanes, MaxBitPlanesLog);
00512 m_codePos += MaxBitPlanesLog;
00513
00514
00515 if (nPlanes == 0) nPlanes = MaxBitPlanes + 1;
00516 planeMask = 1 << (nPlanes - 1);
00517
00518 for (int plane = nPlanes - 1; plane >= 0; plane--) {
00519
00520 for (UINT32 k=0; k < BufferLen; k++) {
00521 sigBits[k] = 0;
00522 }
00523
00524
00525 sigLen = DecomposeBitplane(bufferSize, planeMask, m_codePos + RLblockSizeLen + 1, sigBits, refBits, signBits, signLen, codeLen);
00526
00527 if (sigLen > 0 && codeLen <= MaxCodeLen && codeLen < AlignWordPos(sigLen) + AlignWordPos(signLen) + 2*RLblockSizeLen) {
00528
00529
00530 SetBit(m_codeBuffer, m_codePos++);
00531
00532
00533 SetValueBlock(m_codeBuffer, m_codePos, codeLen, RLblockSizeLen);
00534 m_codePos += RLblockSizeLen + codeLen;
00535 } else {
00536 #ifdef TRACE
00537
00538
00539
00540
00541
00542
00543 #endif // TRACE
00544
00545
00546
00547
00548 ClearBit(m_codeBuffer, m_codePos++);
00549
00550
00551 ASSERT(sigLen <= MaxCodeLen);
00552 SetValueBlock(m_codeBuffer, m_codePos, sigLen, RLblockSizeLen);
00553 m_codePos += RLblockSizeLen;
00554
00555 if (m_encoder->m_favorSpeed || signLen == 0) {
00556 useRL = false;
00557 } else {
00558
00559 useRL = true;
00560
00561 codeLen = RLESigns(m_codePos + RLblockSizeLen + 1, signBits, signLen);
00562 }
00563
00564 if (useRL && codeLen <= MaxCodeLen && codeLen < signLen) {
00565
00566
00567
00568 SetBit(m_codeBuffer, m_codePos++);
00569
00570
00571 SetValueBlock(m_codeBuffer, m_codePos, codeLen, RLblockSizeLen);
00572
00573
00574 wordPos = NumberOfWords(m_codePos + RLblockSizeLen + codeLen);
00575 ASSERT(0 <= wordPos && wordPos < CodeBufferLen);
00576 } else {
00577
00578
00579
00580 ClearBit(m_codeBuffer, m_codePos++);
00581
00582
00583 ASSERT(signLen <= MaxCodeLen);
00584 SetValueBlock(m_codeBuffer, m_codePos, signLen, RLblockSizeLen);
00585
00586
00587 wordPos = NumberOfWords(m_codePos + RLblockSizeLen);
00588 ASSERT(0 <= wordPos && wordPos < CodeBufferLen);
00589 codeLen = NumberOfWords(signLen);
00590
00591 for (UINT32 k=0; k < codeLen; k++) {
00592 m_codeBuffer[wordPos++] = signBits[k];
00593 }
00594 }
00595
00596
00597
00598 ASSERT(0 <= wordPos && wordPos < CodeBufferLen);
00599 refLen = NumberOfWords(sigLen);
00600
00601 for (UINT32 k=0; k < refLen; k++) {
00602 m_codeBuffer[wordPos++] = sigBits[k];
00603 }
00604 m_codePos = wordPos << WordWidthLog;
00605 }
00606
00607
00608
00609 wordPos = NumberOfWords(m_codePos);
00610 ASSERT(0 <= wordPos && wordPos < CodeBufferLen);
00611 refLen = NumberOfWords(bufferSize - sigLen);
00612
00613 for (UINT32 k=0; k < refLen; k++) {
00614 m_codeBuffer[wordPos++] = refBits[k];
00615 }
00616 m_codePos = wordPos << WordWidthLog;
00617 planeMask >>= 1;
00618 }
00619 ASSERT(0 <= m_codePos && m_codePos <= CodeBufferBitLen);
00620 }
00621
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632 UINT32 CEncoder::CMacroBlock::DecomposeBitplane(UINT32 bufferSize, UINT32 planeMask, UINT32 codePos, UINT32* sigBits, UINT32* refBits, UINT32* signBits, UINT32& signLen, UINT32& codeLen) {
00633 ASSERT(sigBits);
00634 ASSERT(refBits);
00635 ASSERT(signBits);
00636 ASSERT(codePos < CodeBufferBitLen);
00637
00638 UINT32 sigPos = 0;
00639 UINT32 valuePos = 0, valueEnd;
00640 UINT32 refPos = 0;
00641
00642
00643 signLen = 0;
00644
00645
00646 const UINT32 outStartPos = codePos;
00647 UINT32 k = 3;
00648 UINT32 runlen = 1 << k;
00649 UINT32 count = 0;
00650
00651 while (valuePos < bufferSize) {
00652
00653 valueEnd = valuePos;
00654 while(!m_sigFlagVector[valueEnd]) { valueEnd++; }
00655
00656
00657
00658 while (valuePos < valueEnd) {
00659 if (GetBitAtPos(valuePos, planeMask)) {
00660
00661
00662
00663 SetBit(m_codeBuffer, codePos++);
00664 if (k > 0) {
00665 SetValueBlock(m_codeBuffer, codePos, count, k);
00666 codePos += k;
00667
00668
00669 k--;
00670 runlen >>= 1;
00671 }
00672
00673
00674 if (m_value[valuePos] < 0) {
00675 SetBit(signBits, signLen++);
00676 SetBit(m_codeBuffer, codePos++);
00677 } else {
00678 ClearBit(signBits, signLen++);
00679 ClearBit(m_codeBuffer, codePos++);
00680 }
00681
00682
00683 SetBit(sigBits, sigPos++);
00684
00685
00686 m_sigFlagVector[valuePos] = true;
00687
00688
00689 count = 0;
00690 } else {
00691
00692 count++;
00693 if (count == runlen) {
00694
00695 ClearBit(m_codeBuffer, codePos++);
00696
00697 if (k < WordWidth) {
00698 k++;
00699 runlen <<= 1;
00700 }
00701
00702
00703 count = 0;
00704 }
00705
00706
00707 sigPos++;
00708 }
00709 valuePos++;
00710 }
00711
00712 if (valuePos < bufferSize) {
00713
00714 if (GetBitAtPos(valuePos++, planeMask)) {
00715 SetBit(refBits, refPos);
00716 } else {
00717 ClearBit(refBits, refPos);
00718 }
00719 refPos++;
00720 }
00721 }
00722
00723
00724
00725 SetBit(m_codeBuffer, codePos++);
00726 if (k > 0) {
00727 SetValueBlock(m_codeBuffer, codePos, count, k);
00728 codePos += k;
00729 }
00730
00731 SetBit(m_codeBuffer, codePos++);
00732
00733
00734
00735 ASSERT(sigPos <= bufferSize);
00736 ASSERT(refPos <= bufferSize);
00737 ASSERT(signLen <= bufferSize);
00738 ASSERT(valuePos == bufferSize);
00739 ASSERT(codePos >= outStartPos && codePos < CodeBufferBitLen);
00740 codeLen = codePos - outStartPos;
00741
00742 return sigPos;
00743 }
00744
00745
00747
00748 UINT8 CEncoder::CMacroBlock::NumberOfBitplanes() {
00749 UINT8 cnt = 0;
00750
00751
00752 if (m_maxAbsValue > 0) {
00753 while (m_maxAbsValue > 0) {
00754 m_maxAbsValue >>= 1; cnt++;
00755 }
00756 if (cnt == MaxBitPlanes + 1) cnt = 0;
00757
00758 ASSERT(cnt <= MaxBitPlanes);
00759 ASSERT((cnt >> MaxBitPlanesLog) == 0);
00760 return cnt;
00761 } else {
00762 return 1;
00763 }
00764 }
00765
00767
00768
00769
00770
00771
00772 UINT32 CEncoder::CMacroBlock::RLESigns(UINT32 codePos, UINT32* signBits, UINT32 signLen) {
00773 ASSERT(signBits);
00774 ASSERT(0 <= codePos && codePos < CodeBufferBitLen);
00775 ASSERT(0 < signLen && signLen <= BufferSize);
00776
00777 const UINT32 outStartPos = codePos;
00778 UINT32 k = 0;
00779 UINT32 runlen = 1 << k;
00780 UINT32 count = 0;
00781 UINT32 signPos = 0;
00782
00783 while (signPos < signLen) {
00784
00785 count = SeekBit1Range(signBits, signPos, __min(runlen, signLen - signPos));
00786
00787 if (count == runlen) {
00788
00789 signPos += count;
00790 SetBit(m_codeBuffer, codePos++);
00791
00792 if (k < WordWidth) {
00793 k++;
00794 runlen <<= 1;
00795 }
00796 } else {
00797
00798
00799 signPos += count + 1;
00800 ClearBit(m_codeBuffer, codePos++);
00801 if (k > 0) {
00802 SetValueBlock(m_codeBuffer, codePos, count, k);
00803 codePos += k;
00804 }
00805
00806 if (k > 0) {
00807 k--;
00808 runlen >>= 1;
00809 }
00810 }
00811 }
00812 ASSERT(signPos == signLen || signPos == signLen + 1);
00813 ASSERT(codePos >= outStartPos && codePos < CodeBufferBitLen);
00814 return codePos - outStartPos;
00815 }
00816
00818 #ifdef TRACE
00819 void CEncoder::DumpBuffer() const {
00820
00821
00822
00823
00824
00825 }
00826 #endif //TRACE
00827
00828