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: 2006-06-04 22:05:59 +0200 (So, 04 Jun 2006) $
5
 * $Revision: 229 $
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 Subband.cpp
26
/// @brief PGF wavelet subband class implementation
27
/// @author C. Stamm
28
 
15796 fschmid 29
#include "Subband.h"
30
#include "Encoder.h"
31
#include "Decoder.h"
32
 
33
/////////////////////////////////////////////////////////////////////
34
// Default constructor
35
CSubband::CSubband() : m_size(0), m_data(0)
36
#ifdef __PGFROISUPPORT__
16771 fschmid 37
, m_ROIs(0), m_dataWidth(0)
15796 fschmid 38
#endif
39
{
40
}
41
 
42
/////////////////////////////////////////////////////////////////////
43
// Destructor
44
CSubband::~CSubband() {
45
        FreeMemory();
46
}
47
 
48
/////////////////////////////////////////////////////////////////////
49
// Initialize subband parameters
50
void CSubband::Initialize(UINT32 width, UINT32 height, int level, Orientation orient) {
51
        m_width = width;
52
        m_height = height;
53
        m_size = m_width*m_height;
54
        m_level = level;
55
        m_orientation = orient;
56
        m_data = 0;
57
        m_dataPos = 0;
58
#ifdef __PGFROISUPPORT__
16771 fschmid 59
        m_ROIs = 0;
15796 fschmid 60
        m_dataWidth = width;
61
#endif
62
}
63
 
64
 
65
/////////////////////////////////////////////////////////////////////
66
// Allocate a memory buffer to store all wavelet coefficients of this subband.
67
// @return True if the allocation did work without any problems
68
bool CSubband::AllocMemory() {
69
        UINT32 oldSize = m_size;
70
 
71
#ifdef __PGFROISUPPORT__
72
        if (m_ROIs) {
73
                // reset dataWidth and size
74
                const PGFRect& roi = m_ROIs->GetROI(m_level);
75
                m_dataWidth = __min(m_width, roi.right) - roi.left;
76
                ASSERT(m_dataWidth > 0);
77
                m_size = m_dataWidth*(__min(m_height, roi.bottom) - roi.top);
78
        }
79
#endif
80
        ASSERT(m_size > 0);
81
 
82
        if (m_data) {
83
                if (oldSize >= m_size) {
84
                        return false;
85
                } else {
86
                        delete[] m_data;
87
                        m_data = new DataT[m_size];
88
                        return (m_data != 0);
89
                }
90
        } else {
91
                m_data = new DataT[m_size];
92
                return (m_data != 0);
93
        }
94
}
95
 
96
/////////////////////////////////////////////////////////////////////
97
// Delete the memory buffer of this subband.
98
void CSubband::FreeMemory() {
99
        if (m_data) {
100
                delete[] m_data; m_data = 0;
101
        }
102
}
103
 
104
/////////////////////////////////////////////////////////////////////
105
// Perform subband quantization with given quantization parameter.
106
// A scalar quantization (with dead-zone) is used. A large quantization value
107
// results in strong quantization and therefore in big quality loss.
108
// @param quantParam A quantization parameter (larger or equal to 0)
109
void CSubband::Quantize(int quantParam) {
110
        if (m_orientation == LL) {
111
                quantParam -= (m_level + 1);
112
                // uniform rounding quantization
113
                if (quantParam > 0) {
114
                        quantParam--;
115
                        for (UINT32 i=0; i < m_size; i++) {
116
                                if (m_data[i] < 0) {
117
                                        m_data[i] = -(((-m_data[i] >> quantParam) + 1) >> 1);
118
                                } else {
119
                                        m_data[i] = ((m_data[i] >> quantParam) + 1) >> 1;
120
                                }
121
                        }
122
                }
123
        } else {
124
                if (m_orientation == HH) {
125
                        quantParam -= (m_level - 1);
126
                } else {
127
                        quantParam -= m_level;
128
                }
129
                // uniform deadzone quantization
130
                if (quantParam > 0) {
131
                        int threshold = ((1 << quantParam) * 7)/5;      // good value
132
                        quantParam--;
133
                        for (UINT32 i=0; i < m_size; i++) {
134
                                if (m_data[i] < -threshold) {
135
                                        m_data[i] = -(((-m_data[i] >> quantParam) + 1) >> 1);
136
                                } else if (m_data[i] > threshold) {
137
                                        m_data[i] = ((m_data[i] >> quantParam) + 1) >> 1;
138
                                } else {
139
                                        m_data[i] = 0;
140
                                }
141
                        }
142
                }
143
        }
144
}
145
 
146
//////////////////////////////////////////////////////////////////////
147
/// Perform subband dequantization with given quantization parameter.
148
/// A scalar quantization (with dead-zone) is used. A large quantization value
149
/// results in strong quantization and therefore in big quality loss.
150
/// @param quantParam A quantization parameter (larger or equal to 0)
16771 fschmid 151
void CSubband::Dequantize(int quantParam) {
15796 fschmid 152
        if (m_orientation == LL) {
153
                quantParam -= m_level + 1;
154
        } else if (m_orientation == HH) {
155
                quantParam -= m_level - 1;
156
        } else {
157
                quantParam -= m_level;
158
        }
159
        if (quantParam > 0) {
160
                for (UINT32 i=0; i < m_size; i++) {
161
                        m_data[i] <<= quantParam;
162
                }
163
        }
164
}
165
 
166
/////////////////////////////////////////////////////////////////////
167
/// Extracts a rectangular subregion of this subband.
168
/// Write wavelet coefficients into buffer.
169
/// It might throw an IOException.
170
/// @param encoder An encoder instance
171
/// @param quant A quantization value (linear scalar quantization)
172
/// @param tile True if just a rectangular region is extracted, false if the entire subband is extracted.
173
/// @param tileX Tile index in x-direction
174
/// @param tileY Tile index in y-direction
175
void CSubband::ExtractTile(CEncoder& encoder, int quant, bool tile /*= false*/, UINT32 tileX /*= 0*/, UINT32 tileY /*= 0*/) THROW_ {
176
        // quantize subband
177
        if (tileX == 0 && tileY == 0) Quantize(quant);
178
 
179
#ifdef __PGFROISUPPORT__
180
        if (tile) {
181
                // compute tile position and size
182
                UINT32 xPos, yPos, w, h;
183
                TilePosition(tileX, tileY, xPos, yPos, w, h);
184
 
185
                // write values into buffer using partitiong scheme
186
                encoder.Partition(this, w, h, xPos + yPos*m_width, m_width);
16771 fschmid 187
        } else
15796 fschmid 188
#endif
189
        {
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
203
void CSubband::PlaceTile(CDecoder& decoder, int quantParam, bool tile /*= false*/, UINT32 tileX /*= 0*/, UINT32 tileY /*= 0*/) THROW_ {
204
        // allocate memory
205
        AllocMemory();
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
                // compute tile position and size
220
                const PGFRect& roi = m_ROIs->GetROI(m_level);
221
                UINT32 xPos, yPos, w, h;
222
                TilePosition(tileX, tileY, xPos, yPos, w, h);
223
 
224
                // read values into buffer using partitiong scheme
225
                decoder.Partition(this, quantParam, w, h, (xPos - roi.left) + (yPos - roi.top)*m_dataWidth, m_dataWidth);
16771 fschmid 226
        } else
15796 fschmid 227
#endif
228
        {
229
                // read values into buffer using partitiong scheme
230
                decoder.Partition(this, quantParam, m_width, m_height, 0, m_width);
231
        }
232
}
233
 
234
 
235
 
236
#ifdef __PGFROISUPPORT__
237
//////////////////////////////////////////////////////////////////////
238
/// Compute tile position and size.
239
/// @param tileX Tile index in x-direction
240
/// @param tileY Tile index in y-direction
241
/// @param xPos [out] Offset to left
242
/// @param yPos [out] Offset to top
243
/// @param w [out] Tile width
244
/// @param h [out] Tile height
245
void CSubband::TilePosition(UINT32 tileX, UINT32 tileY, UINT32& xPos, UINT32& yPos, UINT32& w, UINT32& h) const {
246
        // example
247
        // band = HH, w = 30, ldTiles = 2 -> 4 tiles in a row/column
248
        // --> tile widths
249
        // 8 7 8 7
16771 fschmid 250
        //
15796 fschmid 251
        // tile partitioning scheme
252
        // 0 1 2 3
253
        // 4 5 6 7
254
        // 8 9 A B
255
        // C D E F
256
 
257
        UINT32 nTiles = m_ROIs->GetNofTiles(m_level);
258
        ASSERT(tileX < nTiles); ASSERT(tileY < nTiles);
259
        UINT32 m;
260
        UINT32 left = 0, right = nTiles;
261
        UINT32 top = 0, bottom = nTiles;
262
 
263
        xPos = 0;
264
        yPos = 0;
265
        w = m_width;
266
        h = m_height;
267
 
268
        while (nTiles > 1) {
269
                // compute xPos and w with binary search
270
                m = (left + right) >> 1;
271
                if (tileX >= m) {
272
                        xPos += (w + 1) >> 1;
273
                        w >>= 1;
274
                        left = m;
275
                } else {
276
                        w = (w + 1) >> 1;
277
                        right = m;
278
                }
279
                // compute yPos and h with binary search
280
                m = (top + bottom) >> 1;
281
                if (tileY >= m) {
282
                        yPos += (h + 1) >> 1;
283
                        h >>= 1;
284
                        top = m;
285
                } else {
286
                        h = (h + 1) >> 1;
287
                        bottom = m;
288
                }
289
                nTiles >>= 1;
290
        }
291
        ASSERT(xPos < m_width && (xPos + w <= m_width));
292
        ASSERT(yPos < m_height && (yPos + h <= m_height));
293
}
294
 
295
#endif