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 |