libpgf: Encoder.cpp Source File

| libpgf 7.21.2 PGF - Progressive Graphics File

Loading...
Searching...
No Matches
Encoder.cpp
Go to the documentation of this file.
1/*
2 * The Progressive Graphics File; http://www.libpgf.org
3 *
4 * $Date: 2007-02-03 13:04:21 +0100 (Sa, 03 Feb 2007) $
5 * $Revision: 280 $
6 *
7 * This file Copyright (C) 2006 xeraina GmbH, Switzerland
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
28
29#include "Encoder.h"
30#ifdef TRACE
31 #include <stdio.h>
32#endif
33
35// PGF: file structure
36//
37// PGFPreHeader PGFHeader [PGFPostHeader] LevelLengths Level_n-1 Level_n-2 ... Level_0
38// PGFPostHeader ::= [ColorTable] [UserData]
39// LevelLengths ::= UINT32[nLevels]
40
42// Encoding scheme
43// input: wavelet coefficients stored in subbands
44// output: binary file
45//
46// subband
47// |
48// m_value [BufferSize]
49// | | |
50// m_sign sigBits refBits [BufferSize, BufferLen, BufferLen]
51// | | |
52// m_codeBuffer (for each plane: RLcodeLength (16 bit), RLcoded sigBits + m_sign, refBits)
53// |
54// file (for each buffer: packedLength (16 bit), packed bits)
55//
56
57// Constants
58#define CodeBufferBitLen (CodeBufferLen*WordWidth)
59#define MaxCodeLen ((1 << RLblockSizeLen) - 1)
60
70CEncoder::CEncoder(CPGFStream* stream, PGFPreHeader preHeader, PGFHeader header, const PGFPostHeader& postHeader, UINT64& userDataPos, bool useOMP)
71: m_stream(stream)
72, m_bufferStartPos(0)
73, m_currLevelIndex(0)
74, m_nLevels(header.nLevels)
75, m_favorSpeed(false)
76, m_forceWriting(false)
77#ifdef __PGFROISUPPORT__
78, m_roi(false)
79#endif
80{
81 ASSERT(m_stream);
82
83 int count;
84 m_lastMacroBlock = 0;
85 m_levelLength = nullptr;
86
87 // set number of threads
88#ifdef LIBPGF_USE_OPENMP
89 m_macroBlockLen = omp_get_num_procs();
90#else
91 m_macroBlockLen = 1;
92#endif
93
94 if (useOMP && m_macroBlockLen > 1) {
95#ifdef LIBPGF_USE_OPENMP
96 omp_set_num_threads(m_macroBlockLen);
97#endif
98 // create macro block array
99 m_macroBlocks = new(std::nothrow) CMacroBlock*[m_macroBlockLen];
100 if (!m_macroBlocks) ReturnWithError(InsufficientMemory);
101 for (int i=0; i < m_macroBlockLen; i++) m_macroBlocks[i] = new CMacroBlock(this);
102 m_currentBlock = m_macroBlocks[m_lastMacroBlock++];
103 } else {
104 m_macroBlocks = 0;
105 m_macroBlockLen = 1;
106 m_currentBlock = new CMacroBlock(this);
107 }
108
109 // save file position
110 m_startPosition = m_stream->GetPos();
111
112 // write preHeader
113 preHeader.hSize = __VAL(preHeader.hSize);
114 count = PreHeaderSize;
115 m_stream->Write(&count, &preHeader);
116
117 // write file header
118 header.height = __VAL(header.height);
119 header.width = __VAL(header.width);
120 count = HeaderSize;
121 m_stream->Write(&count, &header);
122
123 // write postHeader
124 if (header.mode == ImageModeIndexedColor) {
125 // write color table
126 count = ColorTableSize;
127 m_stream->Write(&count, (void *)postHeader.clut);
128 }
129 // save user data file position
130 userDataPos = m_stream->GetPos();
131 if (postHeader.userDataLen) {
132 if (postHeader.userData) {
133 // write user data
134 count = postHeader.userDataLen;
135 m_stream->Write(&count, postHeader.userData);
136 } else {
137 m_stream->SetPos(FSFromCurrent, count);
138 }
139 }
140
141 // save level length file position
142 m_levelLengthPos = m_stream->GetPos();
143}
144
146// Destructor
147CEncoder::~CEncoder() {
148 if (m_macroBlocks) {
149 for (int i=0; i < m_macroBlockLen; i++) delete m_macroBlocks[i];
150 delete[] m_macroBlocks;
151 } else {
152 delete m_currentBlock;
153 }
154}
155
160 void CEncoder::UpdatePostHeaderSize(PGFPreHeader preHeader) {
161 UINT64 curPos = m_stream->GetPos(); // end of user data
162 int count = PreHeaderSize;
163
164 // write preHeader
165 SetStreamPosToStart();
166 preHeader.hSize = __VAL(preHeader.hSize);
167 m_stream->Write(&count, &preHeader);
168
169 m_stream->SetPos(FSFromStart, curPos);
170}
171
177UINT32 CEncoder::WriteLevelLength(UINT32*& levelLength) {
178 // renew levelLength
179 delete[] levelLength;
180 levelLength = new(std::nothrow) UINT32[m_nLevels];
181 if (!levelLength) ReturnWithError(InsufficientMemory);
182 for (UINT8 l = 0; l < m_nLevels; l++) levelLength[l] = 0;
183 m_levelLength = levelLength;
184
185 // save level length file position
186 m_levelLengthPos = m_stream->GetPos();
187
188 // write dummy levelLength
189 int count = m_nLevels*WordBytes;
190 m_stream->Write(&count, m_levelLength);
191
192 // save current file position
193 SetBufferStartPos();
194
195 return count;
196}
197
202UINT32 CEncoder::UpdateLevelLength() {
203 UINT64 curPos = m_stream->GetPos(); // end of image
204
205 // set file pos to levelLength
206 m_stream->SetPos(FSFromStart, m_levelLengthPos);
207
208 if (m_levelLength) {
209 #ifdef PGF_USE_BIG_ENDIAN
210 UINT32 levelLength;
211 int count = WordBytes;
212
213 for (int i=0; i < m_currLevelIndex; i++) {
214 levelLength = __VAL(UINT32(m_levelLength[i]));
215 m_stream->Write(&count, &levelLength);
216 }
217 #else
218 int count = m_currLevelIndex*WordBytes;
219
220 m_stream->Write(&count, m_levelLength);
221 #endif //PGF_USE_BIG_ENDIAN
222 } else {
223 int count = m_currLevelIndex*WordBytes;
224 m_stream->SetPos(FSFromCurrent, count);
225 }
226
227 // begin of image
228 UINT32 retValue = UINT32(curPos - m_stream->GetPos());
229
230 // restore file position
231 m_stream->SetPos(FSFromStart, curPos);
232
233 return retValue;
234}
235
246 void CEncoder::Partition(CSubband* band, int width, int height, int startPos, int pitch) {
247 ASSERT(band);
248
249 const div_t hh = div(height, LinBlockSize);
250 const div_t ww = div(width, LinBlockSize);
251 const int ws = pitch - LinBlockSize;
252 const int wr = pitch - ww.rem;
253 int pos, base = startPos, base2;
254
255 // main height
256 for (int i=0; i < hh.quot; i++) {
257 // main width
258 base2 = base;
259 for (int j=0; j < ww.quot; j++) {
260 pos = base2;
261 for (int y=0; y < LinBlockSize; y++) {
262 for (int x=0; x < LinBlockSize; x++) {
263 WriteValue(band, pos);
264 pos++;
265 }
266 pos += ws;
267 }
268 base2 += LinBlockSize;
269 }
270 // rest of width
271 pos = base2;
272 for (int y=0; y < LinBlockSize; y++) {
273 for (int x=0; x < ww.rem; x++) {
274 WriteValue(band, pos);
275 pos++;
276 }
277 pos += wr;
278 base += pitch;
279 }
280 }
281 // main width
282 base2 = base;
283 for (int j=0; j < ww.quot; j++) {
284 // rest of height
285 pos = base2;
286 for (int y=0; y < hh.rem; y++) {
287 for (int x=0; x < LinBlockSize; x++) {
288 WriteValue(band, pos);
289 pos++;
290 }
291 pos += ws;
292 }
293 base2 += LinBlockSize;
294 }
295 // rest of height
296 pos = base2;
297 for (int y=0; y < hh.rem; y++) {
298 // rest of width
299 for (int x=0; x < ww.rem; x++) {
300 WriteValue(band, pos);
301 pos++;
302 }
303 pos += wr;
304 }
305}
306
310 void CEncoder::Flush() {
311 if (m_currentBlock->m_valuePos > 0) {
312 // pad buffer with zeros
313 memset(&(m_currentBlock->m_value[m_currentBlock->m_valuePos]), 0, (BufferSize - m_currentBlock->m_valuePos)*DataTSize);
314 m_currentBlock->m_valuePos = BufferSize;
315
316 // encode buffer
317 m_forceWriting = true; // makes sure that the following EncodeBuffer is really written into the stream
318 EncodeBuffer(ROIBlockHeader(m_currentBlock->m_valuePos, true));
319 }
320}
321
323// Stores band value from given position bandPos into buffer m_value at position m_valuePos
324// If buffer is full encode it to file
325// It might throw an IOException.
326 void CEncoder::WriteValue(CSubband* band, int bandPos) {
327 if (m_currentBlock->m_valuePos == BufferSize) {
328 EncodeBuffer(ROIBlockHeader(BufferSize, false));
329 }
330 DataT val = m_currentBlock->m_value[m_currentBlock->m_valuePos++] = band->GetData(bandPos);
331 UINT32 v = abs(val);
332 if (v > m_currentBlock->m_maxAbsValue) m_currentBlock->m_maxAbsValue = v;
333}
334
336// Encode buffer and write data into stream.
337// h contains buffer size and flag indicating end of tile.
338// Encoding scheme: <wordLen>(16 bits) [ ROI ] data
339// ROI ::= <bufferSize>(15 bits) <eofTile>(1 bit)
340// It might throw an IOException.
341 void CEncoder::EncodeBuffer(ROIBlockHeader h) {
342 ASSERT(m_currentBlock);
343#ifdef __PGFROISUPPORT__
344 ASSERT(m_roi && h.rbh.bufferSize <= BufferSize || h.rbh.bufferSize == BufferSize);
345#else
346 ASSERT(h.rbh.bufferSize == BufferSize);
347#endif
348 m_currentBlock->m_header = h;
349
350 // macro block management
351 if (m_macroBlockLen == 1) {
352 m_currentBlock->BitplaneEncode();
353 WriteMacroBlock(m_currentBlock);
354 } else {
355 // save last level index
356 int lastLevelIndex = m_currentBlock->m_lastLevelIndex;
357
358 if (m_forceWriting || m_lastMacroBlock == m_macroBlockLen) {
359 // encode macro blocks
360 /*
361 volatile OSError error = NoError;
362 #ifdef LIBPGF_USE_OPENMP
363 #pragma omp parallel for ordered default(shared)
364 #endif
365 for (int i=0; i < m_lastMacroBlock; i++) {
366 if (error == NoError) {
367 m_macroBlocks[i]->BitplaneEncode();
368 #ifdef LIBPGF_USE_OPENMP
369 #pragma omp ordered
370 #endif
371 {
372 try {
373 WriteMacroBlock(m_macroBlocks[i]);
374 } catch (IOException& e) {
375 error = e.error;
376 }
377 delete m_macroBlocks[i]; m_macroBlocks[i] = 0;
378 }
379 }
380 }
381 if (error != NoError) ReturnWithError(error);
382 */
383#ifdef LIBPGF_USE_OPENMP
384 #pragma omp parallel for default(shared) //no declared exceptions in next block
385#endif
386 for (int i=0; i < m_lastMacroBlock; i++) {
387 m_macroBlocks[i]->BitplaneEncode();
388 }
389 for (int i=0; i < m_lastMacroBlock; i++) {
390 WriteMacroBlock(m_macroBlocks[i]);
391 }
392
393 // prepare for next round
394 m_forceWriting = false;
395 m_lastMacroBlock = 0;
396 }
397 // re-initialize macro block
398 m_currentBlock = m_macroBlocks[m_lastMacroBlock++];
399 m_currentBlock->Init(lastLevelIndex);
400 }
401}
402
404// Write encoded macro block into stream.
405// It might throw an IOException.
406 void CEncoder::WriteMacroBlock(CMacroBlock* block) {
407 ASSERT(block);
408#ifdef __PGFROISUPPORT__
409 ROIBlockHeader h = block->m_header;
410#endif
411 UINT16 wordLen = UINT16(NumberOfWords(block->m_codePos)); ASSERT(wordLen <= CodeBufferLen);
412 int count = sizeof(UINT16);
413
414#ifdef TRACE
415 //UINT32 filePos = (UINT32)m_stream->GetPos();
416 //printf("EncodeBuffer: %d\n", filePos);
417#endif
418
419#ifdef PGF_USE_BIG_ENDIAN
420 // write wordLen
421 UINT16 wl = __VAL(wordLen);
422 m_stream->Write(&count, &wl); ASSERT(count == sizeof(UINT16));
423
424#ifdef __PGFROISUPPORT__
425 // write ROIBlockHeader
426 if (m_roi) {
427 count = sizeof(ROIBlockHeader);
428 h.val = __VAL(h.val);
429 m_stream->Write(&count, &h.val); ASSERT(count == sizeof(ROIBlockHeader));
430 }
431#endif // __PGFROISUPPORT__
432
433 // convert data
434 for (int i=0; i < wordLen; i++) {
435 block->m_codeBuffer[i] = __VAL(block->m_codeBuffer[i]);
436 }
437#else
438 // write wordLen
439 m_stream->Write(&count, &wordLen); ASSERT(count == sizeof(UINT16));
440
441#ifdef __PGFROISUPPORT__
442 // write ROIBlockHeader
443 if (m_roi) {
444 count = sizeof(ROIBlockHeader);
445 m_stream->Write(&count, &h.val); ASSERT(count == sizeof(ROIBlockHeader));
446 }
447#endif // __PGFROISUPPORT__
448#endif // PGF_USE_BIG_ENDIAN
449
450 // write encoded data into stream
451 count = wordLen*WordBytes;
452 m_stream->Write(&count, block->m_codeBuffer);
453
454 // store levelLength
455 if (m_levelLength) {
456 // store level length
457 // EncodeBuffer has been called after m_lastLevelIndex has been updated
458 ASSERT(m_currLevelIndex < m_nLevels);
459 m_levelLength[m_currLevelIndex] += (UINT32)ComputeBufferLength();
460 m_currLevelIndex = block->m_lastLevelIndex + 1;
461
462 }
463
464 // prepare for next buffer
465 SetBufferStartPos();
466
467 // reset values
468 block->m_valuePos = 0;
469 block->m_maxAbsValue = 0;
470}
471
473// Encode buffer of given size using bit plane coding.
474// A buffer contains bufferLen UINT32 values, thus, bufferSize bits per bit plane.
475// Following coding scheme is used:
476// Buffer ::= <nPlanes>(5 bits) foreach(plane i): Plane[i]
477// Plane[i] ::= [ Sig1 | Sig2 ] [DWORD alignment] refBits
478// Sig1 ::= 1 <codeLen>(15 bits) codedSigAndSignBits
479// Sig2 ::= 0 <sigLen>(15 bits) [Sign1 | Sign2 ] [DWORD alignment] sigBits
480// Sign1 ::= 1 <codeLen>(15 bits) codedSignBits
481// Sign2 ::= 0 <signLen>(15 bits) [DWORD alignment] signBits
482 void CEncoder::CMacroBlock::BitplaneEncode() {
483 UINT8 nPlanes;
484 UINT32 sigLen, codeLen = 0, wordPos, refLen, signLen;
485 UINT32 sigBits[BufferLen] = { 0 };
486 UINT32 refBits[BufferLen] = { 0 };
487 UINT32 signBits[BufferLen] = { 0 };
488 UINT32 planeMask;
489 UINT32 bufferSize = m_header.rbh.bufferSize; ASSERT(bufferSize <= BufferSize);
490 bool useRL;
491
492#ifdef TRACE
493 //printf("which thread: %d\n", omp_get_thread_num());
494#endif
495
496 // clear significance vector
497 for (UINT32 k=0; k < bufferSize; k++) {
498 m_sigFlagVector[k] = false;
499 }
500 m_sigFlagVector[bufferSize] = true; // sentinel
501
502 // clear output buffer
503 for (UINT32 k=0; k < bufferSize; k++) {
504 m_codeBuffer[k] = 0;
505 }
506 m_codePos = 0;
507
508 // compute number of bit planes and split buffer into separate bit planes
509 nPlanes = NumberOfBitplanes();
510
511 // write number of bit planes to m_codeBuffer
512 // <nPlanes>
513 SetValueBlock(m_codeBuffer, 0, nPlanes, MaxBitPlanesLog);
514 m_codePos += MaxBitPlanesLog;
515
516 // loop through all bit planes
517 if (nPlanes == 0) nPlanes = MaxBitPlanes + 1;
518 planeMask = 1 << (nPlanes - 1);
519
520 for (int plane = nPlanes - 1; plane >= 0; plane--) {
521 // clear significant bitset
522 for (UINT32 k=0; k < BufferLen; k++) {
523 sigBits[k] = 0;
524 }
525
526 // split bitplane in significant bitset and refinement bitset
527 sigLen = DecomposeBitplane(bufferSize, planeMask, m_codePos + RLblockSizeLen + 1, sigBits, refBits, signBits, signLen, codeLen);
528
529 if (sigLen > 0 && codeLen <= MaxCodeLen && codeLen < AlignWordPos(sigLen) + AlignWordPos(signLen) + 2*RLblockSizeLen) {
530 // set RL code bit
531 // <1><codeLen>
532 SetBit(m_codeBuffer, m_codePos++);
533
534 // write length codeLen to m_codeBuffer
535 SetValueBlock(m_codeBuffer, m_codePos, codeLen, RLblockSizeLen);
536 m_codePos += RLblockSizeLen + codeLen;
537 } else {
538 #ifdef TRACE
539 //printf("new\n");
540 //for (UINT32 i=0; i < bufferSize; i++) {
541 // printf("%s", (GetBit(sigBits, i)) ? "1" : "_");
542 // if (i%120 == 119) printf("\n");
543 //}
544 //printf("\n");
545 #endif // TRACE
546
547 // run-length coding wasn't efficient enough
548 // we don't use RL coding for sigBits
549 // <0><sigLen>
550 ClearBit(m_codeBuffer, m_codePos++);
551
552 // write length sigLen to m_codeBuffer
553 ASSERT(sigLen <= MaxCodeLen);
554 SetValueBlock(m_codeBuffer, m_codePos, sigLen, RLblockSizeLen);
555 m_codePos += RLblockSizeLen;
556
557 if (m_encoder->m_favorSpeed || signLen == 0) {
558 useRL = false;
559 } else {
560 // overwrite m_codeBuffer
561 useRL = true;
562 // run-length encode m_sign and append them to the m_codeBuffer
563 codeLen = RLESigns(m_codePos + RLblockSizeLen + 1, signBits, signLen);
564 }
565
566 if (useRL && codeLen <= MaxCodeLen && codeLen < signLen) {
567 // RL encoding of m_sign was efficient
568 // <1><codeLen><codedSignBits>_
569 // write RL code bit
570 SetBit(m_codeBuffer, m_codePos++);
571
572 // write codeLen to m_codeBuffer
573 SetValueBlock(m_codeBuffer, m_codePos, codeLen, RLblockSizeLen);
574
575 // compute position of sigBits
576 wordPos = NumberOfWords(m_codePos + RLblockSizeLen + codeLen);
577 ASSERT(0 <= wordPos && wordPos < CodeBufferLen);
578 } else {
579 // RL encoding of signBits wasn't efficient
580 // <0><signLen>_<signBits>_
581 // clear RL code bit
582 ClearBit(m_codeBuffer, m_codePos++);
583
584 // write signLen to m_codeBuffer
585 ASSERT(signLen <= MaxCodeLen);
586 SetValueBlock(m_codeBuffer, m_codePos, signLen, RLblockSizeLen);
587
588 // write signBits to m_codeBuffer
589 wordPos = NumberOfWords(m_codePos + RLblockSizeLen);
590 ASSERT(0 <= wordPos && wordPos < CodeBufferLen);
591 codeLen = NumberOfWords(signLen);
592
593 for (UINT32 k=0; k < codeLen; k++) {
594 m_codeBuffer[wordPos++] = signBits[k];
595 }
596 }
597
598 // write sigBits
599 // <sigBits>_
600 ASSERT(0 <= wordPos && wordPos < CodeBufferLen);
601 refLen = NumberOfWords(sigLen);
602
603 for (UINT32 k=0; k < refLen; k++) {
604 m_codeBuffer[wordPos++] = sigBits[k];
605 }
606 m_codePos = wordPos << WordWidthLog;
607 }
608
609 // append refinement bitset (aligned to word boundary)
610 // _<refBits>
611 wordPos = NumberOfWords(m_codePos);
612 ASSERT(0 <= wordPos && wordPos < CodeBufferLen);
613 refLen = NumberOfWords(bufferSize - sigLen);
614
615 for (UINT32 k=0; k < refLen; k++) {
616 m_codeBuffer[wordPos++] = refBits[k];
617 }
618 m_codePos = wordPos << WordWidthLog;
619 planeMask >>= 1;
620 }
621 ASSERT(0 <= m_codePos && m_codePos <= CodeBufferBitLen);
622}
623
625// Split bitplane of length bufferSize into significant and refinement bitset
626// returns length [bits] of significant bits
627// input: bufferSize, planeMask, codePos
628// output: sigBits, refBits, signBits, signLen [bits], codeLen [bits]
629// RLE
630// - Encode run of 2^k zeros by a single 0.
631// - Encode run of count 0's followed by a 1 with codeword: 1<count>x
632// - x is 0: if a positive sign is stored, otherwise 1
633// - Store each bit in m_codeBuffer[codePos] and increment codePos.
634UINT32 CEncoder::CMacroBlock::DecomposeBitplane(UINT32 bufferSize, UINT32 planeMask, UINT32 codePos, UINT32* sigBits, UINT32* refBits, UINT32* signBits, UINT32& signLen, UINT32& codeLen) {
635 ASSERT(sigBits);
636 ASSERT(refBits);
637 ASSERT(signBits);
638 ASSERT(codePos < CodeBufferBitLen);
639
640 UINT32 sigPos = 0;
641 UINT32 valuePos = 0, valueEnd;
642 UINT32 refPos = 0;
643
644 // set output value
645 signLen = 0;
646
647 // prepare RLE of Sigs and Signs
648 const UINT32 outStartPos = codePos;
649 UINT32 k = 3;
650 UINT32 runlen = 1 << k; // = 2^k
651 UINT32 count = 0;
652
653 while (valuePos < bufferSize) {
654 // search next 1 in m_sigFlagVector using searching with sentinel
655 valueEnd = valuePos;
656 while(!m_sigFlagVector[valueEnd]) { valueEnd++; }
657
658 // search 1's in m_value[plane][valuePos..valueEnd)
659 // these 1's are significant bits
660 while (valuePos < valueEnd) {
661 if (GetBitAtPos(valuePos, planeMask)) {
662 // RLE encoding
663 // encode run of count 0's followed by a 1
664 // with codeword: 1<count>(signBits[signPos])
665 SetBit(m_codeBuffer, codePos++);
666 if (k > 0) {
667 SetValueBlock(m_codeBuffer, codePos, count, k);
668 codePos += k;
669
670 // adapt k (half the zero run-length)
671 k--;
672 runlen >>= 1;
673 }
674
675 // copy and write sign bit
676 if (m_value[valuePos] < 0) {
677 SetBit(signBits, signLen++);
678 SetBit(m_codeBuffer, codePos++);
679 } else {
680 ClearBit(signBits, signLen++);
681 ClearBit(m_codeBuffer, codePos++);
682 }
683
684 // write a 1 to sigBits
685 SetBit(sigBits, sigPos++);
686
687 // update m_sigFlagVector
688 m_sigFlagVector[valuePos] = true;
689
690 // prepare for next run
691 count = 0;
692 } else {
693 // RLE encoding
694 count++;
695 if (count == runlen) {
696 // encode run of 2^k zeros by a single 0
697 ClearBit(m_codeBuffer, codePos++);
698 // adapt k (double the zero run-length)
699 if (k < WordWidth) {
700 k++;
701 runlen <<= 1;
702 }
703
704 // prepare for next run
705 count = 0;
706 }
707
708 // write 0 to sigBits
709 sigPos++;
710 }
711 valuePos++;
712 }
713 // refinement bit
714 if (valuePos < bufferSize) {
715 // write one refinement bit
716 if (GetBitAtPos(valuePos++, planeMask)) {
717 SetBit(refBits, refPos);
718 } else {
719 ClearBit(refBits, refPos);
720 }
721 refPos++;
722 }
723 }
724 // RLE encoding of the rest of the plane
725 // encode run of count 0's followed by a 1
726 // with codeword: 1<count>(signBits[signPos])
727 SetBit(m_codeBuffer, codePos++);
728 if (k > 0) {
729 SetValueBlock(m_codeBuffer, codePos, count, k);
730 codePos += k;
731 }
732 // write dmmy sign bit
733 SetBit(m_codeBuffer, codePos++);
734
735 // write word filler zeros
736
737 ASSERT(sigPos <= bufferSize);
738 ASSERT(refPos <= bufferSize);
739 ASSERT(signLen <= bufferSize);
740 ASSERT(valuePos == bufferSize);
741 ASSERT(codePos >= outStartPos && codePos < CodeBufferBitLen);
742 codeLen = codePos - outStartPos;
743
744 return sigPos;
745}
746
747
749// Compute number of bit planes needed
750UINT8 CEncoder::CMacroBlock::NumberOfBitplanes() {
751 UINT8 cnt = 0;
752
753 // determine number of bitplanes for max value
754 if (m_maxAbsValue > 0) {
755 while (m_maxAbsValue > 0) {
756 m_maxAbsValue >>= 1; cnt++;
757 }
758 if (cnt == MaxBitPlanes + 1) cnt = 0;
759 // end cs
760 ASSERT(cnt <= MaxBitPlanes);
761 ASSERT((cnt >> MaxBitPlanesLog) == 0);
762 return cnt;
763 } else {
764 return 1;
765 }
766}
767
769// Adaptive Run-Length encoder for long sequences of ones.
770// Returns length of output in bits.
771// - Encode run of 2^k ones by a single 1.
772// - Encode run of count 1's followed by a 0 with codeword: 0<count>.
773// - Store each bit in m_codeBuffer[codePos] and increment codePos.
774UINT32 CEncoder::CMacroBlock::RLESigns(UINT32 codePos, UINT32* signBits, UINT32 signLen) {
775 ASSERT(signBits);
776 ASSERT(0 <= codePos && codePos < CodeBufferBitLen);
777 ASSERT(0 < signLen && signLen <= BufferSize);
778
779 const UINT32 outStartPos = codePos;
780 UINT32 k = 0;
781 UINT32 runlen = 1 << k; // = 2^k
782 UINT32 count = 0;
783 UINT32 signPos = 0;
784
785 while (signPos < signLen) {
786 // search next 0 in signBits starting at position signPos
787 count = SeekBit1Range(signBits, signPos, __min(runlen, signLen - signPos));
788 // count 1's found
789 if (count == runlen) {
790 // encode run of 2^k ones by a single 1
791 signPos += count;
792 SetBit(m_codeBuffer, codePos++);
793 // adapt k (double the 1's run-length)
794 if (k < WordWidth) {
795 k++;
796 runlen <<= 1;
797 }
798 } else {
799 // encode run of count 1's followed by a 0
800 // with codeword: 0(count)
801 signPos += count + 1;
802 ClearBit(m_codeBuffer, codePos++);
803 if (k > 0) {
804 SetValueBlock(m_codeBuffer, codePos, count, k);
805 codePos += k;
806 }
807 // adapt k (half the 1's run-length)
808 if (k > 0) {
809 k--;
810 runlen >>= 1;
811 }
812 }
813 }
814 ASSERT(signPos == signLen || signPos == signLen + 1);
815 ASSERT(codePos >= outStartPos && codePos < CodeBufferBitLen);
816 return codePos - outStartPos;
817}
818
820#ifdef TRACE
821void CEncoder::DumpBuffer() const {
822 //printf("\nDump\n");
823 //for (UINT32 i=0; i < BufferSize; i++) {
824 // printf("%d", m_value[i]);
825 //}
826 //printf("\n");
827}
828#endif //TRACE
829
830
AlignWordPos
UINT32 AlignWordPos(UINT32 pos)
Definition BitStream.h:328
SetBit
void SetBit(UINT32 *stream, UINT32 pos)
Definition BitStream.h:62
SetValueBlock
void SetValueBlock(UINT32 *stream, UINT32 pos, UINT32 val, UINT32 k)
Definition BitStream.h:116
ClearBit
void ClearBit(UINT32 *stream, UINT32 pos)
Definition BitStream.h:70
SeekBit1Range
UINT32 SeekBit1Range(UINT32 *stream, UINT32 pos, UINT32 len)
Definition BitStream.h:249
NumberOfWords
UINT32 NumberOfWords(UINT32 pos)
Definition BitStream.h:337
CodeBufferBitLen
#define CodeBufferBitLen
max number of bits in m_codeBuffer
Definition Decoder.cpp:58
MaxCodeLen
#define MaxCodeLen
max length of RL encoded block
Definition Decoder.cpp:59
Encoder.h
PGF encoder class.
CodeBufferLen
#define CodeBufferLen
number of words in code buffer (CodeBufferLen > BufferLen)
Definition Encoder.h:40
BufferLen
#define BufferLen
number of words per buffer
Definition Encoder.h:39
WordWidthLog
#define WordWidthLog
ld of WordWidth
Definition PGFplatform.h:74
__PGFROISUPPORT__
#define __PGFROISUPPORT__
Definition PGFplatform.h:60
__VAL
#define __VAL(x)
Definition PGFplatform.h:603
WordBytes
#define WordBytes
sizeof(UINT32)
Definition PGFplatform.h:76
WordWidth
#define WordWidth
WordBytes*8.
Definition PGFplatform.h:73
__min
#define __min(x, y)
Definition PGFplatform.h:91
ImageModeIndexedColor
#define ImageModeIndexedColor
Definition PGFplatform.h:100
MaxBitPlanesLog
#define MaxBitPlanesLog
number of bits to code the maximum number of bit planes (in 32 or 16 bit mode)
Definition PGFtypes.h:93
PreHeaderSize
#define PreHeaderSize
Definition PGFtypes.h:280
HeaderSize
#define HeaderSize
Definition PGFtypes.h:281
ColorTableSize
#define ColorTableSize
Definition PGFtypes.h:282
LinBlockSize
#define LinBlockSize
side length of a coefficient block in a HH or LL subband
Definition PGFtypes.h:86
BufferSize
#define BufferSize
must be a multiple of WordWidth, BufferSize <= UINT16_MAX
Definition PGFtypes.h:84
RLblockSizeLen
#define RLblockSizeLen
block size length (< 16): ld(BufferSize) < RLblockSizeLen <= 2*ld(BufferSize)
Definition PGFtypes.h:85
DataT
INT32 DataT
Definition PGFtypes.h:269
DataTSize
#define DataTSize
Definition PGFtypes.h:283
MaxBitPlanes
#define MaxBitPlanes
maximum number of bit planes of m_value: 32 minus sign bit
Definition PGFtypes.h:89
CEncoder::CMacroBlock
A macro block is an encoding unit of fixed size (uncoded).
Definition Encoder.h:51
CEncoder::CMacroBlock::m_value
DataT m_value[BufferSize]
input buffer of values with index m_valuePos
Definition Encoder.h:84
CEncoder::CMacroBlock::NumberOfBitplanes
UINT8 NumberOfBitplanes()
Definition Encoder.cpp:750
CEncoder::CMacroBlock::DecomposeBitplane
UINT32 DecomposeBitplane(UINT32 bufferSize, UINT32 planeMask, UINT32 codePos, UINT32 *sigBits, UINT32 *refBits, UINT32 *signBits, UINT32 &signLen, UINT32 &codeLen)
Definition Encoder.cpp:634
CEncoder::CMacroBlock::RLESigns
UINT32 RLESigns(UINT32 codePos, UINT32 *signBits, UINT32 signLen)
Definition Encoder.cpp:774
CEncoder::CMacroBlock::m_codeBuffer
UINT32 m_codeBuffer[CodeBufferLen]
output buffer for encoded bitstream
Definition Encoder.h:85
CEncoder::CMacroBlock::m_lastLevelIndex
int m_lastLevelIndex
index of last encoded level: [0, nLevels); used because a level-end can occur before a buffer is full
Definition Encoder.h:90
CEncoder::CMacroBlock::m_codePos
UINT32 m_codePos
current position in encoded bitstream
Definition Encoder.h:89
CEncoder::CMacroBlock::m_valuePos
UINT32 m_valuePos
current buffer position
Definition Encoder.h:87
CEncoder::CMacroBlock::m_sigFlagVector
bool m_sigFlagVector[BufferSize+1]
Definition Encoder.h:99
CEncoder::CMacroBlock::GetBitAtPos
bool GetBitAtPos(UINT32 pos, UINT32 planeMask) const
Definition Encoder.h:96
CEncoder::CMacroBlock::m_maxAbsValue
UINT32 m_maxAbsValue
maximum absolute coefficient in each buffer
Definition Encoder.h:88
CEncoder::CMacroBlock::m_header
ROIBlockHeader m_header
block header
Definition Encoder.h:86
CEncoder::CMacroBlock::m_encoder
CEncoder * m_encoder
Definition Encoder.h:98
CEncoder::CMacroBlock::BitplaneEncode
void BitplaneEncode()
Definition Encoder.cpp:482
CEncoder::SetBufferStartPos
void SetBufferStartPos()
Save current stream position as beginning of current level.
Definition Encoder.h:192
CEncoder::m_bufferStartPos
UINT64 m_bufferStartPos
stream position of encoded buffer
Definition Encoder.h:216
CEncoder::m_favorSpeed
bool m_favorSpeed
favor speed over size
Definition Encoder.h:226
CEncoder::Partition
void Partition(CSubband *band, int width, int height, int startPos, int pitch)
Definition Encoder.cpp:246
CEncoder::m_startPosition
UINT64 m_startPosition
stream position of PGF start (PreHeader)
Definition Encoder.h:214
CEncoder::ComputeBufferLength
INT64 ComputeBufferLength() const
Definition Encoder.h:179
CEncoder::EncodeBuffer
void EncodeBuffer(ROIBlockHeader h)
Definition Encoder.cpp:341
CEncoder::m_forceWriting
bool m_forceWriting
all macro blocks have to be written into the stream
Definition Encoder.h:227
CEncoder::m_levelLengthPos
UINT64 m_levelLengthPos
stream position of Metadata
Definition Encoder.h:215
CEncoder::m_currentBlock
CMacroBlock * m_currentBlock
current macro block (used by main thread)
Definition Encoder.h:221
CEncoder::WriteValue
void WriteValue(CSubband *band, int bandPos)
Definition Encoder.cpp:326
CEncoder::CEncoder
CEncoder(CPGFStream *stream, PGFPreHeader preHeader, PGFHeader header, const PGFPostHeader &postHeader, UINT64 &userDataPos, bool useOMP)
Definition Encoder.cpp:70
CEncoder::m_levelLength
UINT32 * m_levelLength
temporary saves the level index
Definition Encoder.h:223
CEncoder::m_macroBlocks
CMacroBlock ** m_macroBlocks
array of macroblocks
Definition Encoder.h:218
CEncoder::m_nLevels
UINT8 m_nLevels
number of levels
Definition Encoder.h:225
CEncoder::m_currLevelIndex
int m_currLevelIndex
counts where (=index) to save next value
Definition Encoder.h:224
CEncoder::Flush
void Flush()
Definition Encoder.cpp:310
CEncoder::UpdateLevelLength
UINT32 UpdateLevelLength()
Definition Encoder.cpp:202
CEncoder::~CEncoder
~CEncoder()
Destructor.
Definition Encoder.cpp:147
CEncoder::m_lastMacroBlock
int m_lastMacroBlock
array index of the last created macro block
Definition Encoder.h:220
CEncoder::WriteMacroBlock
void WriteMacroBlock(CMacroBlock *block)
Definition Encoder.cpp:406
CEncoder::m_stream
CPGFStream * m_stream
output PMF stream
Definition Encoder.h:213
CEncoder::WriteLevelLength
UINT32 WriteLevelLength(UINT32 *&levelLength)
Definition Encoder.cpp:177
CEncoder::UpdatePostHeaderSize
void UpdatePostHeaderSize(PGFPreHeader preHeader)
Definition Encoder.cpp:160
CEncoder::SetStreamPosToStart
void SetStreamPosToStart()
Resets stream position to beginning of PGF pre-header.
Definition Encoder.h:188
CEncoder::m_macroBlockLen
int m_macroBlockLen
array length
Definition Encoder.h:219
CPGFStream
Abstract stream base class.
Definition PGFstream.h:39
CSubband
Wavelet channel class.
Definition Subband.h:42
CSubband::GetData
DataT GetData(UINT32 pos) const
Definition Subband.h:113
PGFHeader
PGF header.
Definition PGFtypes.h:151
PGFHeader::mode
UINT8 mode
image mode according to Adobe's image modes
Definition PGFtypes.h:159
PGFHeader::height
UINT32 height
image height in pixels
Definition PGFtypes.h:154
PGFHeader::width
UINT32 width
image width in pixels
Definition PGFtypes.h:153
PGFPostHeader
Optional PGF post-header.
Definition PGFtypes.h:169
PGFPostHeader::userDataLen
UINT32 userDataLen
user data size in bytes (not part of file header)
Definition PGFtypes.h:172
PGFPostHeader::clut
RGBQUAD clut[ColorTableLen]
color table for indexed color images (optional part of file header)
Definition PGFtypes.h:170
PGFPostHeader::userData
UINT8 * userData
user data of size userDataLen (optional part of file header)
Definition PGFtypes.h:171
PGFPreHeader
PGF pre-header.
Definition PGFtypes.h:123
PGFPreHeader::hSize
UINT32 hSize
total size of PGFHeader, [ColorTable], and [UserData] in bytes (since Version 6: 4 Bytes)
Definition PGFtypes.h:124
ROIBlockHeader::RBH::bufferSize
UINT16 bufferSize
number of uncoded UINT32 values in a block
Definition PGFtypes.h:188
ROIBlockHeader
Block header used with ROI coding scheme.
Definition PGFtypes.h:180
ROIBlockHeader::rbh
struct ROIBlockHeader::RBH rbh
ROI block header.
ROIBlockHeader::val
UINT16 val
Definition PGFtypes.h:181