CWaveletTransform - Man Page
PGF wavelet transform.
Synopsis
#include <WaveletTransform.h>
Public Member Functions
CWaveletTransform (UINT32 width, UINT32 height, int levels, DataT *data=nullptr)
~CWaveletTransform ()
Destructor.
OSError ForwardTransform (int level, int quant)
OSError InverseTransform (int level, UINT32 *width, UINT32 *height, DataT **data)
CSubband * GetSubband (int level, Orientation orientation)
Private Member Functions
void Destroy ()
void InitSubbands (UINT32 width, UINT32 height, DataT *data)
void ForwardRow (DataT *buff, UINT32 width)
void InverseRow (DataT *buff, UINT32 width)
void InterleavedToSubbands (int destLevel, DataT *loRow, DataT *hiRow, UINT32 width)
void SubbandsToInterleaved (int srcLevel, DataT *loRow, DataT *hiRow, UINT32 width)
Private Attributes
int m_nLevels
number of LL levels: one more than header.nLevels in PGFimage
CSubband(* m_subband )[NSubbands]
quadtree of subbands: LL HL LH HH
Friends
class CSubband
Detailed Description
PGF wavelet transform.
PGF wavelet transform class.
- Author
C. Stamm, R. Spuler
Definition at line 55 of file WaveletTransform.h.
Constructor & Destructor Documentation
CWaveletTransform::CWaveletTransform (UINT32 width, UINT32 height, int levels, DataT * data = nullptr)
Constructor: Constructs a wavelet transform pyramid of given size and levels.
- Parameters
width The width of the original image (at level 0) in pixels
height The height of the original image (at level 0) in pixels
levels The number of levels (>= 0)
data Input data of subband LL at level 0
Definition at line 40 of file WaveletTransform.cpp.
41 : m_nLevels(levels + 1) // m_nLevels in CPGFImage determines the number of FWT steps; this.m_nLevels determines the number subband-planes 42 , m_subband(nullptr) 43 #ifdef __PGFROISUPPORT__ 44 , m_indices(nullptr) 45 #endif 46 { 47 ASSERT(m_nLevels > 0 && m_nLevels <= MaxLevel + 1); 48 InitSubbands(width, height, data); 49 }
CWaveletTransform::~CWaveletTransform () [inline]
Destructor.
Definition at line 69 of file WaveletTransform.h.
69 { Destroy(); }
Member Function Documentation
void CWaveletTransform::Destroy () [inline], [private]
Definition at line 125 of file WaveletTransform.h.
125 { 126 delete[] m_subband; m_subband = nullptr; 127 #ifdef __PGFROISUPPORT__ 128 delete[] m_indices; m_indices = nullptr; 129 #endif 130 }
void CWaveletTransform::ForwardRow (DataT * buff, UINT32 width) [private]
Definition at line 180 of file WaveletTransform.cpp.
180 { 181 if (width >= FilterSize) { 182 UINT32 i = 3; 183 184 // left border handling 185 src[1] -= ((src[0] + src[2] + c1) >> 1); // high pass 186 src[0] += ((src[1] + c1) >> 1); // low pass 187 188 // middle part 189 for (; i < width-1; i += 2) { 190 src[i] -= ((src[i-1] + src[i+1] + c1) >> 1); // high pass 191 src[i-1] += ((src[i-2] + src[i] + c2) >> 2); // low pass 192 } 193 194 // right border handling 195 if (width & 1) { 196 src[i-1] += ((src[i-2] + c1) >> 1); // low pass 197 } else { 198 src[i] -= src[i-1]; // high pass 199 src[i-1] += ((src[i-2] + src[i] + c2) >> 2); // low pass 200 } 201 } 202 }
OSError CWaveletTransform::ForwardTransform (int level, int quant)
Compute fast forward wavelet transform of LL subband at given level and stores result in all 4 subbands of level + 1.
- Parameters
level A wavelet transform pyramid level (>= 0 && < Levels())
quant A quantization value (linear scalar quantization)- Returns
error in case of a memory allocation problem
Definition at line 88 of file WaveletTransform.cpp.
88 { 89 ASSERT(level >= 0 && level < m_nLevels - 1); 90 const int destLevel = level + 1; 91 ASSERT(m_subband[destLevel]); 92 CSubband* srcBand = &m_subband[level][LL]; ASSERT(srcBand); 93 const UINT32 width = srcBand->GetWidth(); 94 const UINT32 height = srcBand->GetHeight(); 95 DataT* src = srcBand->GetBuffer(); ASSERT(src); 96 DataT *row0, *row1, *row2, *row3; 97 98 // Allocate memory for next transform level 99 for (int i=0; i < NSubbands; i++) { 100 if (!m_subband[destLevel][i].AllocMemory()) return InsufficientMemory; 101 } 102 103 if (height >= FilterSize) { // changed from FilterSizeH to FilterSize 104 // top border handling 105 row0 = src; row1 = row0 + width; row2 = row1 + width; 106 ForwardRow(row0, width); 107 ForwardRow(row1, width); 108 ForwardRow(row2, width); 109 for (UINT32 k=0; k < width; k++) { 110 row1[k] -= ((row0[k] + row2[k] + c1) >> 1); // high pass 111 row0[k] += ((row1[k] + c1) >> 1); // low pass 112 } 113 InterleavedToSubbands(destLevel, row0, row1, width); 114 row0 = row1; row1 = row2; row2 += width; row3 = row2 + width; 115 116 // middle part 117 for (UINT32 i=3; i < height-1; i += 2) { 118 ForwardRow(row2, width); 119 ForwardRow(row3, width); 120 for (UINT32 k=0; k < width; k++) { 121 row2[k] -= ((row1[k] + row3[k] + c1) >> 1); // high pass filter 122 row1[k] += ((row0[k] + row2[k] + c2) >> 2); // low pass filter 123 } 124 InterleavedToSubbands(destLevel, row1, row2, width); 125 row0 = row2; row1 = row3; row2 = row3 + width; row3 = row2 + width; 126 } 127 128 // bottom border handling 129 if (height & 1) { 130 for (UINT32 k=0; k < width; k++) { 131 row1[k] += ((row0[k] + c1) >> 1); // low pass 132 } 133 InterleavedToSubbands(destLevel, row1, nullptr, width); 134 row0 = row1; row1 += width; 135 } else { 136 ForwardRow(row2, width); 137 for (UINT32 k=0; k < width; k++) { 138 row2[k] -= row1[k]; // high pass 139 row1[k] += ((row0[k] + row2[k] + c2) >> 2); // low pass 140 } 141 InterleavedToSubbands(destLevel, row1, row2, width); 142 row0 = row1; row1 = row2; row2 += width; 143 } 144 } else { 145 // if height is too small 146 row0 = src; row1 = row0 + width; 147 // first part 148 for (UINT32 k=0; k < height; k += 2) { 149 ForwardRow(row0, width); 150 ForwardRow(row1, width); 151 InterleavedToSubbands(destLevel, row0, row1, width); 152 row0 += width << 1; row1 += width << 1; 153 } 154 // bottom 155 if (height & 1) { 156 InterleavedToSubbands(destLevel, row0, nullptr, width); 157 } 158 } 159 160 if (quant > 0) { 161 // subband quantization (without LL) 162 for (int i=1; i < NSubbands; i++) { 163 m_subband[destLevel][i].Quantize(quant); 164 } 165 // LL subband quantization 166 if (destLevel == m_nLevels - 1) { 167 m_subband[destLevel][LL].Quantize(quant); 168 } 169 } 170 171 // free source band 172 srcBand->FreeMemory(); 173 return NoError; 174 }
CSubband * CWaveletTransform::GetSubband (int level, Orientation orientation) [inline]
Get pointer to one of the 4 subband at a given level.
- Parameters
level A wavelet transform pyramid level (>= 0 && <= Levels())
orientation A quarter of the subband (LL, LH, HL, HH)
Definition at line 93 of file WaveletTransform.h.
93 { 94 ASSERT(level >= 0 && level < m_nLevels); 95 return &m_subband[level][orientation]; 96 }
void CWaveletTransform::InitSubbands (UINT32 width, UINT32 height, DataT * data) [private]
Definition at line 53 of file WaveletTransform.cpp.
53 { 54 if (m_subband) Destroy(); 55 56 // create subbands 57 m_subband = new CSubband[m_nLevels][NSubbands]; 58 59 // init subbands 60 UINT32 loWidth = width; 61 UINT32 hiWidth = width; 62 UINT32 loHeight = height; 63 UINT32 hiHeight = height; 64 65 for (int level = 0; level < m_nLevels; level++) { 66 m_subband[level][LL].Initialize(loWidth, loHeight, level, LL); // LL 67 m_subband[level][HL].Initialize(hiWidth, loHeight, level, HL); // HL 68 m_subband[level][LH].Initialize(loWidth, hiHeight, level, LH); // LH 69 m_subband[level][HH].Initialize(hiWidth, hiHeight, level, HH); // HH 70 hiWidth = loWidth >> 1; hiHeight = loHeight >> 1; 71 loWidth = (loWidth + 1) >> 1; loHeight = (loHeight + 1) >> 1; 72 } 73 if (data) { 74 m_subband[0][LL].SetBuffer(data); 75 } 76 }
void CWaveletTransform::InterleavedToSubbands (int destLevel, DataT * loRow, DataT * hiRow, UINT32 width) [private]
Definition at line 206 of file WaveletTransform.cpp.
206 { 207 const UINT32 wquot = width >> 1; 208 const bool wrem = (width & 1); 209 CSubband &ll = m_subband[destLevel][LL], &hl = m_subband[destLevel][HL]; 210 CSubband &lh = m_subband[destLevel][LH], &hh = m_subband[destLevel][HH]; 211 212 if (hiRow) { 213 for (UINT32 i=0; i < wquot; i++) { 214 ll.WriteBuffer(*loRow++); // first access, than increment 215 hl.WriteBuffer(*loRow++); 216 lh.WriteBuffer(*hiRow++); // first access, than increment 217 hh.WriteBuffer(*hiRow++); 218 } 219 if (wrem) { 220 ll.WriteBuffer(*loRow); 221 lh.WriteBuffer(*hiRow); 222 } 223 } else { 224 for (UINT32 i=0; i < wquot; i++) { 225 ll.WriteBuffer(*loRow++); // first access, than increment 226 hl.WriteBuffer(*loRow++); 227 } 228 if (wrem) ll.WriteBuffer(*loRow); 229 } 230 }
void CWaveletTransform::InverseRow (DataT * buff, UINT32 width) [private]
Definition at line 419 of file WaveletTransform.cpp.
419 { 420 if (width >= FilterSize) { 421 UINT32 i = 2; 422 423 // left border handling 424 dest[0] -= ((dest[1] + c1) >> 1); // even 425 426 // middle part 427 for (; i < width - 1; i += 2) { 428 dest[i] -= ((dest[i-1] + dest[i+1] + c2) >> 2); // even 429 dest[i-1] += ((dest[i-2] + dest[i] + c1) >> 1); // odd 430 } 431 432 // right border handling 433 if (width & 1) { 434 dest[i] -= ((dest[i-1] + c1) >> 1); // even 435 dest[i-1] += ((dest[i-2] + dest[i] + c1) >> 1); // odd 436 } else { 437 dest[i-1] += dest[i-2]; // odd 438 } 439 } 440 }
OSError CWaveletTransform::InverseTransform (int level, UINT32 * width, UINT32 * height, DataT ** data)
Compute fast inverse wavelet transform of all 4 subbands of given level and stores result in LL subband of level - 1.
- Parameters
level A wavelet transform pyramid level (> 0 && <= Levels())
width A pointer to the returned width of subband LL (in pixels)
height A pointer to the returned height of subband LL (in pixels)
data A pointer to the returned array of image data- Returns
error in case of a memory allocation problem
Definition at line 245 of file WaveletTransform.cpp.
245 { 246 ASSERT(srcLevel > 0 && srcLevel < m_nLevels); 247 const int destLevel = srcLevel - 1; 248 ASSERT(m_subband[destLevel]); 249 CSubband* destBand = &m_subband[destLevel][LL]; 250 UINT32 width, height; 251 252 // allocate memory for the results of the inverse transform 253 if (!destBand->AllocMemory()) return InsufficientMemory; 254 DataT *origin = destBand->GetBuffer(), *row0, *row1, *row2, *row3; 255 256 #ifdef __PGFROISUPPORT__ 257 PGFRect destROI = destBand->GetAlignedROI(); 258 const UINT32 destWidth = destROI.Width(); // destination buffer width 259 const UINT32 destHeight = destROI.Height(); // destination buffer height 260 width = destWidth; // destination working width 261 height = destHeight; // destination working height 262 263 // update destination ROI 264 if (destROI.top & 1) { 265 destROI.top++; 266 origin += destWidth; 267 height--; 268 } 269 if (destROI.left & 1) { 270 destROI.left++; 271 origin++; 272 width--; 273 } 274 275 // init source buffer position 276 const UINT32 leftD = destROI.left >> 1; 277 const UINT32 left0 = m_subband[srcLevel][LL].GetAlignedROI().left; 278 const UINT32 left1 = m_subband[srcLevel][HL].GetAlignedROI().left; 279 const UINT32 topD = destROI.top >> 1; 280 const UINT32 top0 = m_subband[srcLevel][LL].GetAlignedROI().top; 281 const UINT32 top1 = m_subband[srcLevel][LH].GetAlignedROI().top; 282 ASSERT(m_subband[srcLevel][LH].GetAlignedROI().left == left0); 283 ASSERT(m_subband[srcLevel][HH].GetAlignedROI().left == left1); 284 ASSERT(m_subband[srcLevel][HL].GetAlignedROI().top == top0); 285 ASSERT(m_subband[srcLevel][HH].GetAlignedROI().top == top1); 286 287 UINT32 srcOffsetX[2] = { 0, 0 }; 288 UINT32 srcOffsetY[2] = { 0, 0 }; 289 290 if (leftD >= __max(left0, left1)) { 291 srcOffsetX[0] = leftD - left0; 292 srcOffsetX[1] = leftD - left1; 293 } else { 294 if (left0 <= left1) { 295 const UINT32 dx = (left1 - leftD) << 1; 296 destROI.left += dx; 297 origin += dx; 298 width -= dx; 299 srcOffsetX[0] = left1 - left0; 300 } else { 301 const UINT32 dx = (left0 - leftD) << 1; 302 destROI.left += dx; 303 origin += dx; 304 width -= dx; 305 srcOffsetX[1] = left0 - left1; 306 } 307 } 308 if (topD >= __max(top0, top1)) { 309 srcOffsetY[0] = topD - top0; 310 srcOffsetY[1] = topD - top1; 311 } else { 312 if (top0 <= top1) { 313 const UINT32 dy = (top1 - topD) << 1; 314 destROI.top += dy; 315 origin += dy*destWidth; 316 height -= dy; 317 srcOffsetY[0] = top1 - top0; 318 } else { 319 const UINT32 dy = (top0 - topD) << 1; 320 destROI.top += dy; 321 origin += dy*destWidth; 322 height -= dy; 323 srcOffsetY[1] = top0 - top1; 324 } 325 } 326 327 m_subband[srcLevel][LL].InitBuffPos(srcOffsetX[0], srcOffsetY[0]); 328 m_subband[srcLevel][HL].InitBuffPos(srcOffsetX[1], srcOffsetY[0]); 329 m_subband[srcLevel][LH].InitBuffPos(srcOffsetX[0], srcOffsetY[1]); 330 m_subband[srcLevel][HH].InitBuffPos(srcOffsetX[1], srcOffsetY[1]); 331 332 #else 333 width = destBand->GetWidth(); 334 height = destBand->GetHeight(); 335 PGFRect destROI(0, 0, width, height); 336 const UINT32 destWidth = width; // destination buffer width 337 const UINT32 destHeight = height; // destination buffer height 338 339 // init source buffer position 340 for (int i = 0; i < NSubbands; i++) { 341 m_subband[srcLevel][i].InitBuffPos(); 342 } 343 #endif 344 345 if (destHeight >= FilterSize) { // changed from FilterSizeH to FilterSize 346 // top border handling 347 row0 = origin; row1 = row0 + destWidth; 348 SubbandsToInterleaved(srcLevel, row0, row1, width); 349 for (UINT32 k = 0; k < width; k++) { 350 row0[k] -= ((row1[k] + c1) >> 1); // even 351 } 352 353 // middle part 354 row2 = row1 + destWidth; row3 = row2 + destWidth; 355 for (UINT32 i = destROI.top + 2; i < destROI.bottom - 1; i += 2) { 356 SubbandsToInterleaved(srcLevel, row2, row3, width); 357 for (UINT32 k = 0; k < width; k++) { 358 row2[k] -= ((row1[k] + row3[k] + c2) >> 2); // even 359 row1[k] += ((row0[k] + row2[k] + c1) >> 1); // odd 360 } 361 InverseRow(row0, width); 362 InverseRow(row1, width); 363 row0 = row2; row1 = row3; row2 = row1 + destWidth; row3 = row2 + destWidth; 364 } 365 366 // bottom border handling 367 if (height & 1) { 368 SubbandsToInterleaved(srcLevel, row2, nullptr, width); 369 for (UINT32 k = 0; k < width; k++) { 370 row2[k] -= ((row1[k] + c1) >> 1); // even 371 row1[k] += ((row0[k] + row2[k] + c1) >> 1); // odd 372 } 373 InverseRow(row0, width); 374 InverseRow(row1, width); 375 InverseRow(row2, width); 376 row0 = row1; row1 = row2; row2 += destWidth; 377 } else { 378 for (UINT32 k = 0; k < width; k++) { 379 row1[k] += row0[k]; 380 } 381 InverseRow(row0, width); 382 InverseRow(row1, width); 383 row0 = row1; row1 += destWidth; 384 } 385 } else { 386 // height is too small 387 row0 = origin; row1 = row0 + destWidth; 388 // first part 389 for (UINT32 k = 0; k < height; k += 2) { 390 SubbandsToInterleaved(srcLevel, row0, row1, width); 391 InverseRow(row0, width); 392 InverseRow(row1, width); 393 row0 += destWidth << 1; row1 += destWidth << 1; 394 } 395 // bottom 396 if (height & 1) { 397 SubbandsToInterleaved(srcLevel, row0, nullptr, width); 398 InverseRow(row0, width); 399 } 400 } 401 402 // free memory of the current srcLevel 403 for (int i = 0; i < NSubbands; i++) { 404 m_subband[srcLevel][i].FreeMemory(); 405 } 406 407 // return info 408 *w = destWidth; 409 *h = destHeight; 410 *data = destBand->GetBuffer(); 411 return NoError; 412 }
void CWaveletTransform::SubbandsToInterleaved (int srcLevel, DataT * loRow, DataT * hiRow, UINT32 width) [private]
Definition at line 444 of file WaveletTransform.cpp.
444 { 445 const UINT32 wquot = width >> 1; 446 const bool wrem = (width & 1); 447 CSubband &ll = m_subband[srcLevel][LL], &hl = m_subband[srcLevel][HL]; 448 CSubband &lh = m_subband[srcLevel][LH], &hh = m_subband[srcLevel][HH]; 449 450 if (hiRow) { 451 #ifdef __PGFROISUPPORT__ 452 const bool storePos = wquot < ll.BufferWidth(); 453 UINT32 llPos = 0, hlPos = 0, lhPos = 0, hhPos = 0; 454 455 if (storePos) { 456 // save current src buffer positions 457 llPos = ll.GetBuffPos(); 458 hlPos = hl.GetBuffPos(); 459 lhPos = lh.GetBuffPos(); 460 hhPos = hh.GetBuffPos(); 461 } 462 #endif 463 464 for (UINT32 i=0; i < wquot; i++) { 465 *loRow++ = ll.ReadBuffer();// first access, than increment 466 *loRow++ = hl.ReadBuffer();// first access, than increment 467 *hiRow++ = lh.ReadBuffer();// first access, than increment 468 *hiRow++ = hh.ReadBuffer();// first access, than increment 469 } 470 471 if (wrem) { 472 *loRow++ = ll.ReadBuffer();// first access, than increment 473 *hiRow++ = lh.ReadBuffer();// first access, than increment 474 } 475 476 #ifdef __PGFROISUPPORT__ 477 if (storePos) { 478 // increment src buffer positions 479 ll.IncBuffRow(llPos); 480 hl.IncBuffRow(hlPos); 481 lh.IncBuffRow(lhPos); 482 hh.IncBuffRow(hhPos); 483 } 484 #endif 485 486 } else { 487 #ifdef __PGFROISUPPORT__ 488 const bool storePos = wquot < ll.BufferWidth(); 489 UINT32 llPos = 0, hlPos = 0; 490 491 if (storePos) { 492 // save current src buffer positions 493 llPos = ll.GetBuffPos(); 494 hlPos = hl.GetBuffPos(); 495 } 496 #endif 497 498 for (UINT32 i=0; i < wquot; i++) { 499 *loRow++ = ll.ReadBuffer();// first access, than increment 500 *loRow++ = hl.ReadBuffer();// first access, than increment 501 } 502 if (wrem) *loRow++ = ll.ReadBuffer(); 503 504 #ifdef __PGFROISUPPORT__ 505 if (storePos) { 506 // increment src buffer positions 507 ll.IncBuffRow(llPos); 508 hl.IncBuffRow(hlPos); 509 } 510 #endif 511 } 512 }
Friends And Related Symbol Documentation
friend class CSubband [friend]
Definition at line 56 of file WaveletTransform.h.
Member Data Documentation
int CWaveletTransform::m_nLevels [private]
number of LL levels: one more than header.nLevels in PGFimage
Definition at line 141 of file WaveletTransform.h.
CSubband(* CWaveletTransform::m_subband)[NSubbands] [private]
quadtree of subbands: LL HL LH HH
Definition at line 142 of file WaveletTransform.h.
Author
Generated automatically by Doxygen for libpgf from the source code.