libpgf
6.11.42
PGF - Progressive Graphics File
|
00001 /* 00002 * The Progressive Graphics File; http://www.libpgf.org 00003 * 00004 * $Date: 2006-06-04 22:05:59 +0200 (So, 04 Jun 2006) $ 00005 * $Revision: 229 $ 00006 * 00007 * This file Copyright (C) 2006 xeraina GmbH, Switzerland 00008 * 00009 * This program is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE 00011 * as published by the Free Software Foundation; either version 2.1 00012 * of the License, or (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software 00021 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00022 */ 00023 00028 00029 #include "Subband.h" 00030 #include "Encoder.h" 00031 #include "Decoder.h" 00032 00034 // Default constructor 00035 CSubband::CSubband() : m_size(0), m_data(0) 00036 #ifdef __PGFROISUPPORT__ 00037 , m_ROIs(0), m_dataWidth(0) 00038 #endif 00039 { 00040 } 00041 00043 // Destructor 00044 CSubband::~CSubband() { 00045 FreeMemory(); 00046 } 00047 00049 // Initialize subband parameters 00050 void CSubband::Initialize(UINT32 width, UINT32 height, int level, Orientation orient) { 00051 m_width = width; 00052 m_height = height; 00053 m_size = m_width*m_height; 00054 m_level = level; 00055 m_orientation = orient; 00056 m_data = 0; 00057 m_dataPos = 0; 00058 #ifdef __PGFROISUPPORT__ 00059 m_ROIs = 0; 00060 m_dataWidth = width; 00061 #endif 00062 } 00063 00064 00066 // Allocate a memory buffer to store all wavelet coefficients of this subband. 00067 // @return True if the allocation did work without any problems 00068 bool CSubband::AllocMemory() { 00069 UINT32 oldSize = m_size; 00070 00071 #ifdef __PGFROISUPPORT__ 00072 if (m_ROIs) { 00073 // reset dataWidth and size 00074 const PGFRect& roi = m_ROIs->GetROI(m_level); 00075 m_dataWidth = __min(m_width, roi.right) - roi.left; 00076 ASSERT(m_dataWidth > 0); 00077 m_size = m_dataWidth*(__min(m_height, roi.bottom) - roi.top); 00078 } 00079 #endif 00080 ASSERT(m_size > 0); 00081 00082 if (m_data) { 00083 if (oldSize >= m_size) { 00084 return true; 00085 } else { 00086 delete[] m_data; 00087 m_data = new(std::nothrow) DataT[m_size]; 00088 return (m_data != 0); 00089 } 00090 } else { 00091 m_data = new(std::nothrow) DataT[m_size]; 00092 return (m_data != 0); 00093 } 00094 } 00095 00097 // Delete the memory buffer of this subband. 00098 void CSubband::FreeMemory() { 00099 if (m_data) { 00100 delete[] m_data; m_data = 0; 00101 } 00102 } 00103 00105 // Perform subband quantization with given quantization parameter. 00106 // A scalar quantization (with dead-zone) is used. A large quantization value 00107 // results in strong quantization and therefore in big quality loss. 00108 // @param quantParam A quantization parameter (larger or equal to 0) 00109 void CSubband::Quantize(int quantParam) { 00110 if (m_orientation == LL) { 00111 quantParam -= (m_level + 1); 00112 // uniform rounding quantization 00113 if (quantParam > 0) { 00114 quantParam--; 00115 for (UINT32 i=0; i < m_size; i++) { 00116 if (m_data[i] < 0) { 00117 m_data[i] = -(((-m_data[i] >> quantParam) + 1) >> 1); 00118 } else { 00119 m_data[i] = ((m_data[i] >> quantParam) + 1) >> 1; 00120 } 00121 } 00122 } 00123 } else { 00124 if (m_orientation == HH) { 00125 quantParam -= (m_level - 1); 00126 } else { 00127 quantParam -= m_level; 00128 } 00129 // uniform deadzone quantization 00130 if (quantParam > 0) { 00131 int threshold = ((1 << quantParam) * 7)/5; // good value 00132 quantParam--; 00133 for (UINT32 i=0; i < m_size; i++) { 00134 if (m_data[i] < -threshold) { 00135 m_data[i] = -(((-m_data[i] >> quantParam) + 1) >> 1); 00136 } else if (m_data[i] > threshold) { 00137 m_data[i] = ((m_data[i] >> quantParam) + 1) >> 1; 00138 } else { 00139 m_data[i] = 0; 00140 } 00141 } 00142 } 00143 } 00144 } 00145 00151 void CSubband::Dequantize(int quantParam) { 00152 if (m_orientation == LL) { 00153 quantParam -= m_level + 1; 00154 } else if (m_orientation == HH) { 00155 quantParam -= m_level - 1; 00156 } else { 00157 quantParam -= m_level; 00158 } 00159 if (quantParam > 0) { 00160 for (UINT32 i=0; i < m_size; i++) { 00161 m_data[i] <<= quantParam; 00162 } 00163 } 00164 } 00165 00174 void CSubband::ExtractTile(CEncoder& encoder, bool tile /*= false*/, UINT32 tileX /*= 0*/, UINT32 tileY /*= 0*/) THROW_ { 00175 #ifdef __PGFROISUPPORT__ 00176 if (tile) { 00177 // compute tile position and size 00178 UINT32 xPos, yPos, w, h; 00179 TilePosition(tileX, tileY, xPos, yPos, w, h); 00180 00181 // write values into buffer using partitiong scheme 00182 encoder.Partition(this, w, h, xPos + yPos*m_width, m_width); 00183 } else 00184 #endif 00185 { 00186 // write values into buffer using partitiong scheme 00187 encoder.Partition(this, m_width, m_height, 0, m_width); 00188 } 00189 } 00190 00199 void CSubband::PlaceTile(CDecoder& decoder, int quantParam, bool tile /*= false*/, UINT32 tileX /*= 0*/, UINT32 tileY /*= 0*/) THROW_ { 00200 // allocate memory 00201 if (!AllocMemory()) ReturnWithError(InsufficientMemory); 00202 00203 // correct quantParam with normalization factor 00204 if (m_orientation == LL) { 00205 quantParam -= m_level + 1; 00206 } else if (m_orientation == HH) { 00207 quantParam -= m_level - 1; 00208 } else { 00209 quantParam -= m_level; 00210 } 00211 if (quantParam < 0) quantParam = 0; 00212 00213 #ifdef __PGFROISUPPORT__ 00214 if (tile) { 00215 // compute tile position and size 00216 const PGFRect& roi = m_ROIs->GetROI(m_level); 00217 UINT32 xPos, yPos, w, h; 00218 TilePosition(tileX, tileY, xPos, yPos, w, h); 00219 00220 // read values into buffer using partitiong scheme 00221 decoder.Partition(this, quantParam, w, h, (xPos - roi.left) + (yPos - roi.top)*m_dataWidth, m_dataWidth); 00222 } else 00223 #endif 00224 { 00225 // read values into buffer using partitiong scheme 00226 decoder.Partition(this, quantParam, m_width, m_height, 0, m_width); 00227 } 00228 } 00229 00230 00231 00232 #ifdef __PGFROISUPPORT__ 00233 00234 00235 00236 00237 00238 00239 00240 00241 void CSubband::TilePosition(UINT32 tileX, UINT32 tileY, UINT32& xPos, UINT32& yPos, UINT32& w, UINT32& h) const { 00242 // example 00243 // band = HH, w = 30, ldTiles = 2 -> 4 tiles in a row/column 00244 // --> tile widths 00245 // 8 7 8 7 00246 // 00247 // tile partitioning scheme 00248 // 0 1 2 3 00249 // 4 5 6 7 00250 // 8 9 A B 00251 // C D E F 00252 00253 UINT32 nTiles = m_ROIs->GetNofTiles(m_level); 00254 ASSERT(tileX < nTiles); ASSERT(tileY < nTiles); 00255 UINT32 m; 00256 UINT32 left = 0, right = nTiles; 00257 UINT32 top = 0, bottom = nTiles; 00258 00259 xPos = 0; 00260 yPos = 0; 00261 w = m_width; 00262 h = m_height; 00263 00264 while (nTiles > 1) { 00265 // compute xPos and w with binary search 00266 m = (left + right) >> 1; 00267 if (tileX >= m) { 00268 xPos += (w + 1) >> 1; 00269 w >>= 1; 00270 left = m; 00271 } else { 00272 w = (w + 1) >> 1; 00273 right = m; 00274 } 00275 // compute yPos and h with binary search 00276 m = (top + bottom) >> 1; 00277 if (tileY >= m) { 00278 yPos += (h + 1) >> 1; 00279 h >>= 1; 00280 top = m; 00281 } else { 00282 h = (h + 1) >> 1; 00283 bottom = m; 00284 } 00285 nTiles >>= 1; 00286 } 00287 ASSERT(xPos < m_width && (xPos + w <= m_width)); 00288 ASSERT(yPos < m_height && (yPos + h <= m_height)); 00289 } 00290 00291 #endif