Subversion Repositories Scribus

Rev

Rev 19726 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
19721 fschmid 1
/*
2
 * The Progressive Graphics File; http://www.libpgf.org
3
 *
4
 * $Date: 2006-06-04 22:05:59 +0200 (So, 04 Jun 2006) $
5
 * $Revision: 229 $
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
 
24
//////////////////////////////////////////////////////////////////////
25
/// @file Subband.cpp
26
/// @brief PGF wavelet subband class implementation
27
/// @author C. Stamm
28
 
29
#include "Subband.h"
30
#include "Encoder.h"
31
#include "Decoder.h"
32
 
33
/////////////////////////////////////////////////////////////////////
34
// Default constructor
35
CSubband::CSubband()
36
: m_width(0)
37
, m_height(0)
38
, m_size(0)
39
, m_level(0)
40
, m_orientation(LL)
23713 jghali 41
, m_data(0)
19726 fschmid 42
, m_dataPos(0)
19721 fschmid 43
#ifdef __PGFROISUPPORT__
44
, m_nTiles(0)
45
#endif
46
{
47
}
48
 
49
/////////////////////////////////////////////////////////////////////
50
// Destructor
51
CSubband::~CSubband() {
52
        FreeMemory();
53
}
54
 
55
/////////////////////////////////////////////////////////////////////
56
// Initialize subband parameters
57
void CSubband::Initialize(UINT32 width, UINT32 height, int level, Orientation orient) {
58
        m_width = width;
59
        m_height = height;
60
        m_size = m_width*m_height;
61
        m_level = level;
62
        m_orientation = orient;
63
        m_data = 0;
64
        m_dataPos = 0;
65
#ifdef __PGFROISUPPORT__
66
        m_ROI.left = 0;
67
        m_ROI.top = 0;
68
        m_ROI.right = m_width;
69
        m_ROI.bottom = m_height;
70
        m_nTiles = 0;
71
#endif
72
}
73
 
74
/////////////////////////////////////////////////////////////////////
75
// Allocate a memory buffer to store all wavelet coefficients of this subband.
76
// @return True if the allocation works without any problems
77
bool CSubband::AllocMemory() {
78
        UINT32 oldSize = m_size;
79
 
80
#ifdef __PGFROISUPPORT__
81
        m_size = BufferWidth()*m_ROI.Height();
82
#endif
83
        ASSERT(m_size > 0);
84
 
85
        if (m_data) {
86
                if (oldSize >= m_size) {
87
                        return true;
88
                } else {
89
                        delete[] m_data;
90
                        m_data = new(std::nothrow) DataT[m_size];
91
                        return (m_data != 0);
92
                }
93
        } else {
94
                m_data = new(std::nothrow) DataT[m_size];
95
                return (m_data != 0);
96
        }
97
}
98
 
99
/////////////////////////////////////////////////////////////////////
100
// Delete the memory buffer of this subband.
101
void CSubband::FreeMemory() {
102
        if (m_data) {
103
                delete[] m_data; m_data = 0;
104
        }
105
}
106
 
107
/////////////////////////////////////////////////////////////////////
108
// Perform subband quantization with given quantization parameter.
109
// A scalar quantization (with dead-zone) is used. A large quantization value
110
// results in strong quantization and therefore in big quality loss.
111
// @param quantParam A quantization parameter (larger or equal to 0)
112
void CSubband::Quantize(int quantParam) {
113
        if (m_orientation == LL) {
114
                quantParam -= (m_level + 1);
115
                // uniform rounding quantization
116
                if (quantParam > 0) {
117
                        quantParam--;
118
                        for (UINT32 i=0; i < m_size; i++) {
119
                                if (m_data[i] < 0) {
120
                                        m_data[i] = -(((-m_data[i] >> quantParam) + 1) >> 1);
121
                                } else {
122
                                        m_data[i] = ((m_data[i] >> quantParam) + 1) >> 1;
123
                                }
124
                        }
125
                }
126
        } else {
127
                if (m_orientation == HH) {
128
                        quantParam -= (m_level - 1);
129
                } else {
130
                        quantParam -= m_level;
131
                }
132
                // uniform deadzone quantization
133
                if (quantParam > 0) {
134
                        int threshold = ((1 << quantParam) * 7)/5;      // good value
135
                        quantParam--;
136
                        for (UINT32 i=0; i < m_size; i++) {
137
                                if (m_data[i] < -threshold) {
138
                                        m_data[i] = -(((-m_data[i] >> quantParam) + 1) >> 1);
139
                                } else if (m_data[i] > threshold) {
140
                                        m_data[i] = ((m_data[i] >> quantParam) + 1) >> 1;
141
                                } else {
142
                                        m_data[i] = 0;
143
                                }
144
                        }
145
                }
146
        }
147
}
148
 
149
//////////////////////////////////////////////////////////////////////
150
/// Perform subband dequantization with given quantization parameter.
151
/// A scalar quantization (with dead-zone) is used. A large quantization value
152
/// results in strong quantization and therefore in big quality loss.
153
/// @param quantParam A quantization parameter (larger or equal to 0)
154
void CSubband::Dequantize(int quantParam) {
155
        if (m_orientation == LL) {
156
                quantParam -= m_level + 1;
157
        } else if (m_orientation == HH) {
158
                quantParam -= m_level - 1;
159
        } else {
160
                quantParam -= m_level;
161
        }
162
        if (quantParam > 0) {
163
                for (UINT32 i=0; i < m_size; i++) {
164
                        m_data[i] <<= quantParam;
165
                }
166
        }
167
}
168
 
169
/////////////////////////////////////////////////////////////////////
170
/// Extracts a rectangular subregion of this subband.
171
/// Write wavelet coefficients into buffer.
172
/// It might throw an IOException.
173
/// @param encoder An encoder instance
174
/// @param tile True if just a rectangular region is extracted, false if the entire subband is extracted.
175
/// @param tileX Tile index in x-direction
176
/// @param tileY Tile index in y-direction
23713 jghali 177
void CSubband::ExtractTile(CEncoder& encoder, bool tile /*= false*/, UINT32 tileX /*= 0*/, UINT32 tileY /*= 0*/) {
19721 fschmid 178
#ifdef __PGFROISUPPORT__
179
        if (tile) {
180
                // compute tile position and size
181
                UINT32 xPos, yPos, w, h;
182
                TilePosition(tileX, tileY, xPos, yPos, w, h);
183
 
184
                // write values into buffer using partitiong scheme
185
                encoder.Partition(this, w, h, xPos + yPos*m_width, m_width);
186
        } else
187
#endif
188
        {
23713 jghali 189
                tileX; tileY; tile; // prevents from unreferenced formal parameter warning
19721 fschmid 190
                // write values into buffer using partitiong scheme
191
                encoder.Partition(this, m_width, m_height, 0, m_width);
192
        }
193
}
194
 
195
/////////////////////////////////////////////////////////////////////
196
/// Decoding and dequantization of this subband.
197
/// It might throw an IOException.
198
/// @param decoder A decoder instance
199
/// @param quantParam Dequantization value
200
/// @param tile True if just a rectangular region is placed, false if the entire subband is placed.
201
/// @param tileX Tile index in x-direction
202
/// @param tileY Tile index in y-direction
23713 jghali 203
void CSubband::PlaceTile(CDecoder& decoder, int quantParam, bool tile /*= false*/, UINT32 tileX /*= 0*/, UINT32 tileY /*= 0*/) {
19721 fschmid 204
        // allocate memory
205
        if (!AllocMemory()) ReturnWithError(InsufficientMemory);
206
 
207
        // correct quantParam with normalization factor
208
        if (m_orientation == LL) {
209
                quantParam -= m_level + 1;
210
        } else if (m_orientation == HH) {
211
                quantParam -= m_level - 1;
212
        } else {
213
                quantParam -= m_level;
214
        }
215
        if (quantParam < 0) quantParam = 0;
216
 
217
#ifdef __PGFROISUPPORT__
218
        if (tile) {
219
                UINT32 xPos, yPos, w, h;
220
 
221
                // compute tile position and size
222
                TilePosition(tileX, tileY, xPos, yPos, w, h);
223
 
224
                ASSERT(xPos >= m_ROI.left && yPos >= m_ROI.top);
225
                decoder.Partition(this, quantParam, w, h, (xPos - m_ROI.left) + (yPos - m_ROI.top)*BufferWidth(), BufferWidth());
226
        } else
227
#endif
228
        {
23713 jghali 229
                tileX; tileY; tile; // prevents from unreferenced formal parameter warning
19721 fschmid 230
                // read values into buffer using partitiong scheme
231
                decoder.Partition(this, quantParam, m_width, m_height, 0, m_width);
232
        }
233
}
234
 
235
 
236
 
237
#ifdef __PGFROISUPPORT__
238
//////////////////////////////////////////////////////////////////////
23713 jghali 239
/// Set ROI
240
void CSubband::SetAlignedROI(const PGFRect& roi) {
241
        ASSERT(roi.left <= m_width);
242
        ASSERT(roi.top <= m_height);
243
 
244
        m_ROI = roi;
245
        if (m_ROI.right > m_width) m_ROI.right = m_width;
246
        if (m_ROI.bottom > m_height) m_ROI.bottom = m_height;
247
}
248
 
249
//////////////////////////////////////////////////////////////////////
19721 fschmid 250
/// Compute tile position and size.
251
/// @param tileX Tile index in x-direction
252
/// @param tileY Tile index in y-direction
253
/// @param xPos [out] Offset to left
254
/// @param yPos [out] Offset to top
255
/// @param w [out] Tile width
256
/// @param h [out] Tile height
257
void CSubband::TilePosition(UINT32 tileX, UINT32 tileY, UINT32& xPos, UINT32& yPos, UINT32& w, UINT32& h) const {
23713 jghali 258
        ASSERT(tileX < m_nTiles); ASSERT(tileY < m_nTiles);
19721 fschmid 259
        // example
260
        // band = HH, w = 30, ldTiles = 2 -> 4 tiles in a row/column
261
        // --> tile widths
262
        // 8 7 8 7
263
        // 
264
        // tile partitioning scheme
265
        // 0 1 2 3
266
        // 4 5 6 7
267
        // 8 9 A B
268
        // C D E F
269
 
270
        UINT32 nTiles = m_nTiles;
271
        UINT32 m;
272
        UINT32 left = 0, right = nTiles;
273
        UINT32 top = 0, bottom = nTiles;
274
 
275
        xPos = 0;
276
        yPos = 0;
277
        w = m_width;
278
        h = m_height;
279
 
280
        while (nTiles > 1) {
281
                // compute xPos and w with binary search
282
                m = left + ((right - left) >> 1);
283
                if (tileX >= m) {
284
                        xPos += (w + 1) >> 1;
285
                        w >>= 1;
286
                        left = m;
287
                } else {
288
                        w = (w + 1) >> 1;
289
                        right = m;
290
                }
291
                // compute yPos and h with binary search
292
                m = top + ((bottom - top) >> 1);
293
                if (tileY >= m) {
294
                        yPos += (h + 1) >> 1;
295
                        h >>= 1;
296
                        top = m;
297
                } else {
298
                        h = (h + 1) >> 1;
299
                        bottom = m;
300
                }
301
                nTiles >>= 1;
302
        }
303
        ASSERT(xPos < m_width && (xPos + w <= m_width));
304
        ASSERT(yPos < m_height && (yPos + h <= m_height));
305
}
306
 
23713 jghali 307
//////////////////////////////////////////////////////////////////////
308
/// Compute tile index and extrem position (x,y) of given position (xPos, yPos).
309
void CSubband::TileIndex(bool topLeft, UINT32 xPos, UINT32 yPos, UINT32& tileX, UINT32& tileY, UINT32& x, UINT32& y) const {
310
        UINT32 m;
311
        UINT32 left = 0, right = m_width;
312
        UINT32 top = 0, bottom = m_height;
313
        UINT32 nTiles = m_nTiles;
314
 
315
        if (xPos > m_width) xPos = m_width;
316
        if (yPos > m_height) yPos = m_height;
317
 
318
        if (topLeft) {
319
                // compute tileX with binary search
320
                tileX = 0;
321
                while (nTiles > 1) {
322
                        nTiles >>= 1;
323
                        m = left + ((right - left + 1) >> 1);
324
                        if (xPos < m) {
325
                                // exclusive m
326
                                right = m;
327
                        } else {
328
                                tileX += nTiles;
329
                                left = m;
330
                        }
331
                }
332
                x = left;
333
                ASSERT(tileX >= 0 && tileX < m_nTiles);
334
 
335
                // compute tileY with binary search
336
                nTiles = m_nTiles;
337
                tileY = 0;
338
                while (nTiles > 1) {
339
                        nTiles >>= 1;
340
                        m = top + ((bottom - top + 1) >> 1);
341
                        if (yPos < m) {
342
                                // exclusive m
343
                                bottom = m;
344
                        } else {
345
                                tileY += nTiles;
346
                                top = m;
347
                        }
348
                }
349
                y = top;
350
                ASSERT(tileY >= 0 && tileY < m_nTiles);
351
 
352
        } else {
353
                // compute tileX with binary search
354
                tileX = 1;
355
                while (nTiles > 1) {
356
                        nTiles >>= 1;
357
                        m = left + ((right - left + 1) >> 1);
358
                        if (xPos <= m) {
359
                                // inclusive m
360
                                right = m;
361
                        } else {
362
                                tileX += nTiles;
363
                                left = m;
364
                        }
365
                }
366
                x = right;
367
                ASSERT(tileX > 0 && tileX <= m_nTiles);
368
 
369
                // compute tileY with binary search
370
                nTiles = m_nTiles;
371
                tileY = 1;
372
                while (nTiles > 1) {
373
                        nTiles >>= 1;
374
                        m = top + ((bottom - top + 1) >> 1);
375
                        if (yPos <= m) {
376
                                // inclusive m
377
                                bottom = m;
378
                        } else {
379
                                tileY += nTiles;
380
                                top = m;
381
                        }
382
                }
383
                y = bottom;
384
                ASSERT(tileY > 0 && tileY <= m_nTiles);
385
        }
386
}
387
 
19721 fschmid 388
#endif