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 }

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.

Info

Thu Jul 18 2024 00:00:00 Version 7.21.2 libpgf