libpgf  6.11.42
PGF - Progressive Graphics File
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Subband.cpp
Go to the documentation of this file.
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 
28 
29 #include "Subband.h"
30 #include "Encoder.h"
31 #include "Decoder.h"
32 
34 // Default constructor
35 CSubband::CSubband() : m_size(0), m_data(0)
36 #ifdef __PGFROISUPPORT__
37 , m_ROIs(0), m_dataWidth(0)
38 #endif
39 {
40 }
41 
43 // Destructor
45  FreeMemory();
46 }
47 
49 // Initialize subband parameters
50 void CSubband::Initialize(UINT32 width, UINT32 height, int level, Orientation orient) {
51  m_width = width;
52  m_height = height;
54  m_level = level;
55  m_orientation = orient;
56  m_data = 0;
57  m_dataPos = 0;
58 #ifdef __PGFROISUPPORT__
59  m_ROIs = 0;
60  m_dataWidth = width;
61 #endif
62 }
63 
64 
66 // Allocate a memory buffer to store all wavelet coefficients of this subband.
67 // @return True if the allocation did work without any problems
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 true;
85  } else {
86  delete[] m_data;
87  m_data = new(std::nothrow) DataT[m_size];
88  return (m_data != 0);
89  }
90  } else {
91  m_data = new(std::nothrow) DataT[m_size];
92  return (m_data != 0);
93  }
94 }
95 
97 // Delete the memory buffer of this subband.
99  if (m_data) {
100  delete[] m_data; m_data = 0;
101  }
102 }
103 
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 
151 void CSubband::Dequantize(int quantParam) {
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 
174 void CSubband::ExtractTile(CEncoder& encoder, bool tile /*= false*/, UINT32 tileX /*= 0*/, UINT32 tileY /*= 0*/) THROW_ {
175 #ifdef __PGFROISUPPORT__
176  if (tile) {
177  // compute tile position and size
178  UINT32 xPos, yPos, w, h;
179  TilePosition(tileX, tileY, xPos, yPos, w, h);
180 
181  // write values into buffer using partitiong scheme
182  encoder.Partition(this, w, h, xPos + yPos*m_width, m_width);
183  } else
184 #endif
185  {
186  // write values into buffer using partitiong scheme
187  encoder.Partition(this, m_width, m_height, 0, m_width);
188  }
189 }
190 
199 void CSubband::PlaceTile(CDecoder& decoder, int quantParam, bool tile /*= false*/, UINT32 tileX /*= 0*/, UINT32 tileY /*= 0*/) THROW_ {
200  // allocate memory
201  if (!AllocMemory()) ReturnWithError(InsufficientMemory);
202 
203  // correct quantParam with normalization factor
204  if (m_orientation == LL) {
205  quantParam -= m_level + 1;
206  } else if (m_orientation == HH) {
207  quantParam -= m_level - 1;
208  } else {
209  quantParam -= m_level;
210  }
211  if (quantParam < 0) quantParam = 0;
212 
213 #ifdef __PGFROISUPPORT__
214  if (tile) {
215  // compute tile position and size
216  const PGFRect& roi = m_ROIs->GetROI(m_level);
217  UINT32 xPos, yPos, w, h;
218  TilePosition(tileX, tileY, xPos, yPos, w, h);
219 
220  // read values into buffer using partitiong scheme
221  decoder.Partition(this, quantParam, w, h, (xPos - roi.left) + (yPos - roi.top)*m_dataWidth, m_dataWidth);
222  } else
223 #endif
224  {
225  // read values into buffer using partitiong scheme
226  decoder.Partition(this, quantParam, m_width, m_height, 0, m_width);
227  }
228 }
229 
230 
231 
232 #ifdef __PGFROISUPPORT__
233 
234 
235 
236 
237 
238 
239 
240 
241 void CSubband::TilePosition(UINT32 tileX, UINT32 tileY, UINT32& xPos, UINT32& yPos, UINT32& w, UINT32& h) const {
242  // example
243  // band = HH, w = 30, ldTiles = 2 -> 4 tiles in a row/column
244  // --> tile widths
245  // 8 7 8 7
246  //
247  // tile partitioning scheme
248  // 0 1 2 3
249  // 4 5 6 7
250  // 8 9 A B
251  // C D E F
252 
253  UINT32 nTiles = m_ROIs->GetNofTiles(m_level);
254  ASSERT(tileX < nTiles); ASSERT(tileY < nTiles);
255  UINT32 m;
256  UINT32 left = 0, right = nTiles;
257  UINT32 top = 0, bottom = nTiles;
258 
259  xPos = 0;
260  yPos = 0;
261  w = m_width;
262  h = m_height;
263 
264  while (nTiles > 1) {
265  // compute xPos and w with binary search
266  m = (left + right) >> 1;
267  if (tileX >= m) {
268  xPos += (w + 1) >> 1;
269  w >>= 1;
270  left = m;
271  } else {
272  w = (w + 1) >> 1;
273  right = m;
274  }
275  // compute yPos and h with binary search
276  m = (top + bottom) >> 1;
277  if (tileY >= m) {
278  yPos += (h + 1) >> 1;
279  h >>= 1;
280  top = m;
281  } else {
282  h = (h + 1) >> 1;
283  bottom = m;
284  }
285  nTiles >>= 1;
286  }
287  ASSERT(xPos < m_width && (xPos + w <= m_width));
288  ASSERT(yPos < m_height && (yPos + h <= m_height));
289 }
290 
291 #endif