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