File indexing completed on 2025-01-19 03:56:11
0001 /* 0002 * The Progressive Graphics File; http://www.libpgf.org 0003 * 0004 * $Date: 2006-05-18 16:03:32 +0200 (Do, 18 Mai 2006) $ 0005 * $Revision: 194 $ 0006 * 0007 * This file Copyright (C) 2006 xeraina GmbH, Switzerland 0008 * 0009 * This program is free software; you can redistribute it and/or 0010 * modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE 0011 * as published by the Free Software Foundation; either version 2.1 0012 * of the License, or (at your option) any later version. 0013 * 0014 * This program is distributed in the hope that it will be useful, 0015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0017 * GNU General Public License for more details. 0018 * 0019 * You should have received a copy of the GNU General Public License 0020 * along with this program; if not, write to the Free Software 0021 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 0022 */ 0023 0024 ////////////////////////////////////////////////////////////////////// 0025 /// @file WaveletTransform.cpp 0026 /// @brief PGF wavelet transform class implementation 0027 /// @author C. Stamm 0028 0029 #include "WaveletTransform.h" 0030 0031 #define c1 1 // best value 1 0032 #define c2 2 // best value 2 0033 0034 ////////////////////////////////////////////////////////////////////////// 0035 // Constructor: Constructs a wavelet transform pyramid of given size and levels. 0036 // @param width The width of the original image (at level 0) in pixels 0037 // @param height The height of the original image (at level 0) in pixels 0038 // @param levels The number of levels (>= 0) 0039 // @param data Input data of subband LL at level 0 0040 CWaveletTransform::CWaveletTransform(UINT32 width, UINT32 height, int levels, DataT* data) 0041 : m_nLevels(levels + 1) // m_nLevels in CPGFImage determines the number of FWT steps; this.m_nLevels determines the number subband-planes 0042 , m_subband(nullptr) 0043 #ifdef __PGFROISUPPORT__ 0044 , m_indices(nullptr) 0045 #endif 0046 { 0047 ASSERT(m_nLevels > 0 && m_nLevels <= MaxLevel + 1); 0048 InitSubbands(width, height, data); 0049 } 0050 0051 ///////////////////////////////////////////////////////////////////// 0052 // Initialize size subbands on all levels 0053 void CWaveletTransform::InitSubbands(UINT32 width, UINT32 height, DataT* data) { 0054 if (m_subband) Destroy(); 0055 0056 // create subbands 0057 m_subband = new CSubband[m_nLevels][NSubbands]; 0058 0059 // init subbands 0060 UINT32 loWidth = width; 0061 UINT32 hiWidth = width; 0062 UINT32 loHeight = height; 0063 UINT32 hiHeight = height; 0064 0065 for (int level = 0; level < m_nLevels; level++) { 0066 m_subband[level][LL].Initialize(loWidth, loHeight, level, LL); // LL 0067 m_subband[level][HL].Initialize(hiWidth, loHeight, level, HL); // HL 0068 m_subband[level][LH].Initialize(loWidth, hiHeight, level, LH); // LH 0069 m_subband[level][HH].Initialize(hiWidth, hiHeight, level, HH); // HH 0070 hiWidth = loWidth >> 1; hiHeight = loHeight >> 1; 0071 loWidth = (loWidth + 1) >> 1; loHeight = (loHeight + 1) >> 1; 0072 } 0073 if (data) { 0074 m_subband[0][LL].SetBuffer(data); 0075 } 0076 } 0077 0078 ////////////////////////////////////////////////////////////////////////// 0079 // Compute fast forward wavelet transform of LL subband at given level and 0080 // stores result in all 4 subbands of level + 1. 0081 // Wavelet transform used in writing a PGF file 0082 // Forward Transform of srcBand and split and store it into subbands on destLevel 0083 // low pass filter at even positions: 1/8[-1, 2, (6), 2, -1] 0084 // high pass filter at odd positions: 1/4[-2, (4), -2] 0085 // @param level A wavelet transform pyramid level (>= 0 && < Levels()) 0086 // @param quant A quantization value (linear scalar quantization) 0087 // @return error in case of a memory allocation problem 0088 OSError CWaveletTransform::ForwardTransform(int level, int quant) { 0089 ASSERT(level >= 0 && level < m_nLevels - 1); 0090 const int destLevel = level + 1; 0091 ASSERT(m_subband[destLevel]); 0092 CSubband* srcBand = &m_subband[level][LL]; ASSERT(srcBand); 0093 const UINT32 width = srcBand->GetWidth(); 0094 const UINT32 height = srcBand->GetHeight(); 0095 DataT* src = srcBand->GetBuffer(); ASSERT(src); 0096 DataT *row0, *row1, *row2, *row3; 0097 0098 // Allocate memory for next transform level 0099 for (int i=0; i < NSubbands; i++) { 0100 if (!m_subband[destLevel][i].AllocMemory()) return InsufficientMemory; 0101 } 0102 0103 if (height >= FilterSize) { // changed from FilterSizeH to FilterSize 0104 // top border handling 0105 row0 = src; row1 = row0 + width; row2 = row1 + width; 0106 ForwardRow(row0, width); 0107 ForwardRow(row1, width); 0108 ForwardRow(row2, width); 0109 for (UINT32 k=0; k < width; k++) { 0110 row1[k] -= ((row0[k] + row2[k] + c1) >> 1); // high pass 0111 row0[k] += ((row1[k] + c1) >> 1); // low pass 0112 } 0113 InterleavedToSubbands(destLevel, row0, row1, width); 0114 row0 = row1; row1 = row2; row2 += width; row3 = row2 + width; 0115 0116 // middle part 0117 for (UINT32 i=3; i < height-1; i += 2) { 0118 ForwardRow(row2, width); 0119 ForwardRow(row3, width); 0120 for (UINT32 k=0; k < width; k++) { 0121 row2[k] -= ((row1[k] + row3[k] + c1) >> 1); // high pass filter 0122 row1[k] += ((row0[k] + row2[k] + c2) >> 2); // low pass filter 0123 } 0124 InterleavedToSubbands(destLevel, row1, row2, width); 0125 row0 = row2; row1 = row3; row2 = row3 + width; row3 = row2 + width; 0126 } 0127 0128 // bottom border handling 0129 if (height & 1) { 0130 for (UINT32 k=0; k < width; k++) { 0131 row1[k] += ((row0[k] + c1) >> 1); // low pass 0132 } 0133 InterleavedToSubbands(destLevel, row1, nullptr, width); 0134 row0 = row1; row1 += width; 0135 } else { 0136 ForwardRow(row2, width); 0137 for (UINT32 k=0; k < width; k++) { 0138 row2[k] -= row1[k]; // high pass 0139 row1[k] += ((row0[k] + row2[k] + c2) >> 2); // low pass 0140 } 0141 InterleavedToSubbands(destLevel, row1, row2, width); 0142 row0 = row1; row1 = row2; row2 += width; 0143 } 0144 } else { 0145 // if height is too small 0146 row0 = src; row1 = row0 + width; 0147 // first part 0148 for (UINT32 k=0; k < height; k += 2) { 0149 ForwardRow(row0, width); 0150 ForwardRow(row1, width); 0151 InterleavedToSubbands(destLevel, row0, row1, width); 0152 row0 += width << 1; row1 += width << 1; 0153 } 0154 // bottom 0155 if (height & 1) { 0156 InterleavedToSubbands(destLevel, row0, nullptr, width); 0157 } 0158 } 0159 0160 if (quant > 0) { 0161 // subband quantization (without LL) 0162 for (int i=1; i < NSubbands; i++) { 0163 m_subband[destLevel][i].Quantize(quant); 0164 } 0165 // LL subband quantization 0166 if (destLevel == m_nLevels - 1) { 0167 m_subband[destLevel][LL].Quantize(quant); 0168 } 0169 } 0170 0171 // free source band 0172 srcBand->FreeMemory(); 0173 return NoError; 0174 } 0175 0176 ////////////////////////////////////////////////////////////// 0177 // Forward transform one row 0178 // low pass filter at even positions: 1/8[-1, 2, (6), 2, -1] 0179 // high pass filter at odd positions: 1/4[-2, (4), -2] 0180 void CWaveletTransform::ForwardRow(DataT* src, UINT32 width) { 0181 if (width >= FilterSize) { 0182 UINT32 i = 3; 0183 0184 // left border handling 0185 src[1] -= ((src[0] + src[2] + c1) >> 1); // high pass 0186 src[0] += ((src[1] + c1) >> 1); // low pass 0187 0188 // middle part 0189 for (; i < width-1; i += 2) { 0190 src[i] -= ((src[i-1] + src[i+1] + c1) >> 1); // high pass 0191 src[i-1] += ((src[i-2] + src[i] + c2) >> 2); // low pass 0192 } 0193 0194 // right border handling 0195 if (width & 1) { 0196 src[i-1] += ((src[i-2] + c1) >> 1); // low pass 0197 } else { 0198 src[i] -= src[i-1]; // high pass 0199 src[i-1] += ((src[i-2] + src[i] + c2) >> 2); // low pass 0200 } 0201 } 0202 } 0203 0204 ///////////////////////////////////////////////////////////////// 0205 // Copy transformed and interleaved (L,H,L,H,...) rows loRow and hiRow to subbands LL,HL,LH,HH 0206 void CWaveletTransform::InterleavedToSubbands(int destLevel, DataT* loRow, DataT* hiRow, UINT32 width) { 0207 const UINT32 wquot = width >> 1; 0208 const bool wrem = (width & 1); 0209 CSubband &ll = m_subband[destLevel][LL], &hl = m_subband[destLevel][HL]; 0210 CSubband &lh = m_subband[destLevel][LH], &hh = m_subband[destLevel][HH]; 0211 0212 if (hiRow) { 0213 for (UINT32 i=0; i < wquot; i++) { 0214 ll.WriteBuffer(*loRow++); // first access, than increment 0215 hl.WriteBuffer(*loRow++); 0216 lh.WriteBuffer(*hiRow++); // first access, than increment 0217 hh.WriteBuffer(*hiRow++); 0218 } 0219 if (wrem) { 0220 ll.WriteBuffer(*loRow); 0221 lh.WriteBuffer(*hiRow); 0222 } 0223 } else { 0224 for (UINT32 i=0; i < wquot; i++) { 0225 ll.WriteBuffer(*loRow++); // first access, than increment 0226 hl.WriteBuffer(*loRow++); 0227 } 0228 if (wrem) ll.WriteBuffer(*loRow); 0229 } 0230 } 0231 0232 ////////////////////////////////////////////////////////////////////////// 0233 // Compute fast inverse wavelet transform of all 4 subbands of given level and 0234 // stores result in LL subband of level - 1. 0235 // Inverse wavelet transform used in reading a PGF file 0236 // Inverse Transform srcLevel and combine to destBand 0237 // low-pass coefficients at even positions, high-pass coefficients at odd positions 0238 // inverse filter for even positions: 1/4[-1, (4), -1] 0239 // inverse filter for odd positions: 1/8[-1, 4, (6), 4, -1] 0240 // @param srcLevel A wavelet transform pyramid level (> 0 && <= Levels()) 0241 // @param w [out] A pointer to the returned width of subband LL (in pixels) 0242 // @param h [out] A pointer to the returned height of subband LL (in pixels) 0243 // @param data [out] A pointer to the returned array of image data 0244 // @return error in case of a memory allocation problem 0245 OSError CWaveletTransform::InverseTransform(int srcLevel, UINT32* w, UINT32* h, DataT** data) { 0246 ASSERT(srcLevel > 0 && srcLevel < m_nLevels); 0247 const int destLevel = srcLevel - 1; 0248 ASSERT(m_subband[destLevel]); 0249 CSubband* destBand = &m_subband[destLevel][LL]; 0250 UINT32 width, height; 0251 0252 // allocate memory for the results of the inverse transform 0253 if (!destBand->AllocMemory()) return InsufficientMemory; 0254 DataT *origin = destBand->GetBuffer(), *row0, *row1, *row2, *row3; 0255 0256 #ifdef __PGFROISUPPORT__ 0257 PGFRect destROI = destBand->GetAlignedROI(); 0258 const UINT32 destWidth = destROI.Width(); // destination buffer width 0259 const UINT32 destHeight = destROI.Height(); // destination buffer height 0260 width = destWidth; // destination working width 0261 height = destHeight; // destination working height 0262 0263 // update destination ROI 0264 if (destROI.top & 1) { 0265 destROI.top++; 0266 origin += destWidth; 0267 height--; 0268 } 0269 if (destROI.left & 1) { 0270 destROI.left++; 0271 origin++; 0272 width--; 0273 } 0274 0275 // init source buffer position 0276 const UINT32 leftD = destROI.left >> 1; 0277 const UINT32 left0 = m_subband[srcLevel][LL].GetAlignedROI().left; 0278 const UINT32 left1 = m_subband[srcLevel][HL].GetAlignedROI().left; 0279 const UINT32 topD = destROI.top >> 1; 0280 const UINT32 top0 = m_subband[srcLevel][LL].GetAlignedROI().top; 0281 const UINT32 top1 = m_subband[srcLevel][LH].GetAlignedROI().top; 0282 ASSERT(m_subband[srcLevel][LH].GetAlignedROI().left == left0); 0283 ASSERT(m_subband[srcLevel][HH].GetAlignedROI().left == left1); 0284 ASSERT(m_subband[srcLevel][HL].GetAlignedROI().top == top0); 0285 ASSERT(m_subband[srcLevel][HH].GetAlignedROI().top == top1); 0286 0287 UINT32 srcOffsetX[2] = { 0, 0 }; 0288 UINT32 srcOffsetY[2] = { 0, 0 }; 0289 0290 if (leftD >= __max(left0, left1)) { 0291 srcOffsetX[0] = leftD - left0; 0292 srcOffsetX[1] = leftD - left1; 0293 } else { 0294 if (left0 <= left1) { 0295 const UINT32 dx = (left1 - leftD) << 1; 0296 destROI.left += dx; 0297 origin += dx; 0298 width -= dx; 0299 srcOffsetX[0] = left1 - left0; 0300 } else { 0301 const UINT32 dx = (left0 - leftD) << 1; 0302 destROI.left += dx; 0303 origin += dx; 0304 width -= dx; 0305 srcOffsetX[1] = left0 - left1; 0306 } 0307 } 0308 if (topD >= __max(top0, top1)) { 0309 srcOffsetY[0] = topD - top0; 0310 srcOffsetY[1] = topD - top1; 0311 } else { 0312 if (top0 <= top1) { 0313 const UINT32 dy = (top1 - topD) << 1; 0314 destROI.top += dy; 0315 origin += dy*destWidth; 0316 height -= dy; 0317 srcOffsetY[0] = top1 - top0; 0318 } else { 0319 const UINT32 dy = (top0 - topD) << 1; 0320 destROI.top += dy; 0321 origin += dy*destWidth; 0322 height -= dy; 0323 srcOffsetY[1] = top0 - top1; 0324 } 0325 } 0326 0327 m_subband[srcLevel][LL].InitBuffPos(srcOffsetX[0], srcOffsetY[0]); 0328 m_subband[srcLevel][HL].InitBuffPos(srcOffsetX[1], srcOffsetY[0]); 0329 m_subband[srcLevel][LH].InitBuffPos(srcOffsetX[0], srcOffsetY[1]); 0330 m_subband[srcLevel][HH].InitBuffPos(srcOffsetX[1], srcOffsetY[1]); 0331 0332 #else 0333 width = destBand->GetWidth(); 0334 height = destBand->GetHeight(); 0335 PGFRect destROI(0, 0, width, height); 0336 const UINT32 destWidth = width; // destination buffer width 0337 const UINT32 destHeight = height; // destination buffer height 0338 0339 // init source buffer position 0340 for (int i = 0; i < NSubbands; i++) { 0341 m_subband[srcLevel][i].InitBuffPos(); 0342 } 0343 #endif 0344 0345 if (destHeight >= FilterSize) { // changed from FilterSizeH to FilterSize 0346 // top border handling 0347 row0 = origin; row1 = row0 + destWidth; 0348 SubbandsToInterleaved(srcLevel, row0, row1, width); 0349 for (UINT32 k = 0; k < width; k++) { 0350 row0[k] -= ((row1[k] + c1) >> 1); // even 0351 } 0352 0353 // middle part 0354 row2 = row1 + destWidth; row3 = row2 + destWidth; 0355 for (UINT32 i = destROI.top + 2; i < destROI.bottom - 1; i += 2) { 0356 SubbandsToInterleaved(srcLevel, row2, row3, width); 0357 for (UINT32 k = 0; k < width; k++) { 0358 row2[k] -= ((row1[k] + row3[k] + c2) >> 2); // even 0359 row1[k] += ((row0[k] + row2[k] + c1) >> 1); // odd 0360 } 0361 InverseRow(row0, width); 0362 InverseRow(row1, width); 0363 row0 = row2; row1 = row3; row2 = row1 + destWidth; row3 = row2 + destWidth; 0364 } 0365 0366 // bottom border handling 0367 if (height & 1) { 0368 SubbandsToInterleaved(srcLevel, row2, nullptr, width); 0369 for (UINT32 k = 0; k < width; k++) { 0370 row2[k] -= ((row1[k] + c1) >> 1); // even 0371 row1[k] += ((row0[k] + row2[k] + c1) >> 1); // odd 0372 } 0373 InverseRow(row0, width); 0374 InverseRow(row1, width); 0375 InverseRow(row2, width); 0376 row0 = row1; row1 = row2; row2 += destWidth; 0377 } else { 0378 for (UINT32 k = 0; k < width; k++) { 0379 row1[k] += row0[k]; 0380 } 0381 InverseRow(row0, width); 0382 InverseRow(row1, width); 0383 row0 = row1; row1 += destWidth; 0384 } 0385 } else { 0386 // height is too small 0387 row0 = origin; row1 = row0 + destWidth; 0388 // first part 0389 for (UINT32 k = 0; k < height; k += 2) { 0390 SubbandsToInterleaved(srcLevel, row0, row1, width); 0391 InverseRow(row0, width); 0392 InverseRow(row1, width); 0393 row0 += destWidth << 1; row1 += destWidth << 1; 0394 } 0395 // bottom 0396 if (height & 1) { 0397 SubbandsToInterleaved(srcLevel, row0, nullptr, width); 0398 InverseRow(row0, width); 0399 } 0400 } 0401 0402 // free memory of the current srcLevel 0403 for (int i = 0; i < NSubbands; i++) { 0404 m_subband[srcLevel][i].FreeMemory(); 0405 } 0406 0407 // return info 0408 *w = destWidth; 0409 *h = destHeight; 0410 *data = destBand->GetBuffer(); 0411 return NoError; 0412 } 0413 0414 ////////////////////////////////////////////////////////////////////// 0415 // Inverse Wavelet Transform of one row 0416 // low-pass coefficients at even positions, high-pass coefficients at odd positions 0417 // inverse filter for even positions: 1/4[-1, (4), -1] 0418 // inverse filter for odd positions: 1/8[-1, 4, (6), 4, -1] 0419 void CWaveletTransform::InverseRow(DataT* dest, UINT32 width) { 0420 if (width >= FilterSize) { 0421 UINT32 i = 2; 0422 0423 // left border handling 0424 dest[0] -= ((dest[1] + c1) >> 1); // even 0425 0426 // middle part 0427 for (; i < width - 1; i += 2) { 0428 dest[i] -= ((dest[i-1] + dest[i+1] + c2) >> 2); // even 0429 dest[i-1] += ((dest[i-2] + dest[i] + c1) >> 1); // odd 0430 } 0431 0432 // right border handling 0433 if (width & 1) { 0434 dest[i] -= ((dest[i-1] + c1) >> 1); // even 0435 dest[i-1] += ((dest[i-2] + dest[i] + c1) >> 1); // odd 0436 } else { 0437 dest[i-1] += dest[i-2]; // odd 0438 } 0439 } 0440 } 0441 0442 /////////////////////////////////////////////////////////////////// 0443 // Copy transformed coefficients from subbands LL,HL,LH,HH to interleaved format (L,H,L,H,...) 0444 void CWaveletTransform::SubbandsToInterleaved(int srcLevel, DataT* loRow, DataT* hiRow, UINT32 width) { 0445 const UINT32 wquot = width >> 1; 0446 const bool wrem = (width & 1); 0447 CSubband &ll = m_subband[srcLevel][LL], &hl = m_subband[srcLevel][HL]; 0448 CSubband &lh = m_subband[srcLevel][LH], &hh = m_subband[srcLevel][HH]; 0449 0450 if (hiRow) { 0451 #ifdef __PGFROISUPPORT__ 0452 const bool storePos = wquot < ll.BufferWidth(); 0453 UINT32 llPos = 0, hlPos = 0, lhPos = 0, hhPos = 0; 0454 0455 if (storePos) { 0456 // save current src buffer positions 0457 llPos = ll.GetBuffPos(); 0458 hlPos = hl.GetBuffPos(); 0459 lhPos = lh.GetBuffPos(); 0460 hhPos = hh.GetBuffPos(); 0461 } 0462 #endif 0463 0464 for (UINT32 i=0; i < wquot; i++) { 0465 *loRow++ = ll.ReadBuffer();// first access, than increment 0466 *loRow++ = hl.ReadBuffer();// first access, than increment 0467 *hiRow++ = lh.ReadBuffer();// first access, than increment 0468 *hiRow++ = hh.ReadBuffer();// first access, than increment 0469 } 0470 0471 if (wrem) { 0472 *loRow++ = ll.ReadBuffer();// first access, than increment 0473 *hiRow++ = lh.ReadBuffer();// first access, than increment 0474 } 0475 0476 #ifdef __PGFROISUPPORT__ 0477 if (storePos) { 0478 // increment src buffer positions 0479 ll.IncBuffRow(llPos); 0480 hl.IncBuffRow(hlPos); 0481 lh.IncBuffRow(lhPos); 0482 hh.IncBuffRow(hhPos); 0483 } 0484 #endif 0485 0486 } else { 0487 #ifdef __PGFROISUPPORT__ 0488 const bool storePos = wquot < ll.BufferWidth(); 0489 UINT32 llPos = 0, hlPos = 0; 0490 0491 if (storePos) { 0492 // save current src buffer positions 0493 llPos = ll.GetBuffPos(); 0494 hlPos = hl.GetBuffPos(); 0495 } 0496 #endif 0497 0498 for (UINT32 i=0; i < wquot; i++) { 0499 *loRow++ = ll.ReadBuffer();// first access, than increment 0500 *loRow++ = hl.ReadBuffer();// first access, than increment 0501 } 0502 if (wrem) *loRow++ = ll.ReadBuffer(); 0503 0504 #ifdef __PGFROISUPPORT__ 0505 if (storePos) { 0506 // increment src buffer positions 0507 ll.IncBuffRow(llPos); 0508 hl.IncBuffRow(hlPos); 0509 } 0510 #endif 0511 } 0512 } 0513 0514 #ifdef __PGFROISUPPORT__ 0515 ////////////////////////////////////////////////////////////////////// 0516 /// Compute and store ROIs for nLevels 0517 /// @param roi rectangular region of interest at level 0 0518 void CWaveletTransform::SetROI(PGFRect roi) { 0519 const UINT32 delta = (FilterSize >> 1) << m_nLevels; 0520 0521 // create tile indices 0522 delete[] m_indices; 0523 m_indices = new PGFRect[m_nLevels]; 0524 0525 // enlarge rect: add margin 0526 roi.left = (roi.left > delta) ? roi.left - delta : 0; 0527 roi.top = (roi.top > delta) ? roi.top - delta : 0; 0528 roi.right += delta; 0529 roi.bottom += delta; 0530 0531 for (int l = 0; l < m_nLevels; l++) { 0532 PGFRect alignedROI; 0533 PGFRect& indices = m_indices[l]; 0534 UINT32 nTiles = GetNofTiles(l); 0535 CSubband& subband = m_subband[l][LL]; 0536 0537 // use roi to determine the necessary tile indices (for all subbands the same) and aligned ROI for LL subband 0538 subband.SetNTiles(nTiles); // must be called before TileIndex() 0539 subband.TileIndex(true, roi.left, roi.top, indices.left, indices.top, alignedROI.left, alignedROI.top); 0540 subband.TileIndex(false, roi.right, roi.bottom, indices.right, indices.bottom, alignedROI.right, alignedROI.bottom); 0541 subband.SetAlignedROI(alignedROI); 0542 ASSERT(l == 0 || 0543 (m_indices[l-1].left >= 2*m_indices[l].left && 0544 m_indices[l-1].top >= 2*m_indices[l].top && 0545 m_indices[l-1].right <= 2*m_indices[l].right && 0546 m_indices[l-1].bottom <= 2*m_indices[l].bottom)); 0547 0548 // determine aligned ROI of other three subbands 0549 PGFRect aroi; 0550 UINT32 w, h; 0551 for (int b = 1; b < NSubbands; b++) { 0552 CSubband& sb = m_subband[l][b]; 0553 sb.SetNTiles(nTiles); // must be called before TilePosition() 0554 sb.TilePosition(indices.left, indices.top, aroi.left, aroi.top, w, h); 0555 sb.TilePosition(indices.right - 1, indices.bottom - 1, aroi.right, aroi.bottom, w, h); 0556 aroi.right += w; 0557 aroi.bottom += h; 0558 sb.SetAlignedROI(aroi); 0559 } 0560 0561 // use aligned ROI of LL subband for next level 0562 roi.left = alignedROI.left >> 1; 0563 roi.top = alignedROI.top >> 1; 0564 roi.right = (alignedROI.right + 1) >> 1; 0565 roi.bottom = (alignedROI.bottom + 1) >> 1; 0566 } 0567 } 0568 0569 #endif // __PGFROISUPPORT__