libpgf
6.12.24
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() 00036 : m_size(0) 00037 , m_data(0) 00038 #ifdef __PGFROISUPPORT__ 00039 , m_nTiles(0) 00040 #endif 00041 { 00042 } 00043 00045 // Destructor 00046 CSubband::~CSubband() { 00047 FreeMemory(); 00048 } 00049 00051 // Initialize subband parameters 00052 void CSubband::Initialize(UINT32 width, UINT32 height, int level, Orientation orient) { 00053 m_width = width; 00054 m_height = height; 00055 m_size = m_width*m_height; 00056 m_level = level; 00057 m_orientation = orient; 00058 m_data = 0; 00059 m_dataPos = 0; 00060 #ifdef __PGFROISUPPORT__ 00061 m_ROI.left = 0; 00062 m_ROI.top = 0; 00063 m_ROI.right = m_width; 00064 m_ROI.bottom = m_height; 00065 m_nTiles = 0; 00066 #endif 00067 } 00068 00070 // Allocate a memory buffer to store all wavelet coefficients of this subband. 00071 // @return True if the allocation works without any problems 00072 bool CSubband::AllocMemory() { 00073 UINT32 oldSize = m_size; 00074 00075 #ifdef __PGFROISUPPORT__ 00076 m_size = BufferWidth()*m_ROI.Height(); 00077 #endif 00078 ASSERT(m_size > 0); 00079 00080 if (m_data) { 00081 if (oldSize >= m_size) { 00082 return true; 00083 } else { 00084 delete[] m_data; 00085 m_data = new(std::nothrow) DataT[m_size]; 00086 return (m_data != 0); 00087 } 00088 } else { 00089 m_data = new(std::nothrow) DataT[m_size]; 00090 return (m_data != 0); 00091 } 00092 } 00093 00095 // Delete the memory buffer of this subband. 00096 void CSubband::FreeMemory() { 00097 if (m_data) { 00098 delete[] m_data; m_data = 0; 00099 } 00100 } 00101 00103 // Perform subband quantization with given quantization parameter. 00104 // A scalar quantization (with dead-zone) is used. A large quantization value 00105 // results in strong quantization and therefore in big quality loss. 00106 // @param quantParam A quantization parameter (larger or equal to 0) 00107 void CSubband::Quantize(int quantParam) { 00108 if (m_orientation == LL) { 00109 quantParam -= (m_level + 1); 00110 // uniform rounding quantization 00111 if (quantParam > 0) { 00112 quantParam--; 00113 for (UINT32 i=0; i < m_size; i++) { 00114 if (m_data[i] < 0) { 00115 m_data[i] = -(((-m_data[i] >> quantParam) + 1) >> 1); 00116 } else { 00117 m_data[i] = ((m_data[i] >> quantParam) + 1) >> 1; 00118 } 00119 } 00120 } 00121 } else { 00122 if (m_orientation == HH) { 00123 quantParam -= (m_level - 1); 00124 } else { 00125 quantParam -= m_level; 00126 } 00127 // uniform deadzone quantization 00128 if (quantParam > 0) { 00129 int threshold = ((1 << quantParam) * 7)/5; // good value 00130 quantParam--; 00131 for (UINT32 i=0; i < m_size; i++) { 00132 if (m_data[i] < -threshold) { 00133 m_data[i] = -(((-m_data[i] >> quantParam) + 1) >> 1); 00134 } else if (m_data[i] > threshold) { 00135 m_data[i] = ((m_data[i] >> quantParam) + 1) >> 1; 00136 } else { 00137 m_data[i] = 0; 00138 } 00139 } 00140 } 00141 } 00142 } 00143 00149 void CSubband::Dequantize(int quantParam) { 00150 if (m_orientation == LL) { 00151 quantParam -= m_level + 1; 00152 } else if (m_orientation == HH) { 00153 quantParam -= m_level - 1; 00154 } else { 00155 quantParam -= m_level; 00156 } 00157 if (quantParam > 0) { 00158 for (UINT32 i=0; i < m_size; i++) { 00159 m_data[i] <<= quantParam; 00160 } 00161 } 00162 } 00163 00172 void CSubband::ExtractTile(CEncoder& encoder, bool tile /*= false*/, UINT32 tileX /*= 0*/, UINT32 tileY /*= 0*/) THROW_ { 00173 #ifdef __PGFROISUPPORT__ 00174 if (tile) { 00175 // compute tile position and size 00176 UINT32 xPos, yPos, w, h; 00177 TilePosition(tileX, tileY, xPos, yPos, w, h); 00178 00179 // write values into buffer using partitiong scheme 00180 encoder.Partition(this, w, h, xPos + yPos*m_width, m_width); 00181 } else 00182 #endif 00183 { 00184 // write values into buffer using partitiong scheme 00185 encoder.Partition(this, m_width, m_height, 0, m_width); 00186 } 00187 } 00188 00197 void CSubband::PlaceTile(CDecoder& decoder, int quantParam, bool tile /*= false*/, UINT32 tileX /*= 0*/, UINT32 tileY /*= 0*/) THROW_ { 00198 // allocate memory 00199 if (!AllocMemory()) ReturnWithError(InsufficientMemory); 00200 00201 // correct quantParam with normalization factor 00202 if (m_orientation == LL) { 00203 quantParam -= m_level + 1; 00204 } else if (m_orientation == HH) { 00205 quantParam -= m_level - 1; 00206 } else { 00207 quantParam -= m_level; 00208 } 00209 if (quantParam < 0) quantParam = 0; 00210 00211 #ifdef __PGFROISUPPORT__ 00212 if (tile) { 00213 UINT32 xPos, yPos, w, h; 00214 00215 // compute tile position and size 00216 TilePosition(tileX, tileY, xPos, yPos, w, h); 00217 00218 ASSERT(xPos >= m_ROI.left && yPos >= m_ROI.top); 00219 decoder.Partition(this, quantParam, w, h, (xPos - m_ROI.left) + (yPos - m_ROI.top)*BufferWidth(), BufferWidth()); 00220 } else 00221 #endif 00222 { 00223 // read values into buffer using partitiong scheme 00224 decoder.Partition(this, quantParam, m_width, m_height, 0, m_width); 00225 } 00226 } 00227 00228 00229 00230 #ifdef __PGFROISUPPORT__ 00231 00232 00233 00234 00235 00236 00237 00238 00239 void CSubband::TilePosition(UINT32 tileX, UINT32 tileY, UINT32& xPos, UINT32& yPos, UINT32& w, UINT32& h) const { 00240 // example 00241 // band = HH, w = 30, ldTiles = 2 -> 4 tiles in a row/column 00242 // --> tile widths 00243 // 8 7 8 7 00244 // 00245 // tile partitioning scheme 00246 // 0 1 2 3 00247 // 4 5 6 7 00248 // 8 9 A B 00249 // C D E F 00250 00251 UINT32 nTiles = m_nTiles; 00252 ASSERT(tileX < nTiles); ASSERT(tileY < nTiles); 00253 UINT32 m; 00254 UINT32 left = 0, right = nTiles; 00255 UINT32 top = 0, bottom = nTiles; 00256 00257 xPos = 0; 00258 yPos = 0; 00259 w = m_width; 00260 h = m_height; 00261 00262 while (nTiles > 1) { 00263 // compute xPos and w with binary search 00264 m = (left + right) >> 1; 00265 if (tileX >= m) { 00266 xPos += (w + 1) >> 1; 00267 w >>= 1; 00268 left = m; 00269 } else { 00270 w = (w + 1) >> 1; 00271 right = m; 00272 } 00273 // compute yPos and h with binary search 00274 m = (top + bottom) >> 1; 00275 if (tileY >= m) { 00276 yPos += (h + 1) >> 1; 00277 h >>= 1; 00278 top = m; 00279 } else { 00280 h = (h + 1) >> 1; 00281 bottom = m; 00282 } 00283 nTiles >>= 1; 00284 } 00285 ASSERT(xPos < m_width && (xPos + w <= m_width)); 00286 ASSERT(yPos < m_height && (yPos + h <= m_height)); 00287 } 00288 00289 #endif