libpgf  6.11.42
PGF - Progressive Graphics File
CWaveletTransform Class Reference

PGF wavelet transform. More...

#include <WaveletTransform.h>

List of all members.

Public Member Functions

 CWaveletTransform (UINT32 width, UINT32 height, int levels, DataT *data=NULL)
 ~CWaveletTransform ()
OSError ForwardTransform (int level, int quant)
OSError InverseTransform (int level, UINT32 *width, UINT32 *height, DataT **data)
CSubbandGetSubband (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 LinearToMallat (int destLevel, DataT *loRow, DataT *hiRow, UINT32 width)
void MallatToLinear (int srcLevel, DataT *loRow, DataT *hiRow, UINT32 width)

Private Attributes

int m_nLevels
 number of transform levels: one more than the number of level 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 92 of file WaveletTransform.h.


Constructor & Destructor Documentation

CWaveletTransform::CWaveletTransform ( UINT32  width,
UINT32  height,
int  levels,
DataT data = NULL 
)

Constructor: Constructs a wavelet transform pyramid of given size and levels.

Parameters:
widthThe width of the original image (at level 0) in pixels
heightThe height of the original image (at level 0) in pixels
levelsThe number of levels (>= 0)
dataInput data of subband LL at level 0

Definition at line 40 of file WaveletTransform.cpp.

                                                                                         : 
#ifdef __PGFROISUPPORT__
m_ROIs(levels + 1), 
#endif
m_nLevels(levels + 1), m_subband(0) {
        ASSERT(m_nLevels > 0 && m_nLevels <= MaxLevel + 1);
        InitSubbands(width, height, data);
}

Destructor

Definition at line 106 of file WaveletTransform.h.

{ Destroy(); }

Member Function Documentation

void CWaveletTransform::Destroy ( ) [inline, private]

Definition at line 163 of file WaveletTransform.h.

                       { delete[] m_subband; m_subband = 0; 
                #ifdef __PGFROISUPPORT__
                m_ROIs.Destroy(); 
                #endif
        }
void CWaveletTransform::ForwardRow ( DataT buff,
UINT32  width 
) [private]

Definition at line 182 of file WaveletTransform.cpp.

                                                           {
        if (width >= FilterWidth) {
                UINT32 i = 3;

                // left border handling
                src[1] -= ((src[0] + src[2] + c1) >> 1);
                src[0] += ((src[1] + c1) >> 1);
                
                // middle part
                for (; i < width-1; i += 2) {
                        src[i] -= ((src[i-1] + src[i+1] + c1) >> 1);
                        src[i-1] += ((src[i-2] + src[i] + c2) >> 2);
                }

                // right border handling
                if (width & 1) {
                        src[i-1] += ((src[i-2] + c1) >> 1);
                } else {
                        src[i] -= src[i-1];
                        src[i-1] += ((src[i-2] + src[i] + c2) >> 2);
                }
        }
}
OSError CWaveletTransform::ForwardTransform ( int  level,
int  quant 
)

Compute fast forward wavelet transform of LL subband at given level and stores result on all 4 subbands of level + 1.

Parameters:
levelA wavelet transform pyramid level (>= 0 && < Levels())
quantA quantization value (linear scalar quantization)
Returns:
error in case of a memory allocation problem

Definition at line 86 of file WaveletTransform.cpp.

                                                                {
        ASSERT(level >= 0 && level < m_nLevels - 1);
        const int destLevel = level + 1;
        ASSERT(m_subband[destLevel]);
        CSubband* srcBand = &m_subband[level][LL]; ASSERT(srcBand);
        const UINT32 width = srcBand->GetWidth();
        const UINT32 height = srcBand->GetHeight();
        DataT* src = srcBand->GetBuffer(); ASSERT(src);
        UINT32 row0, row1, row2, row3;
        UINT32 i, k;

        // Allocate memory for next transform level
        for (i=0; i < NSubbands; i++) {
                if (!m_subband[destLevel][i].AllocMemory()) return InsufficientMemory;
        }

        if (height >= FilterHeight) {
                // transform LL subband
                // top border handling
                row0 = 0; row1 = width; row2 = row1 + width;
                ForwardRow(&src[row0], width);
                ForwardRow(&src[row1], width);
                ForwardRow(&src[row2], width);
                for (k=0; k < width; k++) {
                        src[row1] -= ((src[row0] + src[row2] + c1) >> 1);
                        src[row0] += ((src[row1] + c1) >> 1);
                        row0++; row1++; row2++;
                }
                LinearToMallat(destLevel, &src[0], &src[row0], width);

                // middle part
                row3 = row2 + width;
                for (i=3; i < height-1; i += 2) {
                        ForwardRow(&src[row2], width);
                        ForwardRow(&src[row3], width);
                        for (k=0; k < width; k++) {
                                src[row2] -= ((src[row1] + src[row3] + c1) >> 1);
                                src[row1] += ((src[row0] + src[row2] + c2) >> 2);
                                row0++; row1++; row2++; row3++;
                        }
                        LinearToMallat(destLevel, &src[row0], &src[row1], width);
                        row0 = row1; row1 = row2; row2 = row3; row3 += width;
                }

                // bottom border handling
                if (height & 1) {
                        for (k=0; k < width; k++) {
                                src[row1] += ((src[row0] + c1) >> 1);
                                row0++; row1++;
                        }
                        LinearToMallat(destLevel, &src[row0], NULL, width);
                } else {
                        ForwardRow(&src[row2], width);
                        for (k=0; k < width; k++) {
                                src[row2] -= src[row1];
                                src[row1] += ((src[row0] + src[row2] + c2) >> 2);
                                row0++; row1++; row2++;
                        }
                        LinearToMallat(destLevel, &src[row0], &src[row1], width);
                }
        } else {
                // if height to small
                row0 = 0; row1 = width;
                // first part
                for (k=0; k < height; k += 2) {
                        ForwardRow(&src[row0], width);
                        ForwardRow(&src[row1], width);
                        LinearToMallat(destLevel, &src[row0], &src[row1], width);
                        row0 += width << 1; row1 += width << 1;
                }
                // bottom
                if (height & 1) {
                        LinearToMallat(destLevel, &src[row0], NULL, width);
                }
        }

        if (quant > 0) {
                // subband quantization (without LL)
                for (i=1; i < NSubbands; i++) {
                        m_subband[destLevel][i].Quantize(quant);
                }
                // LL subband quantization
                if (destLevel == m_nLevels - 1) {
                        m_subband[destLevel][LL].Quantize(quant);
                }
        }

        // free source band
        srcBand->FreeMemory();
        return NoError;
}
CSubband* CWaveletTransform::GetSubband ( int  level,
Orientation  orientation 
) [inline]

Get pointer to one of the 4 subband at a given level.

Parameters:
levelA wavelet transform pyramid level (>= 0 && <= Levels())
orientationA quarter of the subband (LL, LH, HL, HH)

Definition at line 130 of file WaveletTransform.h.

                                                                 {
                ASSERT(level >= 0 && level < m_nLevels);
                return &m_subband[level][orientation];
        }
void CWaveletTransform::InitSubbands ( UINT32  width,
UINT32  height,
DataT data 
) [private]

Definition at line 51 of file WaveletTransform.cpp.

                                                                             {
        if (m_subband) Destroy();

        // create subbands
        m_subband = new CSubband[m_nLevels][NSubbands];

        // init subbands
        UINT32 loWidth = width;
        UINT32 hiWidth = width;
        UINT32 loHeight = height;
        UINT32 hiHeight = height;

        for (int level = 0; level < m_nLevels; level++) {
                m_subband[level][LL].Initialize(loWidth, loHeight, level, LL);  // LL
                m_subband[level][HL].Initialize(hiWidth, loHeight, level, HL);  //    HL
                m_subband[level][LH].Initialize(loWidth, hiHeight, level, LH);  // LH
                m_subband[level][HH].Initialize(hiWidth, hiHeight, level, HH);  //    HH
                hiWidth = loWidth >> 1;                 hiHeight = loHeight >> 1;
                loWidth = (loWidth + 1) >> 1;   loHeight = (loHeight + 1) >> 1;
        }
        if (data) {
                m_subband[0][LL].SetBuffer(data);
        }
}
void CWaveletTransform::InverseRow ( DataT buff,
UINT32  width 
) [private]

Definition at line 387 of file WaveletTransform.cpp.

                                                            {
        if (width >= FilterWidth) {
                UINT32 i = 2;

                // left border handling
                dest[0] -= ((dest[1] + c1) >> 1);

                // middle part
                for (; i < width - 1; i += 2) {
                        dest[i] -= ((dest[i-1] + dest[i+1] + c2) >> 2);
                        dest[i-1] += ((dest[i-2] + dest[i] + c1) >> 1);
                }

                // right border handling
                if (width & 1) {
                        dest[i] -= ((dest[i-1] + c1) >> 1);
                        dest[i-1] += ((dest[i-2] + dest[i] + c1) >> 1);
                } else {
                        dest[i-1] += dest[i-2];
                }
        }
}
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:
levelA wavelet transform pyramid level (> 0 && <= Levels())
widthA pointer to the returned width of subband LL (in pixels)
heightA pointer to the returned height of subband LL (in pixels)
dataA pointer to the returned array of image data
Returns:
error in case of a memory allocation problem

Definition at line 247 of file WaveletTransform.cpp.

                                                                                            {
        ASSERT(srcLevel > 0 && srcLevel < m_nLevels);
        const int destLevel = srcLevel - 1;
        ASSERT(m_subband[destLevel]);
        CSubband* destBand = &m_subband[destLevel][LL];
        const UINT32 width = destBand->GetWidth();
        const UINT32 height = destBand->GetHeight();
        UINT32 row0, row1, row2, row3, i, k, origin = 0;

        // allocate memory for the results of the inverse transform 
        if (!destBand->AllocMemory()) return InsufficientMemory;
        DataT* dest = destBand->GetBuffer();

#ifdef __PGFROISUPPORT__
        const UINT32 srcLeft = (m_ROIs.ROIisSupported()) ? m_ROIs.Left(srcLevel) : 0;
        const UINT32 srcTop = (m_ROIs.ROIisSupported()) ? m_ROIs.Top(srcLevel) : 0;
        UINT32 destWidth = destBand->BufferWidth(); // destination buffer width; is valid only after AllocMemory
        PGFRect destROI = (m_ROIs.ROIisSupported()) ? m_ROIs.GetROI(destLevel) : PGFRect(0, 0, width, height);
        destROI.right = destROI.left + destWidth;
        destROI.bottom = __min(destROI.bottom, height);
        UINT32 destHeight = destROI.Height(); // destination buffer height

        // update destination ROI
        if (destROI.left & 1) {
                destROI.left++;
                origin++;
                destWidth--;
        }
        if (destROI.top & 1) {
                destROI.top++;
                origin += destWidth;
                destHeight--;
        }

        // init source buffer position
        UINT32 left = destROI.left >> 1;
        UINT32 top = destROI.top >> 1;

        left -= srcLeft;
        top -= srcTop;
        for (i=0; i < NSubbands; i++) {
                m_subband[srcLevel][i].InitBuffPos(left, top);
        }
#else
        PGFRect destROI(0, 0, width, height);
        const UINT32 destWidth = width; // destination buffer width
        const UINT32 destHeight = height; // destination buffer height

        // init source buffer position
        for (i=0; i < NSubbands; i++) {
                m_subband[srcLevel][i].InitBuffPos();
        }
#endif

        if (destHeight >= FilterHeight) {
                // top border handling
                row0 = origin; row1 = row0 + destWidth;
                MallatToLinear(srcLevel, &dest[row0], &dest[row1], destWidth);
                for (k=0; k < destWidth; k++) {
                        ASSERT(row0 < destBand->m_size);
                        ASSERT(row1 < destBand->m_size);
                        dest[row0] -= ((dest[row1] + c1) >> 1);
                        row0++; row1++;
                }

                // middle part
                row2 = row1; row1 = row0; row0 = row0 - destWidth; row3 = row2 + destWidth;
                for (i=destROI.top + 2; i < destROI.bottom - 1; i += 2) {
                        MallatToLinear(srcLevel, &dest[row2], &dest[row3], destWidth);
                        for (k=0; k < destWidth; k++) {
                                ASSERT(row0 < destBand->m_size);
                                ASSERT(row1 < destBand->m_size);
                                ASSERT(row2 < destBand->m_size);
                                ASSERT(row3 < destBand->m_size);
                                dest[row2] -= ((dest[row1] + dest[row3] + c2) >> 2);
                                dest[row1] += ((dest[row0] + dest[row2] + c1) >> 1);
                                row0++; row1++; row2++; row3++;
                        }
                        InverseRow(&dest[row0 - destWidth], destWidth);
                        InverseRow(&dest[row1 - destWidth], destWidth);
                        row0 = row1; row1 = row2; row2 = row3; row3 += destWidth;
                }

                // bottom border handling
                if (destHeight & 1) {
                        MallatToLinear(srcLevel, &dest[row2], 0, destWidth);
                        for (k=0; k < destWidth; k++) {
                                ASSERT(row0 < destBand->m_size);
                                ASSERT(row1 < destBand->m_size);
                                ASSERT(row2 < destBand->m_size);
                                dest[row2] -= ((dest[row1] + c1) >> 1);
                                dest[row1] += ((dest[row0] + dest[row2] + c1) >> 1);
                                row0++; row1++; row2++;
                        }
                        InverseRow(&dest[row0 - destWidth], destWidth);
                        InverseRow(&dest[row1 - destWidth], destWidth);
                        InverseRow(&dest[row2 - destWidth], destWidth);
                } else {
                        for (k=0; k < destWidth; k++) {
                                ASSERT(row0 < destBand->m_size);
                                ASSERT(row1 < destBand->m_size);
                                dest[row1] += dest[row0];
                                row0++; row1++;
                        }
                        InverseRow(&dest[row0 - destWidth], destWidth);
                        InverseRow(&dest[row1 - destWidth], destWidth);
                }
        } else {
                // destHeight to small
                row0 = origin; row1 = row0 + destWidth;
                // first part
                for (k=0; k < destHeight; k += 2) {
                        MallatToLinear(srcLevel, &dest[row0], &dest[row1], destWidth);
                        InverseRow(&dest[row0], destWidth);
                        InverseRow(&dest[row1], destWidth);
                        row0 += destWidth << 1; row1 += destWidth << 1;
                }
                // bottom
                if (destHeight & 1) {
                        MallatToLinear(srcLevel, &dest[row0], 0, destWidth);
                        InverseRow(&dest[row0], destWidth);
                } 
        }

        // free memory of the current srcLevel
        for (i=0; i < NSubbands; i++) {
                m_subband[srcLevel][i].FreeMemory();
        }

        // return info
        *w = destWidth;
        *h = destHeight;
        *data = dest;
        return NoError;
}
void CWaveletTransform::LinearToMallat ( int  destLevel,
DataT loRow,
DataT hiRow,
UINT32  width 
) [private]

Definition at line 208 of file WaveletTransform.cpp.

                                                                                              {
        const UINT32 wquot = width >> 1;
        const bool wrem = width & 1;
        CSubband &ll = m_subband[destLevel][LL], &hl = m_subband[destLevel][HL];
        CSubband &lh = m_subband[destLevel][LH], &hh = m_subband[destLevel][HH];
        UINT32 i;

        if (hiRow) {
                for (i=0; i < wquot; i++) {
                        ll.WriteBuffer(*loRow++);       // first access, than increment
                        hl.WriteBuffer(*loRow++);
                        lh.WriteBuffer(*hiRow++);       // first access, than increment
                        hh.WriteBuffer(*hiRow++);
                }
                if (wrem) {
                        ll.WriteBuffer(*loRow);
                        lh.WriteBuffer(*hiRow);
                }
        } else {
                for (i=0; i < wquot; i++) {
                        ll.WriteBuffer(*loRow++);       // first access, than increment
                        hl.WriteBuffer(*loRow++);
                }
                if (wrem) ll.WriteBuffer(*loRow);
        }
}
void CWaveletTransform::MallatToLinear ( int  srcLevel,
DataT loRow,
DataT hiRow,
UINT32  width 
) [private]

Definition at line 412 of file WaveletTransform.cpp.

                                                                                             {
        const UINT32 wquot = width >> 1;
        const bool wrem = width & 1;
        CSubband &ll = m_subband[srcLevel][LL], &hl = m_subband[srcLevel][HL];
        CSubband &lh = m_subband[srcLevel][LH], &hh = m_subband[srcLevel][HH];
        UINT32 i;

        if (hiRow) {
        #ifdef __PGFROISUPPORT__
                const bool storePos = wquot < ll.BufferWidth();
                UINT32 llPos = 0, hlPos = 0, lhPos = 0, hhPos = 0;

                if (storePos) {
                        // save current src buffer positions
                        llPos = ll.GetBuffPos(); 
                        hlPos = hl.GetBuffPos(); 
                        lhPos = lh.GetBuffPos(); 
                        hhPos = hh.GetBuffPos(); 
                }
        #endif

                for (i=0; i < wquot; i++) {
                        *loRow++ = ll.ReadBuffer();// first access, than increment
                        *loRow++ = hl.ReadBuffer();// first access, than increment
                        *hiRow++ = lh.ReadBuffer();// first access, than increment
                        *hiRow++ = hh.ReadBuffer();// first access, than increment
                }

                if (wrem) {
                        *loRow++ = ll.ReadBuffer();// first access, than increment
                        *hiRow++ = lh.ReadBuffer();// first access, than increment
                }

        #ifdef __PGFROISUPPORT__
                if (storePos) {
                        // increment src buffer positions
                        ll.IncBuffRow(llPos); 
                        hl.IncBuffRow(hlPos); 
                        lh.IncBuffRow(lhPos); 
                        hh.IncBuffRow(hhPos); 
                }
        #endif

        } else {
        #ifdef __PGFROISUPPORT__
                const bool storePos = wquot < ll.BufferWidth();
                UINT32 llPos = 0, hlPos = 0;

                if (storePos) {
                        // save current src buffer positions
                        llPos = ll.GetBuffPos(); 
                        hlPos = hl.GetBuffPos(); 
                }
        #endif

                for (i=0; i < wquot; i++) {
                        *loRow++ = ll.ReadBuffer();// first access, than increment
                        *loRow++ = hl.ReadBuffer();// first access, than increment
                }
                if (wrem) *loRow++ = ll.ReadBuffer();

        #ifdef __PGFROISUPPORT__
                if (storePos) {
                        // increment src buffer positions
                        ll.IncBuffRow(llPos); 
                        hl.IncBuffRow(hlPos); 
                }
        #endif
        }
}

Friends And Related Function Documentation

friend class CSubband [friend]

Definition at line 93 of file WaveletTransform.h.


Member Data Documentation

number of transform levels: one more than the number of level in PGFimage

Definition at line 178 of file WaveletTransform.h.

quadtree of subbands: LL HL LH HH

Definition at line 179 of file WaveletTransform.h.


The documentation for this class was generated from the following files:
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines