Scroll to navigation

CWaveletTransform(3) libpgf CWaveletTransform(3)

NAME

CWaveletTransform - 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 Function 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.

Sat Feb 27 2021 Version 7.21.2