Subversion Repositories Scribus

Rev

Rev 16771 | Rev 19721 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
15796 fschmid 1
/*
2
 * The Progressive Graphics File; http://www.libpgf.org
16771 fschmid 3
 *
15796 fschmid 4
 * $Date: 2007-02-03 13:04:21 +0100 (Sa, 03 Feb 2007) $
5
 * $Revision: 280 $
16771 fschmid 6
 *
15796 fschmid 7
 * This file Copyright (C) 2006 xeraina GmbH, Switzerland
16771 fschmid 8
 *
15796 fschmid 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.
16771 fschmid 13
 *
15796 fschmid 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.
16771 fschmid 18
 *
15796 fschmid 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
18122 mrdocs 21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
15796 fschmid 22
 */
23
 
16771 fschmid 24
//////////////////////////////////////////////////////////////////////
25
/// @file Encoder.cpp
26
/// @brief PGF encoder class implementation
27
/// @author C. Stamm, R. Spuler
28
 
15796 fschmid 29
#include "Encoder.h"
16771 fschmid 30
 
15796 fschmid 31
#ifdef TRACE
32
        #include <stdio.h>
33
#endif
34
 
35
//////////////////////////////////////////////////////
36
// PGF: file structure
37
//
38
// PGFPreHeader PGFHeader PGFPostHeader LevelLengths Level_n-1 Level_n-2 ... Level_0
39
// PGFPostHeader ::= [ColorTable] [UserData]
40
// LevelLengths  ::= UINT32[nLevels]
41
 
42
//////////////////////////////////////////////////////
43
// Encoding scheme
44
// input: wavelet coefficients stored in subbands
45
// output: binary file
46
//
47
//                   subband
48
//                      |
49
//                   m_value    [BufferSize]
50
//                |     |     |
51
//           m_sign  sigBits  refBits   [BufferSize, BufferLen, BufferLen]
52
//                |     |     |
53
//                m_codeBuffer  (for each plane: RLcodeLength (16 bit), RLcoded sigBits + m_sign, refBits)
54
//                      |
55
//                    file      (for each buffer: packedLength (16 bit), packed bits)
16771 fschmid 56
//
15796 fschmid 57
 
58
// Constants
59
#define CodeBufferBitLen                (BufferSize*WordWidth)          // max number of bits in m_codeBuffer
60
#define MaxCodeLen                              ((1 << RLblockSizeLen) - 1)     // max length of RL encoded block
61
 
62
//////////////////////////////////////////////////////
63
// Constructor
64
// Write pre-header, header, postHeader, and levelLength.
16771 fschmid 65
// It might throw an IOException.
15796 fschmid 66
// preHeader and header must not be references, because on BigEndian platforms they are modified
16771 fschmid 67
CEncoder::CEncoder(CPGFStream* stream, PGFPreHeader preHeader, PGFHeader header, const PGFPostHeader& postHeader, UINT32*& levelLength, bool useOMP /*= true*/) THROW_
15796 fschmid 68
: m_stream(stream)
69
, m_startPosition(0)
16771 fschmid 70
, m_currLevelIndex(0)
71
, m_nLevels(header.nLevels)
72
, m_favorSpeed(false)
73
, m_forceWriting(false)
15796 fschmid 74
#ifdef __PGFROISUPPORT__
75
, m_roi(false)
76
#endif
77
{
78
        ASSERT(m_stream);
79
 
80
        int count;
81
 
16771 fschmid 82
        // set number of threads
83
#ifdef LIBPGF_USE_OPENMP
84
        m_macroBlockLen = omp_get_num_procs();
85
#else
86
        m_macroBlockLen = 1;
87
#endif
88
 
89
        if (useOMP && m_macroBlockLen > 1) {
90
#ifdef LIBPGF_USE_OPENMP
91
                omp_set_num_threads(m_macroBlockLen);
92
#endif
93
 
94
                // create macro block array
95
                m_macroBlocks = new CMacroBlock*[m_macroBlockLen];
96
                for (int i=0; i < m_macroBlockLen; i++) m_macroBlocks[i] = new CMacroBlock(this);
97
                m_lastMacroBlock = 0;
98
                m_currentBlock = m_macroBlocks[m_lastMacroBlock++];
99
        } else {
100
                m_macroBlocks = 0;
101
                m_currentBlock = new CMacroBlock(this);
102
        }
103
 
15796 fschmid 104
        // save file position
105
        m_startPosition = m_stream->GetPos();
106
 
107
        // write preHeader
108
        preHeader.hSize = __VAL(preHeader.hSize);
109
        count = PreHeaderSize;
110
        m_stream->Write(&count, &preHeader);
111
 
112
        // write file header
113
        header.height = __VAL(header.height);
114
        header.width = __VAL(header.width);
115
        count = HeaderSize;
116
        m_stream->Write(&count, &header);
117
 
118
        // write postHeader
119
        if (header.mode == ImageModeIndexedColor) {
120
                // write color table
121
                count = ColorTableSize;
122
                m_stream->Write(&count, (void *)postHeader.clut);
123
        }
124
        if (postHeader.userData && postHeader.userDataLen) {
125
                // write user data
126
                count = postHeader.userDataLen;
127
                m_stream->Write(&count, postHeader.userData);
128
        }
129
 
130
        // renew levelLength
131
        delete[] levelLength;
16771 fschmid 132
        levelLength = new UINT32[m_nLevels];
15796 fschmid 133
        if (!levelLength) ReturnWithError(InsufficientMemory);
16771 fschmid 134
        for (UINT8 l = 0; l < m_nLevels; l++) levelLength[l] = 0;
15796 fschmid 135
        m_levelLength = levelLength;
136
 
137
        // write dummy levelLength
138
        m_levelLengthPos = m_stream->GetPos();
16771 fschmid 139
        count = m_nLevels*WordBytes;
15796 fschmid 140
        m_stream->Write(&count, m_levelLength);
141
 
142
        // save current file position
16771 fschmid 143
        SetBufferStartPos();
15796 fschmid 144
}
145
 
146
//////////////////////////////////////////////////////
147
// Destructor
16771 fschmid 148
CEncoder::~CEncoder() {
149
        delete m_currentBlock;
150
        delete[] m_macroBlocks;
15796 fschmid 151
}
152
 
153
/////////////////////////////////////////////////////////////////////
154
/// Partitions a rectangular region of a given subband.
155
/// Partitioning scheme: The plane is partitioned in squares of side length LinBlockSize.
156
/// Write wavelet coefficients into buffer.
157
/// It might throw an IOException.
158
/// @param band A subband
159
/// @param width The width of the rectangle
160
/// @param height The height of the rectangle
161
/// @param startPos The buffer position of the top left corner of the rectangular region
162
/// @param pitch The number of bytes in row of the subband
163
void CEncoder::Partition(CSubband* band, int width, int height, int startPos, int pitch) THROW_ {
164
        ASSERT(band);
165
 
166
        const div_t hh = div(height, LinBlockSize);
167
        const div_t ww = div(width, LinBlockSize);
168
        const int ws = pitch - LinBlockSize;
169
        const int wr = pitch - ww.rem;
170
        int pos, base = startPos, base2;
171
 
172
        // main height
16771 fschmid 173
        for (int i=0; i < hh.quot; i++) {
15796 fschmid 174
                // main width
175
                base2 = base;
16771 fschmid 176
                for (int j=0; j < ww.quot; j++) {
15796 fschmid 177
                        pos = base2;
16771 fschmid 178
                        for (int y=0; y < LinBlockSize; y++) {
179
                                for (int x=0; x < LinBlockSize; x++) {
15796 fschmid 180
                                        WriteValue(band, pos);
181
                                        pos++;
182
                                }
183
                                pos += ws;
184
                        }
185
                        base2 += LinBlockSize;
186
                }
187
                // rest of width
188
                pos = base2;
16771 fschmid 189
                for (int y=0; y < LinBlockSize; y++) {
190
                        for (int x=0; x < ww.rem; x++) {
15796 fschmid 191
                                WriteValue(band, pos);
192
                                pos++;
193
                        }
194
                        pos += wr;
195
                        base += pitch;
196
                }
197
        }
16771 fschmid 198
        // main width
15796 fschmid 199
        base2 = base;
16771 fschmid 200
        for (int j=0; j < ww.quot; j++) {
15796 fschmid 201
                // rest of height
202
                pos = base2;
16771 fschmid 203
                for (int y=0; y < hh.rem; y++) {
204
                        for (int x=0; x < LinBlockSize; x++) {
15796 fschmid 205
                                WriteValue(band, pos);
206
                                pos++;
207
                        }
208
                        pos += ws;
209
                }
210
                base2 += LinBlockSize;
211
        }
212
        // rest of height
213
        pos = base2;
16771 fschmid 214
        for (int y=0; y < hh.rem; y++) {
15796 fschmid 215
                // rest of width
16771 fschmid 216
                for (int x=0; x < ww.rem; x++) {
15796 fschmid 217
                        WriteValue(band, pos);
218
                        pos++;
219
                }
220
                pos += wr;
221
        }
222
}
223
 
224
//////////////////////////////////////////////////////
16771 fschmid 225
/// Pad buffer with zeros and encode buffer.
226
/// It might throw an IOException.
227
void CEncoder::Flush() THROW_ {
228
        // pad buffer with zeros
229
        memset(&(m_currentBlock->m_value[m_currentBlock->m_valuePos]), 0, (BufferSize - m_currentBlock->m_valuePos)*DataTSize);
230
        m_currentBlock->m_valuePos = BufferSize;
15796 fschmid 231
 
232
        // encode buffer
16771 fschmid 233
        m_forceWriting = true;  // makes sure that the following EncodeBuffer is really written into the stream
234
        EncodeBuffer(ROIBlockHeader(m_currentBlock->m_valuePos, true));
235
}
15796 fschmid 236
 
16771 fschmid 237
//////////////////////////////////////////////////////
238
/// Write levelLength into header.
239
/// @return number of bytes written into stream
240
/// It might throw an IOException.
241
UINT32 CEncoder::WriteLevelLength() THROW_ {
242
        UINT64 curPos = m_stream->GetPos();
243
        UINT32 retValue = UINT32(curPos - m_startPosition);
15796 fschmid 244
 
245
        if (m_levelLength) {
246
                // append levelLength to file, directly after post-header
247
                // set file pos to levelLength
248
                m_stream->SetPos(FSFromStart, m_levelLengthPos);
16771 fschmid 249
        #ifdef PGF_USE_BIG_ENDIAN
15796 fschmid 250
                UINT32 levelLength;
251
                int count = WordBytes;
16771 fschmid 252
 
15796 fschmid 253
                for (int i=0; i < m_currLevelIndex; i++) {
254
                        levelLength = __VAL(UINT32(m_levelLength[i]));
255
                        m_stream->Write(&count, &levelLength);
256
                }
16771 fschmid 257
        #else
15796 fschmid 258
                int count = m_currLevelIndex*WordBytes;
16771 fschmid 259
 
15796 fschmid 260
                m_stream->Write(&count, m_levelLength);
16771 fschmid 261
        #endif //PGF_USE_BIG_ENDIAN
15796 fschmid 262
 
263
                // restore file position
264
                m_stream->SetPos(FSFromStart, curPos);
265
        }
266
 
267
        return retValue;
268
}
269
 
270
/////////////////////////////////////////////////////////////////////
271
// Stores band value from given position bandPos into buffer m_value at position m_valuePos
272
// If buffer is full encode it to file
16771 fschmid 273
// It might throw an IOException.
15796 fschmid 274
void CEncoder::WriteValue(CSubband* band, int bandPos) THROW_ {
16771 fschmid 275
        if (m_currentBlock->m_valuePos == BufferSize) {
15796 fschmid 276
                EncodeBuffer(ROIBlockHeader(BufferSize, false));
277
        }
16771 fschmid 278
        DataT val = m_currentBlock->m_value[m_currentBlock->m_valuePos++] = band->GetData(bandPos);
279
        UINT32 v = abs(val);
280
        if (v > m_currentBlock->m_maxAbsValue) m_currentBlock->m_maxAbsValue = v;
15796 fschmid 281
}
282
 
16771 fschmid 283
/////////////////////////////////////////////////////////////////////
284
// Write encoded macro block into stream.
285
// It might throw an IOException.
286
void CEncoder::WriteMacroBlock(CMacroBlock* block) THROW_ {
287
        ASSERT(block);
15796 fschmid 288
 
16771 fschmid 289
        ROIBlockHeader h = block->m_header;
290
        UINT16 wordLen = UINT16(NumberOfWords(block->m_codePos)); ASSERT(wordLen <= BufferSize);
15796 fschmid 291
        int count = sizeof(UINT16);
292
 
16771 fschmid 293
#ifdef TRACE
294
        //UINT32 filePos = (UINT32)m_stream->GetPos();
295
        //printf("EncodeBuffer: %d\n", filePos);
296
#endif
297
 
298
#ifdef PGF_USE_BIG_ENDIAN
15796 fschmid 299
        // write wordLen
16771 fschmid 300
        UINT16 wl = __VAL(wordLen);
301
        m_stream->Write(&count, &wl); ASSERT(count == sizeof(UINT16));
15796 fschmid 302
 
16771 fschmid 303
#ifdef __PGFROISUPPORT__
304
        // write ROIBlockHeader
305
        if (m_roi) {
306
                h.val = __VAL(h.val);
307
                m_stream->Write(&count, &h.val); ASSERT(count == sizeof(UINT16));
308
        }
309
#endif // __PGFROISUPPORT__
15796 fschmid 310
 
311
        // convert data
312
        for (int i=0; i < wordLen; i++) {
313
                m_codeBuffer[i] = __VAL(m_codeBuffer[i]);
314
        }
315
#else
316
        // write wordLen
317
        m_stream->Write(&count, &wordLen); ASSERT(count == sizeof(UINT16));
318
 
16771 fschmid 319
#ifdef __PGFROISUPPORT__
320
        // write ROIBlockHeader
321
        if (m_roi) {
322
                m_stream->Write(&count, &h.val); ASSERT(count == sizeof(UINT16));
323
        }
324
#endif // __PGFROISUPPORT__
325
#endif // PGF_USE_BIG_ENDIAN
15796 fschmid 326
 
16771 fschmid 327
        // write encoded data into stream
15796 fschmid 328
        count = wordLen*WordBytes;
16771 fschmid 329
        m_stream->Write(&count, block->m_codeBuffer);
15796 fschmid 330
 
331
        // store levelLength
16771 fschmid 332
        if (m_levelLength) {
333
                // store level length
334
                // EncodeBuffer has been called after m_lastLevelIndex has been updated
335
                m_levelLength[m_currLevelIndex] += ComputeBufferLength();
336
                m_currLevelIndex = block->m_lastLevelIndex + 1;
337
 
15796 fschmid 338
        }
339
 
16771 fschmid 340
        // prepare for next buffer
341
        SetBufferStartPos();
342
 
15796 fschmid 343
        // reset values
16771 fschmid 344
        block->m_valuePos = 0;
345
        block->m_maxAbsValue = 0;
15796 fschmid 346
}
347
 
16771 fschmid 348
/////////////////////////////////////////////////////////////////////
349
// Encode buffer and write data into stream.
350
// h contains buffer size and flag indicating end of tile.
351
// Encoding scheme: <wordLen>(16 bits) [ ROI ] data
352
//              ROI       ::= <bufferSize>(15 bits) <eofTile>(1 bit)
353
// It might throw an IOException.
354
void CEncoder::EncodeBuffer(ROIBlockHeader h) THROW_ {
355
        ASSERT(m_currentBlock);
356
#ifdef __PGFROISUPPORT__
357
        ASSERT(m_roi && h.rbh.bufferSize <= BufferSize || h.rbh.bufferSize == BufferSize);
358
#else
359
        ASSERT(h.rbh.bufferSize == BufferSize);
360
#endif
361
        m_currentBlock->m_header = h;
362
 
363
        // macro block management
364
        if (m_macroBlockLen == 1) {
365
                m_currentBlock->BitplaneEncode();
366
                WriteMacroBlock(m_currentBlock);
367
        } else {
368
                // save last level index
369
                int lastLevelIndex = m_currentBlock->m_lastLevelIndex;
370
 
371
                if (m_forceWriting || m_lastMacroBlock == m_macroBlockLen) {
372
                        // encode macro blocks
373
                        /*
374
                        volatile OSError error = NoError;
375
                        #pragma omp parallel for ordered default(shared)
376
                        for (int i=0; i < m_lastMacroBlock; i++) {
377
                                if (error == NoError) {
378
                                        m_macroBlocks[i]->BitplaneEncode();
379
                                        #pragma omp ordered
380
                                        {
381
                                                try {
382
                                                        WriteMacroBlock(m_macroBlocks[i]);
383
                                                } catch (IOException& e) {
384
                                                        error = e.error;
385
                                                }
386
                                                delete m_macroBlocks[i]; m_macroBlocks[i] = 0;
387
                                        }
388
                                }
389
                        }
390
                        if (error != NoError) ReturnWithError(error);
391
                        */
392
                        #pragma omp parallel for default(shared) //no declared exceptions in next block
393
                        for (int i=0; i < m_lastMacroBlock; i++) {
394
                                m_macroBlocks[i]->BitplaneEncode();
395
                        }
396
                        for (int i=0; i < m_lastMacroBlock; i++) {
397
                                WriteMacroBlock(m_macroBlocks[i]);
398
                        }
399
 
400
                        // prepare for next round
401
                        m_forceWriting = false;
402
                        m_lastMacroBlock = 0;
403
                }
404
                // re-initialize macro block
405
                m_currentBlock = m_macroBlocks[m_lastMacroBlock++];
406
                m_currentBlock->Init(lastLevelIndex);
407
        }
408
}
409
 
15796 fschmid 410
////////////////////////////////////////////////////////
411
// Encode buffer of given size using bit plane coding.
412
// A buffer contains bufferLen UINT32 values, thus, bufferSize bits per bit plane.
16771 fschmid 413
// Following coding scheme is used:
414
//              Buffer          ::= <nPlanes>(5 bits) foreach(plane i): Plane[i]
15796 fschmid 415
//              Plane[i]        ::= [ Sig1 | Sig2 ] [DWORD alignment] refBits
16771 fschmid 416
//              Sig1            ::= 1 <codeLen>(15 bits) codedSigAndSignBits
417
//              Sig2            ::= 0 <sigLen>(15 bits) [Sign1 | Sign2 ] sigBits
15796 fschmid 418
//              Sign1           ::= 1 <codeLen>(15 bits) [DWORD alignment] codedSignBits
419
//              Sign2           ::= 0 <signLen>(15 bits) [DWORD alignment] signBits
16771 fschmid 420
void CEncoder::CMacroBlock::BitplaneEncode() {
15796 fschmid 421
        UINT8   nPlanes;
16771 fschmid 422
        UINT32  sigLen, codeLen = 0, wordPos, refLen, signLen;
423
        UINT32  sigBits[BufferLen] = { 0 };
424
        UINT32  refBits[BufferLen] = { 0 };
425
        UINT32  signBits[BufferLen] = { 0 };
15796 fschmid 426
        UINT32  planeMask;
16771 fschmid 427
        UINT32  bufferSize = m_header.rbh.bufferSize; ASSERT(bufferSize <= BufferSize);
15796 fschmid 428
        bool    useRL;
16771 fschmid 429
        //const UINT32 bufferLen = NumberOfWords(m_bufferSize);
15796 fschmid 430
 
16771 fschmid 431
#ifdef TRACE
432
        //printf("which thread: %d\n", omp_get_thread_num());
433
#endif
434
 
15796 fschmid 435
        // clear significance vector
16771 fschmid 436
        for (UINT32 k=0; k < bufferSize; k++) {
437
                m_sigFlagVector[k] = false;
15796 fschmid 438
        }
16771 fschmid 439
        m_sigFlagVector[bufferSize] = true; // sentinel
15796 fschmid 440
 
16771 fschmid 441
        // clear output buffer
442
        for (UINT32 k=0; k < bufferSize; k++) {
443
                m_codeBuffer[k] = 0;
444
        }
445
        m_codePos = 0;
446
 
15796 fschmid 447
        // compute number of bit planes and split buffer into separate bit planes
448
        nPlanes = NumberOfBitplanes();
449
 
450
        // write number of bit planes to m_codeBuffer
451
        SetValueBlock(m_codeBuffer, 0, nPlanes, MaxBitPlanesLog);
16771 fschmid 452
        m_codePos += MaxBitPlanesLog;
15796 fschmid 453
 
454
        // loop through all bit planes
455
        if (nPlanes == 0) nPlanes = MaxBitPlanes + 1;
456
        planeMask = 1 << (nPlanes - 1);
457
 
16771 fschmid 458
        for (int plane = nPlanes - 1; plane >= 0; plane--) {
15796 fschmid 459
                // clear significant bitset
16771 fschmid 460
                for (UINT32 k=0; k < BufferLen; k++) {
15796 fschmid 461
                        sigBits[k] = 0;
462
                }
463
 
464
                // split bitplane in significant bitset and refinement bitset
16771 fschmid 465
                sigLen = DecomposeBitplane(bufferSize, planeMask, m_codePos + RLblockSizeLen + 1, sigBits, refBits, signBits, signLen, codeLen);
15796 fschmid 466
 
16771 fschmid 467
                if (sigLen > 0 && codeLen <= MaxCodeLen && codeLen < AlignWordPos(sigLen) + AlignWordPos(signLen) + 2*RLblockSizeLen) {
15796 fschmid 468
                        // set RL code bit
16771 fschmid 469
                        SetBit(m_codeBuffer, m_codePos++);
15796 fschmid 470
 
471
                        // write length codeLen to m_codeBuffer
16771 fschmid 472
                        SetValueBlock(m_codeBuffer, m_codePos, codeLen, RLblockSizeLen);
473
                        m_codePos += RLblockSizeLen + codeLen;
15796 fschmid 474
                } else {
16771 fschmid 475
                #ifdef TRACE
476
                        //printf("new\n");
477
                        //for (UINT32 i=0; i < bufferSize; i++) {
478
                        //      printf("%s", (GetBit(sigBits, i)) ? "1" : "_");
479
                        //      if (i%120 == 119) printf("\n");
480
                        //}
481
                        //printf("\n");
482
                #endif // TRACE
15796 fschmid 483
 
484
                        // run-length coding wasn't efficient enough
485
                        // we don't use RL coding for sigBits
16771 fschmid 486
                        ClearBit(m_codeBuffer, m_codePos++);
15796 fschmid 487
 
488
                        // write length sigLen to m_codeBuffer
16771 fschmid 489
                        ASSERT(sigLen <= MaxCodeLen);
490
                        SetValueBlock(m_codeBuffer, m_codePos, sigLen, RLblockSizeLen);
491
                        m_codePos += RLblockSizeLen;
15796 fschmid 492
 
16771 fschmid 493
                        if (m_encoder->m_favorSpeed || signLen == 0) {
494
                                useRL = false;
495
                        } else {
496
                                // overwrite m_codeBuffer
15796 fschmid 497
                                useRL = true;
498
                                // run-length encode m_sign and append them to the m_codeBuffer
16771 fschmid 499
                                codeLen = RLESigns(m_codePos + RLblockSizeLen + 1, signBits, signLen);
15796 fschmid 500
                        }
501
 
502
                        if (useRL && codeLen <= MaxCodeLen && codeLen < signLen) {
503
                                // RL encoding of m_sign was efficient
504
                                // write RL code bit
16771 fschmid 505
                                SetBit(m_codeBuffer, m_codePos++);
506
 
15796 fschmid 507
                                // write codeLen to m_codeBuffer
16771 fschmid 508
                                SetValueBlock(m_codeBuffer, m_codePos, codeLen, RLblockSizeLen);
15796 fschmid 509
 
510
                                // compute position of sigBits
16771 fschmid 511
                                wordPos = NumberOfWords(m_codePos + codeLen + RLblockSizeLen);
15796 fschmid 512
                                ASSERT(0 <= wordPos && wordPos < BufferSize);
513
                        } else {
514
                                // RL encoding of signBits wasn't efficient
515
                                // clear RL code bit
16771 fschmid 516
                                ClearBit(m_codeBuffer, m_codePos++);
15796 fschmid 517
 
518
                                // write signLen to m_codeBuffer
16771 fschmid 519
                                ASSERT(signLen <= MaxCodeLen);
520
                                SetValueBlock(m_codeBuffer, m_codePos, signLen, RLblockSizeLen);
15796 fschmid 521
 
522
                                // write signBits to m_codeBuffer
16771 fschmid 523
                                wordPos = NumberOfWords(m_codePos + RLblockSizeLen);
15796 fschmid 524
                                ASSERT(0 <= wordPos && wordPos < BufferSize);
16771 fschmid 525
                                codeLen = NumberOfWords(signLen);
15796 fschmid 526
 
16771 fschmid 527
                                for (UINT32 k=0; k < codeLen; k++) {
528
                                        m_codeBuffer[wordPos++] = signBits[k];
15796 fschmid 529
                                }
16771 fschmid 530
 
15796 fschmid 531
                        }
532
 
533
                        // write sigBits
534
                        ASSERT(0 <= wordPos && wordPos < BufferSize);
16771 fschmid 535
                        refLen = NumberOfWords(sigLen);
15796 fschmid 536
 
16771 fschmid 537
                        for (UINT32 k=0; k < refLen; k++) {
538
                                m_codeBuffer[wordPos++] = sigBits[k];
15796 fschmid 539
                        }
16771 fschmid 540
                        m_codePos = wordPos << WordWidthLog;
15796 fschmid 541
                }
542
 
543
                // append refinement bitset (aligned to word boundary)
16771 fschmid 544
                wordPos = NumberOfWords(m_codePos);
15796 fschmid 545
                ASSERT(0 <= wordPos && wordPos < BufferSize);
16771 fschmid 546
                refLen = NumberOfWords(bufferSize - sigLen);
15796 fschmid 547
 
16771 fschmid 548
                for (UINT32 k=0; k < refLen; k++) {
549
                        m_codeBuffer[wordPos++] = refBits[k];
15796 fschmid 550
                }
16771 fschmid 551
                m_codePos = wordPos << WordWidthLog;
15796 fschmid 552
                planeMask >>= 1;
553
        }
16771 fschmid 554
        ASSERT(0 <= m_codePos && m_codePos <= CodeBufferBitLen);
15796 fschmid 555
}
556
 
557
//////////////////////////////////////////////////////////
558
// Split bitplane of length bufferSize into significant and refinement bitset
559
// returns length [bits] of significant bits
16771 fschmid 560
// input:  bufferSize, planeMask, codePos
561
// output: sigBits, refBits, signBits, signLen [bits], codeLen [bits]
562
// RLE
563
// - Encode run of 2^k zeros by a single 0.
564
// - Encode run of count 0's followed by a 1 with codeword: 1<count>x
565
// - x is 0: if a positive sign is stored, otherwise 1
566
// - Store each bit in m_codeBuffer[codePos] and increment codePos.
567
UINT32 CEncoder::CMacroBlock::DecomposeBitplane(UINT32 bufferSize, UINT32 planeMask, UINT32 codePos, UINT32* sigBits, UINT32* refBits, UINT32* signBits, UINT32& signLen, UINT32& codeLen) {
15796 fschmid 568
        ASSERT(sigBits);
569
        ASSERT(refBits);
570
        ASSERT(signBits);
16771 fschmid 571
        ASSERT(codePos < CodeBufferBitLen);
15796 fschmid 572
 
573
        UINT32 sigPos = 0;
574
        UINT32 valuePos = 0, valueEnd;
575
        UINT32 refPos = 0;
576
 
16771 fschmid 577
        // set output value
15796 fschmid 578
        signLen = 0;
579
 
16771 fschmid 580
        // prepare RLE of Sigs and Signs
581
        const UINT32 outStartPos = codePos;
582
        UINT32 k = 3;
583
        UINT32 runlen = 1 << k; // = 2^k
584
        UINT32 count = 0;
585
 
15796 fschmid 586
        while (valuePos < bufferSize) {
16771 fschmid 587
                // search next 1 in m_sigFlagVector using searching with sentinel
588
                valueEnd = valuePos;
589
                while(!m_sigFlagVector[valueEnd]) { valueEnd++; }
15796 fschmid 590
 
16771 fschmid 591
                // search 1's in m_value[plane][valuePos..valueEnd)
15796 fschmid 592
                // these 1's are significant bits
593
                while (valuePos < valueEnd) {
16771 fschmid 594
                        if (GetBitAtPos(valuePos, planeMask)) {
595
                                // RLE encoding
596
                                // encode run of count 0's followed by a 1
597
                                // with codeword: 1<count>(signBits[signPos])
598
                                SetBit(m_codeBuffer, codePos++);
599
                                if (k > 0) {
600
                                        SetValueBlock(m_codeBuffer, codePos, count, k);
601
                                        codePos += k;
15796 fschmid 602
 
16771 fschmid 603
                                        // adapt k (half the zero run-length)
604
                                        k--;
605
                                        runlen >>= 1;
606
                                }
607
 
608
                                // copy and write sign bit
15796 fschmid 609
                                if (m_value[valuePos] < 0) {
16771 fschmid 610
                                        SetBit(signBits, signLen++);
611
                                        SetBit(m_codeBuffer, codePos++);
15796 fschmid 612
                                } else {
16771 fschmid 613
                                        ClearBit(signBits, signLen++);
614
                                        ClearBit(m_codeBuffer, codePos++);
15796 fschmid 615
                                }
616
 
16771 fschmid 617
                                // write a 1 to sigBits
618
                                SetBit(sigBits, sigPos++);
619
 
15796 fschmid 620
                                // update m_sigFlagVector
16771 fschmid 621
                                m_sigFlagVector[valuePos] = true;
622
 
623
                                // prepare for next run
624
                                count = 0;
625
                        } else {
626
                                // RLE encoding
627
                                count++;
628
                                if (count == runlen) {
629
                                        // encode run of 2^k zeros by a single 0
630
                                        ClearBit(m_codeBuffer, codePos++);
631
                                        // adapt k (double the zero run-length)
632
                                        if (k < WordWidth) {
633
                                                k++;
634
                                                runlen <<= 1;
635
                                        }
636
 
637
                                        // prepare for next run
638
                                        count = 0;
639
                                }
640
 
641
                                // write 0 to sigBits
642
                                sigPos++;
15796 fschmid 643
                        }
16771 fschmid 644
                        valuePos++;
15796 fschmid 645
                }
646
                // refinement bit
647
                if (valuePos < bufferSize) {
648
                        // write one refinement bit
16771 fschmid 649
                        if (GetBitAtPos(valuePos++, planeMask)) {
15796 fschmid 650
                                SetBit(refBits, refPos);
651
                        } else {
652
                                ClearBit(refBits, refPos);
653
                        }
654
                        refPos++;
655
                }
656
        }
16771 fschmid 657
        // RLE encoding of the rest of the plane
658
        // encode run of count 0's followed by a 1
659
        // with codeword: 1<count>(signBits[signPos])
660
        SetBit(m_codeBuffer, codePos++);
661
        if (k > 0) {
662
                SetValueBlock(m_codeBuffer, codePos, count, k);
663
                codePos += k;
664
        }
665
        // write dmmy sign bit
666
        SetBit(m_codeBuffer, codePos++);
15796 fschmid 667
 
16771 fschmid 668
        // write word filler zeros
669
 
15796 fschmid 670
        ASSERT(sigPos <= bufferSize);
671
        ASSERT(refPos <= bufferSize);
672
        ASSERT(signLen <= bufferSize);
673
        ASSERT(valuePos == bufferSize);
16771 fschmid 674
        ASSERT(codePos >= outStartPos && codePos < CodeBufferBitLen);
675
        codeLen = codePos - outStartPos;
15796 fschmid 676
 
677
        return sigPos;
678
}
679
 
680
 
681
///////////////////////////////////////////////////////
682
// Compute number of bit planes needed
16771 fschmid 683
UINT8 CEncoder::CMacroBlock::NumberOfBitplanes() {
15796 fschmid 684
        UINT8 cnt = 0;
685
 
686
        // determine number of bitplanes for max value
687
        if (m_maxAbsValue > 0) {
688
                while (m_maxAbsValue > 0) {
689
                        m_maxAbsValue >>= 1; cnt++;
690
                }
691
                if (cnt == MaxBitPlanes + 1) cnt = 0;
692
                // end cs
693
                ASSERT(cnt <= MaxBitPlanes);
694
                ASSERT((cnt >> MaxBitPlanesLog) == 0);
695
                return cnt;
696
        } else {
697
                return 1;
698
        }
699
}
700
 
701
//////////////////////////////////////////////////////
702
// Adaptive Run-Length encoder for long sequences of ones.
703
// Returns length of output in bits.
704
// - Encode run of 2^k ones by a single 1.
705
// - Encode run of count 1's followed by a 0 with codeword: 0<count>.
16771 fschmid 706
// - Store each bit in m_codeBuffer[codePos] and increment codePos.
707
UINT32 CEncoder::CMacroBlock::RLESigns(UINT32 codePos, UINT32* signBits, UINT32 signLen) {
15796 fschmid 708
        ASSERT(signBits);
16771 fschmid 709
        ASSERT(0 <= codePos && codePos < CodeBufferBitLen);
15796 fschmid 710
        ASSERT(0 < signLen && signLen <= BufferSize);
16771 fschmid 711
 
712
        const UINT32  outStartPos = codePos;
15796 fschmid 713
        UINT32 k = 0;
714
        UINT32 runlen = 1 << k; // = 2^k
715
        UINT32 count = 0;
716
        UINT32 signPos = 0;
717
 
718
        while (signPos < signLen) {
719
                // search next 0 in signBits starting at position signPos
720
                count = SeekBit1Range(signBits, signPos, __min(runlen, signLen - signPos));
721
                // count 1's found
722
                if (count == runlen) {
723
                        // encode run of 2^k ones by a single 1
16771 fschmid 724
                        signPos += count;
725
                        SetBit(m_codeBuffer, codePos++);
15796 fschmid 726
                        // adapt k (double the 1's run-length)
727
                        if (k < WordWidth) {
16771 fschmid 728
                                k++;
15796 fschmid 729
                                runlen <<= 1;
730
                        }
731
                } else {
732
                        // encode run of count 1's followed by a 0
733
                        // with codeword: 0(count)
734
                        signPos += count + 1;
16771 fschmid 735
                        ClearBit(m_codeBuffer, codePos++);
15796 fschmid 736
                        if (k > 0) {
16771 fschmid 737
                                SetValueBlock(m_codeBuffer, codePos, count, k);
738
                                codePos += k;
15796 fschmid 739
                        }
740
                        // adapt k (half the 1's run-length)
741
                        if (k > 0) {
16771 fschmid 742
                                k--;
15796 fschmid 743
                                runlen >>= 1;
744
                        }
745
                }
746
        }
747
        ASSERT(signPos == signLen || signPos == signLen + 1);
16771 fschmid 748
        ASSERT(codePos >= outStartPos && codePos < CodeBufferBitLen);
749
        return codePos - outStartPos;
15796 fschmid 750
}
751
 
752
//////////////////////////////////////////////////////
753
#ifdef TRACE
754
void CEncoder::DumpBuffer() const {
16771 fschmid 755
        //printf("\nDump\n");
756
        //for (UINT32 i=0; i < BufferSize; i++) {
757
        //      printf("%d", m_value[i]);
758
        //}
759
        //printf("\n");
15796 fschmid 760
}
761
#endif //TRACE
762
 
763