libpgf  6.11.42
PGF - Progressive Graphics File
CPGFImage Class Reference

PGF main class. More...

#include <PGFimage.h>

List of all members.

Public Member Functions

 CPGFImage ()
virtual ~CPGFImage ()
virtual void Close ()
virtual void Destroy ()
void Open (CPGFStream *stream) THROW_
bool IsOpen () const
void Read (int level=0, CallbackPtr cb=NULL, void *data=NULL) THROW_
void Read (PGFRect &rect, int level=0, CallbackPtr cb=NULL, void *data=NULL) THROW_
void ReadPreview () THROW_
void Reconstruct (int level=0) THROW_
void GetBitmap (int pitch, UINT8 *buff, BYTE bpp, int channelMap[]=NULL, CallbackPtr cb=NULL, void *data=NULL) const THROW_
void GetYUV (int pitch, DataT *buff, BYTE bpp, int channelMap[]=NULL, CallbackPtr cb=NULL, void *data=NULL) const THROW_
void ImportBitmap (int pitch, UINT8 *buff, BYTE bpp, int channelMap[]=NULL, CallbackPtr cb=NULL, void *data=NULL) THROW_
void ImportYUV (int pitch, DataT *buff, BYTE bpp, int channelMap[]=NULL, CallbackPtr cb=NULL, void *data=NULL) THROW_
void Write (CPGFStream *stream, UINT32 *nWrittenBytes=NULL, CallbackPtr cb=NULL, void *data=NULL) THROW_
UINT32 WriteHeader (CPGFStream *stream) THROW_
UINT32 Write (int level, CallbackPtr cb=NULL, void *data=NULL) THROW_
void ConfigureEncoder (bool useOMP=true, bool favorSpeedOverSize=false)
void ConfigureDecoder (bool useOMP=true)
void SetChannel (DataT *channel, int c=0)
void SetHeader (const PGFHeader &header, BYTE flags=0, UINT8 *userData=0, UINT32 userDataLength=0) THROW_
void SetMaxValue (UINT32 maxValue)
BYTE UsedBitsPerChannel () const
void SetRefreshCallback (RefreshCB callback, void *arg)
void SetColorTable (UINT32 iFirstColor, UINT32 nColors, const RGBQUAD *prgbColors) THROW_
DataTGetChannel (int c=0)
void GetColorTable (UINT32 iFirstColor, UINT32 nColors, RGBQUAD *prgbColors) const THROW_
const RGBQUAD * GetColorTable () const
const PGFHeaderGetHeader () const
UINT32 GetMaxValue () const
const UINT8 * GetUserData (UINT32 &size) const
UINT32 GetEncodedHeaderLength () const
UINT32 GetEncodedLevelLength (int level) const
void ResetStreamPos () THROW_
UINT32 ReadEncodedHeader (UINT8 *target, UINT32 targetLen) const THROW_
UINT32 ReadEncodedData (int level, UINT8 *target, UINT32 targetLen) const THROW_
UINT32 ChannelWidth (int c=0) const
UINT32 ChannelHeight (int c=0) const
BYTE ChannelDepth () const
UINT32 Width (int level=0) const
UINT32 Height (int level=0) const
BYTE Level () const
BYTE Levels () const
BYTE Quality () const
BYTE Channels () const
BYTE Mode () const
BYTE BPP () const
bool ROIisSupported () const
BYTE Version () const

Static Public Member Functions

static bool ImportIsSupported (BYTE mode)
static UINT32 LevelWidth (UINT32 width, int level)
static UINT32 LevelHeight (UINT32 height, int level)
static BYTE CurrentVersion (BYTE version=PGFVersion)
static BYTE CurrentChannelDepth (BYTE version=PGFVersion)

Protected Attributes

CWaveletTransformm_wtChannel [MaxChannels]
 wavelet transformed color channels
DataTm_channel [MaxChannels]
 untransformed channels in YUV format
CDecoderm_decoder
 PGF decoder.
CEncoderm_encoder
 PGF encoder.
UINT32 * m_levelLength
 length of each level in bytes; first level starts immediately after this array
UINT32 m_width [MaxChannels]
 width of each channel at current level
UINT32 m_height [MaxChannels]
 height of each channel at current level
PGFPreHeader m_preHeader
 PGF pre header.
PGFHeader m_header
 PGF file header.
PGFPostHeader m_postHeader
 PGF post header.
int m_currentLevel
 transform level of current image
BYTE m_quant
 quantization parameter
bool m_downsample
 chrominance channels are downsampled
bool m_favorSpeedOverSize
 favor encoding speed over compression ratio
bool m_useOMPinEncoder
 use Open MP in encoder
bool m_useOMPinDecoder
 use Open MP in decoder
bool m_levelwise
 write level-wise (only used with WriteNextLevel)
bool m_streamReinitialized
 stream has been reinitialized
PGFRect m_roi
 region of interest

Private Member Functions

void ComputeLevels ()
void CompleteHeader ()
void RgbToYuv (int pitch, UINT8 *rgbBuff, BYTE bpp, int channelMap[], CallbackPtr cb, void *data) THROW_
void Downsample (int nChannel)
void WriteLevel () THROW_
void SetROI (PGFRect rect)
UINT8 Clamp4 (DataT v) const
UINT16 Clamp6 (DataT v) const
UINT8 Clamp8 (DataT v) const
UINT16 Clamp16 (DataT v) const
UINT32 Clamp31 (DataT v) const

Private Attributes

RefreshCB m_cb
 pointer to refresh callback procedure
void * m_cbArg
 refresh callback argument

Detailed Description

PGF main class.

PGF image class is the main class. You always need a PGF object for encoding or decoding image data. Decoding: pgf.Open(...) pgf.Read(...) pgf.GetBitmap(...) Encoding: pgf.SetHeader(...) pgf.ImportBitmap(...) pgf.Write(...)

Author:
C. Stamm, R. Spuler

Definition at line 51 of file PGFimage.h.


Constructor & Destructor Documentation

Standard constructor: It is used to create a PGF instance for opening and reading.

Definition at line 55 of file PGFimage.cpp.

: m_decoder(0)
, m_encoder(0)
, m_levelLength(0)
, m_quant(0)
, m_downsample(false)
, m_favorSpeedOverSize(false)
, m_useOMPinEncoder(true)
, m_useOMPinDecoder(true)
#ifdef __PGFROISUPPORT__
, m_levelwise(true)
, m_streamReinitialized(false)
#endif
, m_cb(0)
, m_cbArg(0)
{

        // init preHeader
        memcpy(m_preHeader.magic, Magic, 3);
        m_preHeader.version = PGFVersion;
        m_preHeader.hSize = 0;

        // init postHeader
        m_postHeader.userData = 0;
        m_postHeader.userDataLen = 0;

        // init channels
        for (int i=0; i < MaxChannels; i++) {
                m_channel[i] = 0;
                m_wtChannel[i] = 0;
        }

        // set image width and height
        m_width[0] = 0;
        m_height[0] = 0;
}
CPGFImage::~CPGFImage ( ) [virtual]

Destructor: Destroy internal data structures.

Definition at line 94 of file PGFimage.cpp.

                      {
        Destroy();
}

Member Function Documentation

BYTE CPGFImage::BPP ( ) const [inline]

Return the number of bits per pixel. Valid values can be 1, 8, 12, 16, 24, 31, 32, 48, 64.

Returns:
Number of bits per pixel.

Definition at line 452 of file PGFimage.h.

{ return m_header.bpp; }
BYTE CPGFImage::ChannelDepth ( ) const [inline]

Return bits per channel of the image's encoder.

Returns:
Bits per channel

Definition at line 401 of file PGFimage.h.

UINT32 CPGFImage::ChannelHeight ( int  c = 0) const [inline]

Return current image height of given channel in pixels. The returned height depends on the levels read so far and on ROI.

Parameters:
cA channel index
Returns:
Channel height in pixels

Definition at line 396 of file PGFimage.h.

{ ASSERT(c >= 0 && c < MaxChannels); return m_height[c]; }
BYTE CPGFImage::Channels ( ) const [inline]

Return the number of image channels. An image of type RGB contains 3 image channels (B, G, R).

Returns:
Number of image channels

Definition at line 439 of file PGFimage.h.

{ return m_header.channels; }
UINT32 CPGFImage::ChannelWidth ( int  c = 0) const [inline]

Return current image width of given channel in pixels. The returned width depends on the levels read so far and on ROI.

Parameters:
cA channel index
Returns:
Channel width in pixels

Definition at line 389 of file PGFimage.h.

{ ASSERT(c >= 0 && c < MaxChannels); return m_width[c]; }
UINT16 CPGFImage::Clamp16 ( DataT  v) const [inline, private]

Definition at line 543 of file PGFimage.h.

                                      {
                if (v & 0xFFFF0000) return (v < 0) ? (UINT16)0: (UINT16)65535; else return (UINT16)v;
        }       
UINT32 CPGFImage::Clamp31 ( DataT  v) const [inline, private]

Definition at line 546 of file PGFimage.h.

                                      {
                return (v < 0) ? 0 : (UINT32)v;
        }       
UINT8 CPGFImage::Clamp4 ( DataT  v) const [inline, private]

Definition at line 533 of file PGFimage.h.

                                    {
                if (v & 0xFFFFFFF0) return (v < 0) ? (UINT8)0: (UINT8)15; else return (UINT8)v;
        }       
UINT16 CPGFImage::Clamp6 ( DataT  v) const [inline, private]

Definition at line 536 of file PGFimage.h.

                                     {
                if (v & 0xFFFFFFC0) return (v < 0) ? (UINT16)0: (UINT16)63; else return (UINT16)v;
        }       
UINT8 CPGFImage::Clamp8 ( DataT  v) const [inline, private]

Definition at line 539 of file PGFimage.h.

                                    {
                // needs only one test in the normal case
                if (v & 0xFFFFFF00) return (v < 0) ? (UINT8)0 : (UINT8)255; else return (UINT8)v;
        }
void CPGFImage::Close ( ) [virtual]

Close PGF image after opening and reading. Destructor calls this method during destruction.

Definition at line 116 of file PGFimage.cpp.

                      {
        delete m_decoder; m_decoder = 0;
}
void CPGFImage::CompleteHeader ( ) [private]

Definition at line 195 of file PGFimage.cpp.

                               {
        if (m_header.mode == ImageModeUnknown) {
                // undefined mode
                switch(m_header.bpp) {
                case 1: m_header.mode = ImageModeBitmap; break;
                case 8: m_header.mode = ImageModeGrayScale; break;
                case 12: m_header.mode = ImageModeRGB12; break;
                case 16: m_header.mode = ImageModeRGB16; break;
                case 24: m_header.mode = ImageModeRGBColor; break;
                case 32: m_header.mode = ImageModeRGBA; break;
                case 48: m_header.mode = ImageModeRGB48; break;
                default: m_header.mode = ImageModeRGBColor; break;
                }
        }
        if (!m_header.bpp) {
                // undefined bpp
                switch(m_header.mode) {
                case ImageModeBitmap: 
                        m_header.bpp = 1;
                        break;
                case ImageModeIndexedColor:
                case ImageModeGrayScale:
                        m_header.bpp = 8;
                        break;
                case ImageModeRGB12:
                        m_header.bpp = 12;
                        break;
                case ImageModeRGB16:
                case ImageModeGray16:
                        m_header.bpp = 16;
                        break;
                case ImageModeRGBColor:
                case ImageModeLabColor:
                        m_header.bpp = 24;
                        break;
                case ImageModeRGBA:
                case ImageModeCMYKColor:
        #ifdef __PGF32SUPPORT__
                case ImageModeGray32:
        #endif                  
                        m_header.bpp = 32;
                        break;
                case ImageModeRGB48:
                case ImageModeLab48:
                        m_header.bpp = 48;
                        break;
                case ImageModeCMYK64:
                        m_header.bpp = 64;
                        break;
                default:
                        ASSERT(false);
                        m_header.bpp = 24;
                }
        } 
        if (m_header.mode == ImageModeRGBColor && m_header.bpp == 32) {
                // change mode
                m_header.mode = ImageModeRGBA;
        }
        ASSERT(m_header.mode != ImageModeBitmap || m_header.bpp == 1);
        ASSERT(m_header.mode != ImageModeGrayScale || m_header.bpp == 8);
        ASSERT(m_header.mode != ImageModeGray16 || m_header.bpp == 16);
        ASSERT(m_header.mode != ImageModeRGBColor || m_header.bpp == 24);
        ASSERT(m_header.mode != ImageModeRGBA || m_header.bpp == 32);
        ASSERT(m_header.mode != ImageModeRGB12 || m_header.bpp == 12);
        ASSERT(m_header.mode != ImageModeRGB16 || m_header.bpp == 16);
        ASSERT(m_header.mode != ImageModeRGB48 || m_header.bpp == 48);
        ASSERT(m_header.mode != ImageModeLabColor || m_header.bpp == 24);
        ASSERT(m_header.mode != ImageModeLab48 || m_header.bpp == 48);
        ASSERT(m_header.mode != ImageModeCMYKColor || m_header.bpp == 32);
        ASSERT(m_header.mode != ImageModeCMYK64 || m_header.bpp == 64);

        // set number of channels
        if (!m_header.channels) {
                switch(m_header.mode) {
                case ImageModeBitmap: 
                case ImageModeIndexedColor:
                case ImageModeGrayScale:
                case ImageModeGray16:
        #ifdef __PGF32SUPPORT__
                case ImageModeGray32:
        #endif
                        m_header.channels = 1; 
                        break;
                case ImageModeRGBColor:
                case ImageModeRGB12:
                case ImageModeRGB16:
                case ImageModeRGB48:
                case ImageModeLabColor:
                case ImageModeLab48:
                        m_header.channels = 3;
                        break;
                case ImageModeRGBA:
                case ImageModeCMYKColor:
                case ImageModeCMYK64:
                        m_header.channels = 4;
                        break;
                default:
                        ASSERT(false);
                        m_header.channels = 3;
                }
        }

        // store used bits per channel
        UINT8 bpc = m_header.bpp/m_header.channels;
        if (bpc > 31) bpc = 31;
        if (!m_header.usedBitsPerChannel || m_header.usedBitsPerChannel > bpc) {
                m_header.usedBitsPerChannel = bpc;
        }
}
void CPGFImage::ComputeLevels ( ) [private]

Definition at line 799 of file PGFimage.cpp.

                              {
        const int maxThumbnailWidth = 20*FilterWidth;
        const int m = __min(m_header.width, m_header.height);
        int s = m;

        if (m_header.nLevels < 1 || m_header.nLevels > MaxLevel) {
                m_header.nLevels = 1;
                // compute a good value depending on the size of the image
                while (s > maxThumbnailWidth) {
                        m_header.nLevels++;
                        s = s/2;
                }
        }

        int levels = m_header.nLevels; // we need a signed value during level reduction

        // reduce number of levels if the image size is smaller than FilterWidth*2^levels
        s = FilterWidth*(1 << levels);  // must be at least the double filter size because of subsampling
        while (m < s) {
                levels--;
                s = s/2;
        }
        if (levels > MaxLevel) m_header.nLevels = MaxLevel;
        else if (levels < 0) m_header.nLevels = 0;
        else m_header.nLevels = (UINT8)levels;

        ASSERT(0 <= m_header.nLevels && m_header.nLevels <= MaxLevel);
}
void CPGFImage::ConfigureDecoder ( bool  useOMP = true) [inline]

Configures the encoder.

Parameters:
useOMPUse parallel threading with Open MP during decoding. Default value: true. Influences the decoding only if the codec has been compiled with OpenMP support.

Definition at line 249 of file PGFimage.h.

{ m_useOMPinDecoder = useOMP; }
void CPGFImage::ConfigureEncoder ( bool  useOMP = true,
bool  favorSpeedOverSize = false 
) [inline]

Configures the encoder.

Parameters:
useOMPUse parallel threading with Open MP during encoding. Default value: true. Influences the encoding only if the codec has been compiled with OpenMP support.
favorSpeedOverSizeFavors encoding speed over compression ratio. Default value: false

Definition at line 244 of file PGFimage.h.

{ m_useOMPinEncoder = useOMP; m_favorSpeedOverSize = favorSpeedOverSize; }
static BYTE CPGFImage::CurrentChannelDepth ( BYTE  version = PGFVersion) [inline, static]

Compute and return codec version.

Returns:
current PGF codec version

Definition at line 494 of file PGFimage.h.

{ return (version & PGF32) ? 32 : 16; }
BYTE CPGFImage::CurrentVersion ( BYTE  version = PGFVersion) [static]

Compute and return codec version.

Returns:
current PGF codec version

Return version

Definition at line 714 of file PGFimage.cpp.

                                           {
        if (version & Version6) return 6;
        if (version & Version5) return 5;
        if (version & Version2) return 2;
        return 1;
}
void CPGFImage::Destroy ( ) [virtual]

Destroy internal data structures. Destructor calls this method during destruction.

Definition at line 101 of file PGFimage.cpp.

                        {
        Close();

        for (int i=0; i < m_header.channels; i++) {
                delete m_wtChannel[i]; m_wtChannel[i]=0; // also deletes m_channel
                m_channel[i] = 0;
        }
        delete[] m_postHeader.userData; m_postHeader.userData = 0; m_postHeader.userDataLen = 0;
        delete[] m_levelLength; m_levelLength = 0;
        delete m_encoder; m_encoder = NULL;
}
void CPGFImage::Downsample ( int  nChannel) [private]

Definition at line 754 of file PGFimage.cpp.

                                 {
        ASSERT(ch > 0);

        const int w = m_width[0];
        const int w2 = w/2;
        const int h2 = m_height[0]/2;
        const int oddW = w%2;                           // don't use bool -> problems with MaxSpeed optimization
        const int oddH = m_height[0]%2;         // "
        int i, j;
        int loPos = 0;
        int hiPos = w;
        int sampledPos = 0;
        DataT* buff = m_channel[ch]; ASSERT(buff);

        for (i=0; i < h2; i++) {
                for (j=0; j < w2; j++) {
                        // compute average of pixel block
                        buff[sampledPos] = (buff[loPos] + buff[loPos + 1] + buff[hiPos] + buff[hiPos + 1]) >> 2;
                        loPos += 2; hiPos += 2;
                        sampledPos++;
                }
                if (oddW) { 
                        buff[sampledPos] = (buff[loPos] + buff[hiPos]) >> 1;
                        loPos++; hiPos++;
                        sampledPos++;
                }
                loPos += w; hiPos += w;
        }
        if (oddH) {
                for (j=0; j < w2; j++) {
                        buff[sampledPos] = (buff[loPos] + buff[loPos+1]) >> 1;
                        loPos += 2; hiPos += 2;
                        sampledPos++;
                }
                if (oddW) {
                        buff[sampledPos] = buff[loPos];
                }
        }

        // downsampled image has half width and half height
        m_width[ch] = (m_width[ch] + 1)/2;
        m_height[ch] = (m_height[ch] + 1)/2;
}
void CPGFImage::GetBitmap ( int  pitch,
UINT8 *  buff,
BYTE  bpp,
int  channelMap[] = NULL,
CallbackPtr  cb = NULL,
void *  data = NULL 
) const

Get image data in interleaved format: (ordering of RGB data is BGR[A]) Upsampling, YUV to RGB transform and interleaving are done here to reduce the number of passes over the data. The absolute value of pitch is the number of bytes of an image row of the given image buffer. If pitch is negative, then the image buffer must point to the last row of a bottom-up image (first byte on last row). if pitch is positive, then the image buffer must point to the first row of a top-down image (first byte). The sequence of output channels in the output image buffer does not need to be the same as provided by PGF. In case of different sequences you have to provide a channelMap of size of expected channels (depending on image mode). For example, PGF provides a channel sequence BGR in RGB color mode. If your provided image buffer expects a channel sequence ARGB, then the channelMap looks like { 3, 2, 1, 0 }. It might throw an IOException.

Parameters:
pitchThe number of bytes of a row of the image buffer.
buffAn image buffer.
bppThe number of bits per pixel used in image buffer.
channelMapA integer array containing the mapping of PGF channel ordering to expected channel ordering.
cbA pointer to a callback procedure. The procedure is called after each copied buffer row. If cb returns true, then it stops proceeding.
dataData Pointer to C++ class container to host callback procedure.

Definition at line 1668 of file PGFimage.cpp.

                                                                                                                           {
        ASSERT(buff);
        UINT32 w = m_width[0];
        UINT32 h = m_height[0];
        UINT8* targetBuff = 0;  // used if ROI is used
        UINT8* buffStart = 0;   // used if ROI is used
        int targetPitch = 0;    // used if ROI is used

#ifdef __PGFROISUPPORT__
        const PGFRect& roi = (ROIisSupported()) ? m_wtChannel[0]->GetROI(m_currentLevel) : PGFRect(0, 0, w, h); // roi is usually larger than m_roi
        const PGFRect levelRoi(LevelWidth(m_roi.left, m_currentLevel), LevelHeight(m_roi.top, m_currentLevel), LevelWidth(m_roi.Width(), m_currentLevel), LevelHeight(m_roi.Height(), m_currentLevel));
        ASSERT(w == roi.Width() && h == roi.Height());
        ASSERT(roi.left <= levelRoi.left && levelRoi.right <= roi.right); 
        ASSERT(roi.top <= levelRoi.top && levelRoi.bottom <= roi.bottom); 

        if (ROIisSupported() && (levelRoi.Width() < w || levelRoi.Height() < h)) {
                // ROI is used -> create a temporary image buffer for roi
                // compute pitch
                targetPitch = pitch;
                pitch = AlignWordPos(w*bpp)/8;

                // create temporary output buffer
                targetBuff = buff;
                buff = buffStart = new(std::nothrow) UINT8[pitch*h];
                if (!buff) ReturnWithError(InsufficientMemory);
        }
#endif

        const bool wOdd = (1 == w%2);

        const double dP = 1.0/h;
        int defMap[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; ASSERT(sizeof(defMap)/sizeof(defMap[0]) == MaxChannels);
        if (channelMap == NULL) channelMap = defMap;
        int sampledPos = 0, yPos = 0;
        DataT uAvg, vAvg;
        double percent = 0;
        UINT32 i, j;

        switch(m_header.mode) {
        case ImageModeBitmap:
                {
                        ASSERT(m_header.channels == 1);
                        ASSERT(m_header.bpp == 1);
                        ASSERT(bpp == 1);

                        const UINT32 w2 = (w + 7)/8;
                        DataT* y = m_channel[0]; ASSERT(y);

                        for (i=0; i < h; i++) {
                                
                                for (j=0; j < w2; j++) {
                                        buff[j] = Clamp8(y[yPos++] + YUVoffset8);
                                }
                                yPos += w - w2;
                                
                                //UINT32 cnt = w;
                                //for (j=0; j < w2; j++) {
                                //      buff[j] = 0;
                                //      for (int k=0; k < 8; k++) {
                                //              if (cnt) {
                                //                      buff[j] <<= 1;
                                //                      buff[j] |= (1 & (y[yPos++] - YUVoffset8)); 
                                //                      cnt--;
                                //              }
                                //      }
                                //}
                                buff += pitch;

                                if (cb) {
                                        percent += dP;
                                        if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                }
                        }
                        break;
                }
        case ImageModeIndexedColor:
        case ImageModeGrayScale:
        case ImageModeHSLColor:
        case ImageModeHSBColor:
                {
                        ASSERT(m_header.channels >= 1);
                        ASSERT(m_header.bpp == m_header.channels*8);
                        ASSERT(bpp%8 == 0);

                        int cnt, channels = bpp/8; ASSERT(channels >= m_header.channels);

                        for (i=0; i < h; i++) {
                                cnt = 0;
                                for (j=0; j < w; j++) {
                                        for (int c=0; c < m_header.channels; c++) {
                                                buff[cnt + channelMap[c]] = Clamp8(m_channel[c][yPos] + YUVoffset8);
                                        }
                                        cnt += channels;
                                        yPos++;
                                }
                                buff += pitch;

                                if (cb) {
                                        percent += dP;
                                        if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                }
                        }
                        break;
                }
        case ImageModeGray16:
                {
                        ASSERT(m_header.channels >= 1);
                        ASSERT(m_header.bpp == m_header.channels*16);

                        const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
                        int cnt, channels;

                        if (bpp%16 == 0) {
                                const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
                                UINT16 *buff16 = (UINT16 *)buff;
                                int pitch16 = pitch/2;
                                channels = bpp/16; ASSERT(channels >= m_header.channels);

                                for (i=0; i < h; i++) {
                                        cnt = 0;
                                        for (j=0; j < w; j++) {
                                                for (int c=0; c < m_header.channels; c++) {
                                                        buff16[cnt + channelMap[c]] = Clamp16(m_channel[c][yPos] + yuvOffset16) << shift;
                                                }
                                                cnt += channels;
                                                yPos++;
                                        }
                                        buff16 += pitch16;

                                        if (cb) {
                                                percent += dP;
                                                if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                        }
                                }
                        } else {
                                ASSERT(bpp%8 == 0);
                                const int shift = __max(0, UsedBitsPerChannel() - 8);
                                channels = bpp/8; ASSERT(channels >= m_header.channels);
                                
                                for (i=0; i < h; i++) {
                                        cnt = 0;
                                        for (j=0; j < w; j++) {
                                                for (int c=0; c < m_header.channels; c++) {
                                                        buff[cnt + channelMap[c]] = UINT8(Clamp16(m_channel[c][yPos] + yuvOffset16) >> shift);
                                                }
                                                cnt += channels;
                                                yPos++;
                                        }
                                        buff += pitch;

                                        if (cb) {
                                                percent += dP;
                                                if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                        }
                                }
                        }
                        break;
                }
        case ImageModeRGBColor:
                {
                        ASSERT(m_header.channels == 3);
                        ASSERT(m_header.bpp == m_header.channels*8);
                        ASSERT(bpp%8 == 0);
                        ASSERT(bpp >= m_header.bpp);

                        DataT* y = m_channel[0]; ASSERT(y);
                        DataT* u = m_channel[1]; ASSERT(u);
                        DataT* v = m_channel[2]; ASSERT(v);
                        UINT8 *buffg = &buff[channelMap[1]],
                                  *buffr = &buff[channelMap[2]],
                                  *buffb = &buff[channelMap[0]];
                        UINT8 g;
                        int cnt, channels = bpp/8;
                        if(m_downsample){
                                for (i=0; i < h; i++) {
                                        if (i%2) sampledPos -= (w + 1)/2;
                                        cnt = 0;
                                        for (j=0; j < w; j++) {
                                                // image was downsampled
                                                uAvg = u[sampledPos];
                                                vAvg = v[sampledPos];
                                                // Yuv
                                                buffg[cnt] = g = Clamp8(y[yPos] + YUVoffset8 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
                                                buffr[cnt] = Clamp8(uAvg + g);
                                                buffb[cnt] = Clamp8(vAvg + g);
                                                yPos++;
                                                cnt += channels;
                                                if (j%2) sampledPos++;
                                        }
                                        buffb += pitch;
                                        buffg += pitch;
                                        buffr += pitch;
                                        if (wOdd) sampledPos++;
                                        if (cb) {
                                                percent += dP;
                                                if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                        }
                                }
                        }else{
                                for (i=0; i < h; i++) {
                                        cnt = 0;
                                        for (j = 0; j < w; j++) {
                                                uAvg = u[yPos];
                                                vAvg = v[yPos];
                                                // Yuv
                                                buffg[cnt] = g = Clamp8(y[yPos] + YUVoffset8 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
                                                buffr[cnt] = Clamp8(uAvg + g);
                                                buffb[cnt] = Clamp8(vAvg + g);
                                                yPos++;
                                                cnt += channels;
                                        }
                                        buffb += pitch;
                                        buffg += pitch;
                                        buffr += pitch;

                                        if (cb) {
                                                percent += dP;
                                                if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                        }
                                }
                        }
                        break;
                }
        case ImageModeRGB48:
                {
                        ASSERT(m_header.channels == 3);
                        ASSERT(m_header.bpp == 48);

                        const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);

                        DataT* y = m_channel[0]; ASSERT(y);
                        DataT* u = m_channel[1]; ASSERT(u);
                        DataT* v = m_channel[2]; ASSERT(v);
                        UINT16 g;
                        int cnt, channels;

                        if (bpp >= 48 && bpp%16 == 0) {
                                const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
                                UINT16 *buff16 = (UINT16 *)buff;
                                int pitch16 = pitch/2;
                                channels = bpp/16; ASSERT(channels >= m_header.channels);

                                for (i=0; i < h; i++) {
                                        if (i%2) sampledPos -= (w + 1)/2;
                                        cnt = 0;
                                        for (j=0; j < w; j++) {
                                                if (m_downsample) {
                                                        // image was downsampled
                                                        uAvg = u[sampledPos];
                                                        vAvg = v[sampledPos];
                                                } else {
                                                        uAvg = u[yPos];
                                                        vAvg = v[yPos];
                                                }
                                                // Yuv
                                                g = Clamp16(y[yPos] + yuvOffset16 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
                                                buff16[cnt + channelMap[1]] = g << shift;
                                                buff16[cnt + channelMap[2]] = Clamp16(uAvg + g) << shift;
                                                buff16[cnt + channelMap[0]] = Clamp16(vAvg + g) << shift;
                                                yPos++; 
                                                cnt += channels;
                                                if (j%2) sampledPos++;
                                        }
                                        buff16 += pitch16;
                                        if (wOdd) sampledPos++;

                                        if (cb) {
                                                percent += dP;
                                                if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                        }
                                }
                        } else {
                                ASSERT(bpp%8 == 0);
                                const int shift = __max(0, UsedBitsPerChannel() - 8);
                                channels = bpp/8; ASSERT(channels >= m_header.channels);

                                for (i=0; i < h; i++) {
                                        if (i%2) sampledPos -= (w + 1)/2;
                                        cnt = 0;
                                        for (j=0; j < w; j++) {
                                                if (m_downsample) {
                                                        // image was downsampled
                                                        uAvg = u[sampledPos];
                                                        vAvg = v[sampledPos];
                                                } else {
                                                        uAvg = u[yPos];
                                                        vAvg = v[yPos];
                                                }
                                                // Yuv
                                                g = Clamp16(y[yPos] + yuvOffset16 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
                                                buff[cnt + channelMap[1]] = UINT8(g >> shift); 
                                                buff[cnt + channelMap[2]] = UINT8(Clamp16(uAvg + g) >> shift);
                                                buff[cnt + channelMap[0]] = UINT8(Clamp16(vAvg + g) >> shift);
                                                yPos++; 
                                                cnt += channels;
                                                if (j%2) sampledPos++;
                                        }
                                        buff += pitch;
                                        if (wOdd) sampledPos++;

                                        if (cb) {
                                                percent += dP;
                                                if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                        }
                                }
                        }
                        break;
                }
        case ImageModeLabColor:
                {
                        ASSERT(m_header.channels == 3);
                        ASSERT(m_header.bpp == m_header.channels*8);
                        ASSERT(bpp%8 == 0);

                        DataT* l = m_channel[0]; ASSERT(l);
                        DataT* a = m_channel[1]; ASSERT(a);
                        DataT* b = m_channel[2]; ASSERT(b);
                        int cnt, channels = bpp/8; ASSERT(channels >= m_header.channels);

                        for (i=0; i < h; i++) {
                                if (i%2) sampledPos -= (w + 1)/2;
                                cnt = 0;
                                for (j=0; j < w; j++) {
                                        if (m_downsample) {
                                                // image was downsampled
                                                uAvg = a[sampledPos];
                                                vAvg = b[sampledPos];
                                        } else {
                                                uAvg = a[yPos];
                                                vAvg = b[yPos];
                                        }
                                        buff[cnt + channelMap[0]] = Clamp8(l[yPos] + YUVoffset8);
                                        buff[cnt + channelMap[1]] = Clamp8(uAvg + YUVoffset8); 
                                        buff[cnt + channelMap[2]] = Clamp8(vAvg + YUVoffset8);
                                        cnt += channels;
                                        yPos++;
                                        if (j%2) sampledPos++;
                                }
                                buff += pitch;
                                if (wOdd) sampledPos++;

                                if (cb) {
                                        percent += dP;
                                        if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                }
                        }
                        break;
                }
        case ImageModeLab48:
                {
                        ASSERT(m_header.channels == 3);
                        ASSERT(m_header.bpp == m_header.channels*16);

                        const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);

                        DataT* l = m_channel[0]; ASSERT(l);
                        DataT* a = m_channel[1]; ASSERT(a);
                        DataT* b = m_channel[2]; ASSERT(b);
                        int cnt, channels;

                        if (bpp%16 == 0) {
                                const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
                                UINT16 *buff16 = (UINT16 *)buff;
                                int pitch16 = pitch/2;
                                channels = bpp/16; ASSERT(channels >= m_header.channels);

                                for (i=0; i < h; i++) {
                                        if (i%2) sampledPos -= (w + 1)/2;
                                        cnt = 0;
                                        for (j=0; j < w; j++) {
                                                if (m_downsample) {
                                                        // image was downsampled
                                                        uAvg = a[sampledPos];
                                                        vAvg = b[sampledPos];
                                                } else {
                                                        uAvg = a[yPos];
                                                        vAvg = b[yPos];
                                                }
                                                buff16[cnt + channelMap[0]] = Clamp16(l[yPos] + yuvOffset16) << shift;
                                                buff16[cnt + channelMap[1]] = Clamp16(uAvg + yuvOffset16) << shift;
                                                buff16[cnt + channelMap[2]] = Clamp16(vAvg + yuvOffset16) << shift;
                                                cnt += channels;
                                                yPos++;
                                                if (j%2) sampledPos++;
                                        }
                                        buff16 += pitch16;
                                        if (wOdd) sampledPos++;

                                        if (cb) {
                                                percent += dP;
                                                if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                        }
                                }
                        } else {
                                ASSERT(bpp%8 == 0);
                                const int shift = __max(0, UsedBitsPerChannel() - 8);
                                channels = bpp/8; ASSERT(channels >= m_header.channels);

                                for (i=0; i < h; i++) {
                                        if (i%2) sampledPos -= (w + 1)/2;
                                        cnt = 0;
                                        for (j=0; j < w; j++) {
                                                if (m_downsample) {
                                                        // image was downsampled
                                                        uAvg = a[sampledPos];
                                                        vAvg = b[sampledPos];
                                                } else {
                                                        uAvg = a[yPos];
                                                        vAvg = b[yPos];
                                                }
                                                buff[cnt + channelMap[0]] = UINT8(Clamp16(l[yPos] + yuvOffset16) >> shift);
                                                buff[cnt + channelMap[1]] = UINT8(Clamp16(uAvg + yuvOffset16) >> shift);
                                                buff[cnt + channelMap[2]] = UINT8(Clamp16(vAvg + yuvOffset16) >> shift);
                                                cnt += channels;
                                                yPos++;
                                                if (j%2) sampledPos++;
                                        }
                                        buff += pitch;
                                        if (wOdd) sampledPos++;

                                        if (cb) {
                                                percent += dP;
                                                if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                        }
                                }
                        }
                        break;
                }
        case ImageModeRGBA:
        case ImageModeCMYKColor:
                {
                        ASSERT(m_header.channels == 4);
                        ASSERT(m_header.bpp == m_header.channels*8);
                        ASSERT(bpp%8 == 0);

                        DataT* y = m_channel[0]; ASSERT(y);
                        DataT* u = m_channel[1]; ASSERT(u);
                        DataT* v = m_channel[2]; ASSERT(v);
                        DataT* a = m_channel[3]; ASSERT(a);
                        UINT8 g, aAvg;
                        int cnt, channels = bpp/8; ASSERT(channels >= m_header.channels);

                        for (i=0; i < h; i++) {
                                if (i%2) sampledPos -= (w + 1)/2;
                                cnt = 0;
                                for (j=0; j < w; j++) {
                                        if (m_downsample) {
                                                // image was downsampled
                                                uAvg = u[sampledPos];
                                                vAvg = v[sampledPos];
                                                aAvg = Clamp8(a[sampledPos] + YUVoffset8);
                                        } else {
                                                uAvg = u[yPos];
                                                vAvg = v[yPos];
                                                aAvg = Clamp8(a[yPos] + YUVoffset8);
                                        }
                                        // Yuv
                                        buff[cnt + channelMap[1]] = g = Clamp8(y[yPos] + YUVoffset8 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
                                        buff[cnt + channelMap[2]] = Clamp8(uAvg + g);
                                        buff[cnt + channelMap[0]] = Clamp8(vAvg + g);
                                        buff[cnt + channelMap[3]] = aAvg;
                                        yPos++; 
                                        cnt += channels;
                                        if (j%2) sampledPos++;
                                }
                                buff += pitch;
                                if (wOdd) sampledPos++;

                                if (cb) {
                                        percent += dP;
                                        if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                }
                        }
                        break;
                }
        case ImageModeCMYK64: 
                {
                        ASSERT(m_header.channels == 4);
                        ASSERT(m_header.bpp == 64);

                        const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);

                        DataT* y = m_channel[0]; ASSERT(y);
                        DataT* u = m_channel[1]; ASSERT(u);
                        DataT* v = m_channel[2]; ASSERT(v);
                        DataT* a = m_channel[3]; ASSERT(a);
                        UINT16 g, aAvg;
                        int cnt, channels;

                        if (bpp%16 == 0) {
                                const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
                                UINT16 *buff16 = (UINT16 *)buff;
                                int pitch16 = pitch/2;
                                channels = bpp/16; ASSERT(channels >= m_header.channels);

                                for (i=0; i < h; i++) {
                                        if (i%2) sampledPos -= (w + 1)/2;
                                        cnt = 0;
                                        for (j=0; j < w; j++) {
                                                if (m_downsample) {
                                                        // image was downsampled
                                                        uAvg = u[sampledPos];
                                                        vAvg = v[sampledPos];
                                                        aAvg = Clamp16(a[sampledPos] + yuvOffset16);
                                                } else {
                                                        uAvg = u[yPos];
                                                        vAvg = v[yPos];
                                                        aAvg = Clamp16(a[yPos] + yuvOffset16);
                                                }
                                                // Yuv
                                                g = Clamp16(y[yPos] + yuvOffset16 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
                                                buff16[cnt + channelMap[1]] = g << shift;
                                                buff16[cnt + channelMap[2]] = Clamp16(uAvg + g) << shift;
                                                buff16[cnt + channelMap[0]] = Clamp16(vAvg + g) << shift;
                                                buff16[cnt + channelMap[3]] = aAvg << shift;
                                                yPos++; 
                                                cnt += channels;
                                                if (j%2) sampledPos++;
                                        }
                                        buff16 += pitch16;
                                        if (wOdd) sampledPos++;

                                        if (cb) {
                                                percent += dP;
                                                if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                        }
                                }
                        } else {
                                ASSERT(bpp%8 == 0);
                                const int shift = __max(0, UsedBitsPerChannel() - 8);
                                channels = bpp/8; ASSERT(channels >= m_header.channels);

                                for (i=0; i < h; i++) {
                                        if (i%2) sampledPos -= (w + 1)/2;
                                        cnt = 0;
                                        for (j=0; j < w; j++) {
                                                if (m_downsample) {
                                                        // image was downsampled
                                                        uAvg = u[sampledPos];
                                                        vAvg = v[sampledPos];
                                                        aAvg = Clamp16(a[sampledPos] + yuvOffset16);
                                                } else {
                                                        uAvg = u[yPos];
                                                        vAvg = v[yPos];
                                                        aAvg = Clamp16(a[yPos] + yuvOffset16);
                                                }
                                                // Yuv
                                                g = Clamp16(y[yPos] + yuvOffset16 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
                                                buff[cnt + channelMap[1]] = UINT8(g >> shift); 
                                                buff[cnt + channelMap[2]] = UINT8(Clamp16(uAvg + g) >> shift);
                                                buff[cnt + channelMap[0]] = UINT8(Clamp16(vAvg + g) >> shift);
                                                buff[cnt + channelMap[3]] = UINT8(aAvg >> shift);
                                                yPos++; 
                                                cnt += channels;
                                                if (j%2) sampledPos++;
                                        }
                                        buff += pitch;
                                        if (wOdd) sampledPos++;

                                        if (cb) {
                                                percent += dP;
                                                if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                        }
                                }
                        }
                        break;
                }
#ifdef __PGF32SUPPORT__
        case ImageModeGray32:
                {
                        ASSERT(m_header.channels == 1);
                        ASSERT(m_header.bpp == 32);

                        const int yuvOffset32 = 1 << (UsedBitsPerChannel() - 1);

                        DataT* y = m_channel[0]; ASSERT(y);

                        if (bpp == 32) {
                                const int shift = 32 - UsedBitsPerChannel(); ASSERT(shift >= 0);
                                UINT32 *buff32 = (UINT32 *)buff;
                                int pitch32 = pitch/4;

                                for (i=0; i < h; i++) {
                                        for (j=0; j < w; j++) {
                                                buff32[j] = Clamp31(y[yPos++] + yuvOffset32) << shift;
                                        }
                                        buff32 += pitch32;

                                        if (cb) {
                                                percent += dP;
                                                if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                        }
                                }
                        } else if (bpp == 16) {
                                const int usedBits = UsedBitsPerChannel();
                                UINT16 *buff16 = (UINT16 *)buff;
                                int pitch16 = pitch/2;

                                if (usedBits < 16) {
                                        const int shift = 16 - usedBits;
                                        for (i=0; i < h; i++) {
                                                for (j=0; j < w; j++) {
                                                        buff16[j] = Clamp16(y[yPos++] + yuvOffset32) << shift;
                                                }
                                                buff16 += pitch16;

                                                if (cb) {
                                                        percent += dP;
                                                        if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                                }
                                        }
                                } else {
                                        const int shift = __max(0, usedBits - 16);
                                        for (i=0; i < h; i++) {
                                                for (j=0; j < w; j++) {
                                                        buff16[j] = UINT16(Clamp31(y[yPos++] + yuvOffset32) >> shift);
                                                }
                                                buff16 += pitch16;

                                                if (cb) {
                                                        percent += dP;
                                                        if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                                }
                                        }
                                }
                        } else {
                                ASSERT(bpp == 8);
                                const int shift = __max(0, UsedBitsPerChannel() - 8);
                                
                                for (i=0; i < h; i++) {
                                        for (j=0; j < w; j++) {
                                                buff[j] = UINT8(Clamp31(y[yPos++] + yuvOffset32) >> shift);
                                        }
                                        buff += pitch;

                                        if (cb) {
                                                percent += dP;
                                                if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                        }
                                }
                        }
                        break;  
                }
#endif
        case ImageModeRGB12: 
                {
                        ASSERT(m_header.channels == 3);
                        ASSERT(m_header.bpp == m_header.channels*4);
                        ASSERT(bpp == m_header.channels*4);
                        ASSERT(!m_downsample);

                        DataT* y = m_channel[0]; ASSERT(y);
                        DataT* u = m_channel[1]; ASSERT(u);
                        DataT* v = m_channel[2]; ASSERT(v);
                        UINT16 yval;
                        int cnt;

                        for (i=0; i < h; i++) {
                                cnt = 0;
                                for (j=0; j < w; j++) {
                                        // Yuv
                                        uAvg = u[yPos];
                                        vAvg = v[yPos];
                                        yval = Clamp4(y[yPos++] + YUVoffset4 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
                                        if (j%2 == 0) {
                                                buff[cnt] = UINT8(Clamp4(vAvg + yval) | (yval << 4));
                                                cnt++;
                                                buff[cnt] = Clamp4(uAvg + yval);
                                        } else {
                                                buff[cnt] |= Clamp4(vAvg + yval) << 4;
                                                cnt++;
                                                buff[cnt] = UINT8(yval | (Clamp4(uAvg + yval) << 4));
                                                cnt++;
                                        }
                                }
                                buff += pitch;

                                if (cb) {
                                        percent += dP;
                                        if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                }
                        }
                        break;
                }
        case ImageModeRGB16: 
                {
                        ASSERT(m_header.channels == 3);
                        ASSERT(m_header.bpp == 16);
                        ASSERT(bpp == 16);
                        ASSERT(!m_downsample);

                        DataT* y = m_channel[0]; ASSERT(y);
                        DataT* u = m_channel[1]; ASSERT(u);
                        DataT* v = m_channel[2]; ASSERT(v);
                        UINT16 yval;
                        UINT16 *buff16 = (UINT16 *)buff;
                        int pitch16 = pitch/2;

                        for (i=0; i < h; i++) {
                                for (j=0; j < w; j++) {
                                        // Yuv
                                        uAvg = u[yPos];
                                        vAvg = v[yPos];
                                        yval = Clamp6(y[yPos++] + YUVoffset6 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
                                        buff16[j] = (yval << 5) | ((Clamp6(uAvg + yval) >> 1) << 11) | (Clamp6(vAvg + yval) >> 1);
                                }
                                buff16 += pitch16;

                                if (cb) {
                                        percent += dP;
                                        if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                }
                        }
                        break;
                }
        default:
                ASSERT(false);
        }

#ifdef __PGFROISUPPORT__
        if (targetBuff) {
                // copy valid ROI (m_roi) from temporary buffer (roi) to target buffer
                if (bpp%8 == 0) {
                        BYTE bypp = bpp/8;
                        buff = buffStart + (levelRoi.top - roi.top)*pitch + (levelRoi.left - roi.left)*bypp;
                        w = levelRoi.Width()*bypp;
                        h = levelRoi.Height();

                        for (i=0; i < h; i++) {
                                for (j=0; j < w; j++) {
                                        targetBuff[j] = buff[j];
                                }
                                targetBuff += targetPitch;
                                buff += pitch;
                        }
                } else {
                        // to do
                }

                delete[] buffStart;
        }
#endif
}                       
DataT* CPGFImage::GetChannel ( int  c = 0) [inline]

Return the background color of an RGB image with transparency channel.

Returns:
Background color in RGB Return an internal YUV image channel.
Parameters:
cA channel index
Returns:
An internal YUV image channel

Definition at line 315 of file PGFimage.h.

{ ASSERT(c >= 0 && c < MaxChannels); return m_channel[c]; }
void CPGFImage::GetColorTable ( UINT32  iFirstColor,
UINT32  nColors,
RGBQUAD *  prgbColors 
) const

Retrieves red, green, blue (RGB) color values from a range of entries in the palette of the DIB section. It might throw an IOException.

Parameters:
iFirstColorThe color table index of the first entry to retrieve.
nColorsThe number of color table entries to retrieve.
prgbColorsA pointer to the array of RGBQUAD structures to retrieve the color table entries.

Definition at line 1240 of file PGFimage.cpp.

                                                                                                  {
        if (iFirstColor + nColors > ColorTableLen)      ReturnWithError(ColorTableError);

        for (UINT32 i=iFirstColor, j=0; j < nColors; i++, j++) {
                prgbColors[j] = m_postHeader.clut[i];
        }
}
const RGBQUAD* CPGFImage::GetColorTable ( ) const [inline]
Returns:
Address of color table

Definition at line 328 of file PGFimage.h.

{ return m_postHeader.clut; }

Return the length of all encoded headers in bytes. Precondition: The PGF image has been opened with a call of Open(...).

Returns:
The length of all encoded headers in bytes

Definition at line 592 of file PGFimage.cpp.

                                               { 
        ASSERT(m_decoder); 
        return m_decoder->GetEncodedHeaderLength(); 
}
UINT32 CPGFImage::GetEncodedLevelLength ( int  level) const [inline]

Return the length of an encoded PGF level in bytes. Precondition: The PGF image has been opened with a call of Open(...).

Parameters:
levelThe image level
Returns:
The length of a PGF level in bytes

Definition at line 358 of file PGFimage.h.

{ ASSERT(level >= 0 && level < m_header.nLevels); return m_levelLength[m_header.nLevels - level - 1]; }
const PGFHeader* CPGFImage::GetHeader ( ) const [inline]

Return the PGF header structure.

Returns:
A PGF header structure

Definition at line 333 of file PGFimage.h.

{ return &m_header; }
UINT32 CPGFImage::GetMaxValue ( ) const [inline]

Get maximum intensity value for image modes with more than eight bits per channel. Don't call this method before the PGF header has been read.

Returns:
The maximum intensity value.

Definition at line 339 of file PGFimage.h.

{ return (1 << m_header.usedBitsPerChannel) - 1; }
const UINT8 * CPGFImage::GetUserData ( UINT32 &  size) const

Return user data and size of user data.

Parameters:
size[out] Size of user data in bytes.
Returns:
A pointer to user data or NULL if there is no user data.

Definition at line 309 of file PGFimage.cpp.

void CPGFImage::GetYUV ( int  pitch,
DataT buff,
BYTE  bpp,
int  channelMap[] = NULL,
CallbackPtr  cb = NULL,
void *  data = NULL 
) const

Get YUV image data in interleaved format: (ordering is YUV[A]) The absolute value of pitch is the number of bytes of an image row of the given image buffer. If pitch is negative, then the image buffer must point to the last row of a bottom-up image (first byte on last row). if pitch is positive, then the image buffer must point to the first row of a top-down image (first byte). The sequence of output channels in the output image buffer does not need to be the same as provided by PGF. In case of different sequences you have to provide a channelMap of size of expected channels (depending on image mode). For example, PGF provides a channel sequence BGR in RGB color mode. If your provided image buffer expects a channel sequence VUY, then the channelMap looks like { 2, 1, 0 }. It might throw an IOException.

Parameters:
pitchThe number of bytes of a row of the image buffer.
buffAn image buffer.
bppThe number of bits per pixel used in image buffer.
channelMapA integer array containing the mapping of PGF channel ordering to expected channel ordering.
cbA pointer to a callback procedure. The procedure is called after each copied buffer row. If cb returns true, then it stops proceeding.
dataData Pointer to C++ class container to host callback procedure.

Get YUV image data in interleaved format: (ordering is YUV[A]) The absolute value of pitch is the number of bytes of an image row of the given image buffer. If pitch is negative, then the image buffer must point to the last row of a bottom-up image (first byte on last row). if pitch is positive, then the image buffer must point to the first row of a top-down image (first byte). The sequence of output channels in the output image buffer does not need to be the same as provided by PGF. In case of different sequences you have to provide a channelMap of size of expected channels (depending on image mode). For example, PGF provides a channel sequence BGR in RGB color mode. If your provided image buffer expects a channel sequence VUY, then the channelMap looks like { 2, 1, 0 }. It might throw an IOException.

Parameters:
pitchThe number of bytes of a row of the image buffer.
buffAn image buffer.
bppThe number of bits per pixel used in image buffer.
channelMapA integer array containing the mapping of PGF channel ordering to expected channel ordering.
cbA pointer to a callback procedure. The procedure is called after each copied buffer row. If cb returns true, then it stops proceeding.

Definition at line 2426 of file PGFimage.cpp.

                                                                                                                        {
        ASSERT(buff);
        const UINT32 w = m_width[0];
        const UINT32 h = m_height[0];
        const bool wOdd = (1 == w%2);
        const int dataBits = DataTSize*8; ASSERT(dataBits == 16 || dataBits == 32);
        const int pitch2 = pitch/DataTSize;
        const int yuvOffset = (dataBits == 16) ? YUVoffset8 : YUVoffset16;
        const double dP = 1.0/h;

        int defMap[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; ASSERT(sizeof(defMap)/sizeof(defMap[0]) == MaxChannels);
        if (channelMap == NULL) channelMap = defMap;
        int sampledPos = 0, yPos = 0;
        DataT uAvg, vAvg;
        double percent = 0;
        UINT32 i, j;

        if (m_header.channels == 3) { 
                ASSERT(bpp%dataBits == 0);

                DataT* y = m_channel[0]; ASSERT(y);
                DataT* u = m_channel[1]; ASSERT(u);
                DataT* v = m_channel[2]; ASSERT(v);
                int cnt, channels = bpp/dataBits; ASSERT(channels >= m_header.channels);

                for (i=0; i < h; i++) {
                        if (i%2) sampledPos -= (w + 1)/2;
                        cnt = 0;
                        for (j=0; j < w; j++) {
                                if (m_downsample) {
                                        // image was downsampled
                                        uAvg = u[sampledPos];
                                        vAvg = v[sampledPos];
                                } else {
                                        uAvg = u[yPos];
                                        vAvg = v[yPos];
                                }
                                buff[cnt + channelMap[0]] = y[yPos];
                                buff[cnt + channelMap[1]] = uAvg;
                                buff[cnt + channelMap[2]] = vAvg;
                                yPos++; 
                                cnt += channels;
                                if (j%2) sampledPos++;
                        }
                        buff += pitch2;
                        if (wOdd) sampledPos++;

                        if (cb) {
                                percent += dP;
                                if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                        }
                }
        } else if (m_header.channels == 4) {
                ASSERT(m_header.bpp == m_header.channels*8);
                ASSERT(bpp%dataBits == 0);

                DataT* y = m_channel[0]; ASSERT(y);
                DataT* u = m_channel[1]; ASSERT(u);
                DataT* v = m_channel[2]; ASSERT(v);
                DataT* a = m_channel[3]; ASSERT(a);
                UINT8 aAvg;
                int cnt, channels = bpp/dataBits; ASSERT(channels >= m_header.channels);

                for (i=0; i < h; i++) {
                        if (i%2) sampledPos -= (w + 1)/2;
                        cnt = 0;
                        for (j=0; j < w; j++) {
                                if (m_downsample) {
                                        // image was downsampled
                                        uAvg = u[sampledPos];
                                        vAvg = v[sampledPos];
                                        aAvg = Clamp8(a[sampledPos] + yuvOffset);
                                } else {
                                        uAvg = u[yPos];
                                        vAvg = v[yPos];
                                        aAvg = Clamp8(a[yPos] + yuvOffset);
                                }
                                // Yuv
                                buff[cnt + channelMap[0]] = y[yPos];
                                buff[cnt + channelMap[1]] = uAvg;
                                buff[cnt + channelMap[2]] = vAvg;
                                buff[cnt + channelMap[3]] = aAvg;
                                yPos++; 
                                cnt += channels;
                                if (j%2) sampledPos++;
                        }
                        buff += pitch2;
                        if (wOdd) sampledPos++;

                        if (cb) {
                                percent += dP;
                                if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                        }
                }
        }
}
UINT32 CPGFImage::Height ( int  level = 0) const [inline]

Return image height of channel 0 at given level in pixels. The returned height is independent of any Read-operations and ROI.

Parameters:
levelA level
Returns:
Image level height in pixels

Definition at line 415 of file PGFimage.h.

{ ASSERT(level >= 0); return LevelHeight(m_header.height, level); }
void CPGFImage::ImportBitmap ( int  pitch,
UINT8 *  buff,
BYTE  bpp,
int  channelMap[] = NULL,
CallbackPtr  cb = NULL,
void *  data = NULL 
)

Import an image from a specified image buffer. This method is usually called before Write(...) and after SetHeader(...). The absolute value of pitch is the number of bytes of an image row. If pitch is negative, then buff points to the last row of a bottom-up image (first byte on last row). If pitch is positive, then buff points to the first row of a top-down image (first byte). The sequence of input channels in the input image buffer does not need to be the same as expected from PGF. In case of different sequences you have to provide a channelMap of size of expected channels (depending on image mode). For example, PGF expects in RGB color mode a channel sequence BGR. If your provided image buffer contains a channel sequence ARGB, then the channelMap looks like { 3, 2, 1, 0 }. It might throw an IOException.

Parameters:
pitchThe number of bytes of a row of the image buffer.
buffAn image buffer.
bppThe number of bits per pixel used in image buffer.
channelMapA integer array containing the mapping of input channel ordering to expected channel ordering.
cbA pointer to a callback procedure. The procedure is called after each imported buffer row. If cb returns true, then it stops proceeding.
dataData Pointer to C++ class container to host callback procedure.

Definition at line 737 of file PGFimage.cpp.

                                                                                                                        {
        ASSERT(buff);
        ASSERT(m_channel[0]);

        // color transform
        RgbToYuv(pitch, buff, bpp, channelMap, cb, data);

        if (m_downsample) {
                // Subsampling of the chrominance and alpha channels
                for (int i=1; i < m_header.channels; i++) {
                        Downsample(i);
                }
        }
}
bool CPGFImage::ImportIsSupported ( BYTE  mode) [static]

Check for valid import image mode.

Parameters:
modeImage mode
Returns:
True if an image of given mode can be imported with ImportBitmap(...)

Definition at line 1195 of file PGFimage.cpp.

                                           {
        size_t size = DataTSize;

        if (size >= 2) {
                switch(mode) {
                        case ImageModeBitmap:
                        case ImageModeIndexedColor:
                        case ImageModeGrayScale:
                        case ImageModeRGBColor:
                        case ImageModeCMYKColor:
                        case ImageModeHSLColor:
                        case ImageModeHSBColor:
                        //case ImageModeDuotone:
                        case ImageModeLabColor:
                        case ImageModeRGB12:
                        case ImageModeRGB16:
                        case ImageModeRGBA:
                                return true;
                }
        }
        if (size >= 3) {
                switch(mode) {
                        case ImageModeGray16:
                        case ImageModeRGB48:
                        case ImageModeLab48:
                        case ImageModeCMYK64:
                        //case ImageModeDuotone16:
                                return true;
                }
        }
        if (size >=4) {
                switch(mode) {
                        case ImageModeGray32:
                                return true;
                }
        }
        return false;
}
void CPGFImage::ImportYUV ( int  pitch,
DataT buff,
BYTE  bpp,
int  channelMap[] = NULL,
CallbackPtr  cb = NULL,
void *  data = NULL 
)

Import a YUV image from a specified image buffer. The absolute value of pitch is the number of bytes of an image row. If pitch is negative, then buff points to the last row of a bottom-up image (first byte on last row). If pitch is positive, then buff points to the first row of a top-down image (first byte). The sequence of input channels in the input image buffer does not need to be the same as expected from PGF. In case of different sequences you have to provide a channelMap of size of expected channels (depending on image mode). For example, PGF expects in RGB color mode a channel sequence BGR. If your provided image buffer contains a channel sequence VUY, then the channelMap looks like { 2, 1, 0 }. It might throw an IOException.

Parameters:
pitchThe number of bytes of a row of the image buffer.
buffAn image buffer.
bppThe number of bits per pixel used in image buffer.
channelMapA integer array containing the mapping of input channel ordering to expected channel ordering.
cbA pointer to a callback procedure. The procedure is called after each imported buffer row. If cb returns true, then it stops proceeding.
dataData Pointer to C++ class container to host callback procedure.

Import a YUV image from a specified image buffer. The absolute value of pitch is the number of bytes of an image row. If pitch is negative, then buff points to the last row of a bottom-up image (first byte on last row). If pitch is positive, then buff points to the first row of a top-down image (first byte). The sequence of input channels in the input image buffer does not need to be the same as expected from PGF. In case of different sequences you have to provide a channelMap of size of expected channels (depending on image mode). For example, PGF expects in RGB color mode a channel sequence BGR. If your provided image buffer contains a channel sequence VUY, then the channelMap looks like { 2, 1, 0 }. It might throw an IOException.

Parameters:
pitchThe number of bytes of a row of the image buffer.
buffAn image buffer.
bppThe number of bits per pixel used in image buffer.
channelMapA integer array containing the mapping of input channel ordering to expected channel ordering.
cbA pointer to a callback procedure. The procedure is called after each imported buffer row. If cb returns true, then it stops proceeding.

Definition at line 2537 of file PGFimage.cpp.

                                                                                                                     {
        ASSERT(buff);
        const double dP = 1.0/m_header.height;
        const int dataBits = DataTSize*8; ASSERT(dataBits == 16 || dataBits == 32);
        const int pitch2 = pitch/DataTSize;
        const int yuvOffset = (dataBits == 16) ? YUVoffset8 : YUVoffset16;

        int yPos = 0, cnt = 0;
        double percent = 0;
        int defMap[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; ASSERT(sizeof(defMap)/sizeof(defMap[0]) == MaxChannels);

        if (channelMap == NULL) channelMap = defMap;

        if (m_header.channels == 3)     {
                ASSERT(bpp%dataBits == 0);

                DataT* y = m_channel[0]; ASSERT(y);
                DataT* u = m_channel[1]; ASSERT(u);
                DataT* v = m_channel[2]; ASSERT(v);
                const int channels = bpp/dataBits; ASSERT(channels >= m_header.channels);

                for (UINT32 h=0; h < m_header.height; h++) {
                        if (cb) {
                                if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                percent += dP;
                        }

                        cnt = 0;
                        for (UINT32 w=0; w < m_header.width; w++) {
                                y[yPos] = buff[cnt + channelMap[0]];
                                u[yPos] = buff[cnt + channelMap[1]];
                                v[yPos] = buff[cnt + channelMap[2]];
                                yPos++;
                                cnt += channels;
                        }
                        buff += pitch2;
                }       
        } else if (m_header.channels == 4) {
                ASSERT(bpp%dataBits == 0);

                DataT* y = m_channel[0]; ASSERT(y);
                DataT* u = m_channel[1]; ASSERT(u);
                DataT* v = m_channel[2]; ASSERT(v);
                DataT* a = m_channel[3]; ASSERT(a);
                const int channels = bpp/dataBits; ASSERT(channels >= m_header.channels);

                for (UINT32 h=0; h < m_header.height; h++) {
                        if (cb) {
                                if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                percent += dP;
                        }

                        cnt = 0;
                        for (UINT32 w=0; w < m_header.width; w++) {
                                y[yPos] = buff[cnt + channelMap[0]];
                                u[yPos] = buff[cnt + channelMap[1]];
                                v[yPos] = buff[cnt + channelMap[2]];
                                a[yPos] = buff[cnt + channelMap[3]] - yuvOffset;
                                yPos++;
                                cnt += channels;
                        }
                        buff += pitch2;
                }       
        }

        if (m_downsample) {
                // Subsampling of the chrominance and alpha channels
                for (int i=1; i < m_header.channels; i++) {
                        Downsample(i);
                }
        }
}
bool CPGFImage::IsOpen ( ) const [inline]

Returns true if the PGF has been opened and not closed.

Definition at line 81 of file PGFimage.h.

{ return m_decoder != NULL; }
BYTE CPGFImage::Level ( ) const [inline]

Return current image level. Since Read(...) can be used to read each image level separately, it is helpful to know the current level. The current level immediately after Open(...) is Levels().

Returns:
Current image level

Definition at line 422 of file PGFimage.h.

{ return (BYTE)m_currentLevel; }
static UINT32 CPGFImage::LevelHeight ( UINT32  height,
int  level 
) [inline, static]

Compute and return image height at given level.

Parameters:
heightOriginal image height (at level 0)
levelAn image level
Returns:
Image level height in pixels

Definition at line 484 of file PGFimage.h.

{ ASSERT(level >= 0); UINT32 h = (height >> level); return ((h << level) == height) ? h : h + 1; }
BYTE CPGFImage::Levels ( ) const [inline]

Return the number of image levels.

Returns:
Number of image levels

Definition at line 427 of file PGFimage.h.

{ return m_header.nLevels; }
static UINT32 CPGFImage::LevelWidth ( UINT32  width,
int  level 
) [inline, static]

Compute and return image width at given level.

Parameters:
widthOriginal image width (at level 0)
levelAn image level
Returns:
Image level width in pixels

Definition at line 477 of file PGFimage.h.

{ ASSERT(level >= 0); UINT32 w = (width >> level); return ((w << level) == width) ? w : w + 1; }
BYTE CPGFImage::Mode ( ) const [inline]

Return the image mode. An image mode is a predefined constant value (see also PGFtypes.h) compatible with Adobe Photoshop. It represents an image type and format.

Returns:
Image mode

Definition at line 446 of file PGFimage.h.

{ return m_header.mode; }
void CPGFImage::Open ( CPGFStream stream)

Open a PGF image at current stream position: read pre-header, header, and ckeck image type. Precondition: The stream has been opened for reading. It might throw an IOException.

Parameters:
streamA PGF stream

Definition at line 125 of file PGFimage.cpp.

                                              {
        ASSERT(stream);

        m_decoder = new CDecoder(stream, m_preHeader, m_header, m_postHeader, m_levelLength, m_useOMPinDecoder);

        if (m_header.nLevels > MaxLevel) ReturnWithError(FormatCannotRead);

        // set current level
        m_currentLevel = m_header.nLevels;

        // set image width and height
        m_width[0] = m_header.width;
        m_height[0] = m_header.height;

        // complete header
        CompleteHeader();

        // interpret quant parameter
        if (m_header.quality > DownsampleThreshold && 
                (m_header.mode == ImageModeRGBColor || 
                 m_header.mode == ImageModeRGBA || 
                 m_header.mode == ImageModeRGB48 || 
                 m_header.mode == ImageModeCMYKColor || 
                 m_header.mode == ImageModeCMYK64 || 
                 m_header.mode == ImageModeLabColor || 
                 m_header.mode == ImageModeLab48)) {
                m_downsample = true;
                m_quant = m_header.quality - 1;
        } else {
                m_downsample = false;
                m_quant = m_header.quality;
        }

        // set channel dimensions (chrominance is subsampled by factor 2)
        if (m_downsample) {
                for (int i=1; i < m_header.channels; i++) {
                        m_width[i] = (m_width[0] + 1)/2;
                        m_height[i] = (m_height[0] + 1)/2;
                }
        } else {
                for (int i=1; i < m_header.channels; i++) {
                        m_width[i] = m_width[0];
                        m_height[i] = m_height[0];
                }
        }

        if (m_header.nLevels > 0) {
                // init wavelet subbands
                for (int i=0; i < m_header.channels; i++) {
                        m_wtChannel[i] = new CWaveletTransform(m_width[i], m_height[i], m_header.nLevels);
                }
        } else {
                // very small image: we don't use DWT and encoding

                // read channels
                for (int c=0; c < m_header.channels; c++) {
                        const UINT32 size = m_width[c]*m_height[c];
                        m_channel[c] = new DataT[size];

                        // read channel data from stream
                        for (UINT32 i=0; i < size; i++) {
                                int count = DataTSize;
                                stream->Read(&count, &m_channel[c][i]);
                                if (count != DataTSize) ReturnWithError(MissingData);
                        }
                }
        }
}
BYTE CPGFImage::Quality ( ) const [inline]

Return the PGF quality. The quality is inbetween 0 and MaxQuality. PGF quality 0 means lossless quality.

Returns:
PGF quality

Definition at line 433 of file PGFimage.h.

{ return m_header.quality; }
void CPGFImage::Read ( int  level = 0,
CallbackPtr  cb = NULL,
void *  data = NULL 
)

Read and decode some levels of a PGF image at current stream position. A PGF image is structered in levels, numbered between 0 and Levels() - 1. Each level can be seen as a single image, containing the same content as all other levels, but in a different size (width, height). The image size at level i is double the size (width, height) of the image at level i+1. The image at level 0 contains the original size. Precondition: The PGF image has been opened with a call of Open(...). It might throw an IOException.

Parameters:
level[0, nLevels) The image level of the resulting image in the internal image buffer.
cbA pointer to a callback procedure. The procedure is called after reading a single level. If cb returns true, then it stops proceeding.
dataData Pointer to C++ class container to host callback procedure.

Definition at line 370 of file PGFimage.cpp.

                                                                       {
        ASSERT((level >= 0 && level < m_header.nLevels) || m_header.nLevels == 0); // m_header.nLevels == 0: image didn't use wavelet transform
        ASSERT(m_decoder);

#ifdef __PGFROISUPPORT__
        if (ROIisSupported() && m_header.nLevels > 0) {
                // new encoding scheme supporting ROI
                PGFRect rect(0, 0, m_header.width, m_header.height);
                Read(rect, level, cb, data);
                return;
        }
#endif

        if (m_header.nLevels == 0) {
                if (level == 0) {
                        // the data has already been read during open
                        // now update progress
                        if (cb) {
                                if ((*cb)(1.0, true, data)) ReturnWithError(EscapePressed);
                        }
                }
        } else {
                const int levelDiff = m_currentLevel - level;
                double percent = pow(0.25, levelDiff);

                // encoding scheme without ROI
                while (m_currentLevel > level) {
                        for (int i=0; i < m_header.channels; i++) {
                                ASSERT(m_wtChannel[i]);
                                // decode file and write stream to m_wtChannel
                                if (m_currentLevel == m_header.nLevels) { 
                                        // last level also has LL band
                                        m_wtChannel[i]->GetSubband(m_currentLevel, LL)->PlaceTile(*m_decoder, m_quant);
                                }
                                if (m_preHeader.version & Version5) {
                                        // since version 5
                                        m_wtChannel[i]->GetSubband(m_currentLevel, HL)->PlaceTile(*m_decoder, m_quant);
                                        m_wtChannel[i]->GetSubband(m_currentLevel, LH)->PlaceTile(*m_decoder, m_quant);
                                } else {
                                        // until version 4
                                        m_decoder->DecodeInterleaved(m_wtChannel[i], m_currentLevel, m_quant);
                                }
                                m_wtChannel[i]->GetSubband(m_currentLevel, HH)->PlaceTile(*m_decoder, m_quant);
                        }

                        volatile OSError error = NoError; // volatile prevents optimizations
                        #pragma omp parallel for default(shared) 
                        for (int i=0; i < m_header.channels; i++) {
                                // inverse transform from m_wtChannel to m_channel
                                if (error == NoError) {
                                        OSError err = m_wtChannel[i]->InverseTransform(m_currentLevel, &m_width[i], &m_height[i], &m_channel[i]);       
                                        if (err != NoError) error = err;
                                }
                                ASSERT(m_channel[i]);
                        }
                        if (error != NoError) ReturnWithError(error);

                        // set new level: must be done before refresh callback
                        m_currentLevel--;

                        // now we have to refresh the display
                        if (m_cb) m_cb(m_cbArg);

                        // now update progress
                        if (cb) {
                                percent += 3*percent;
                                if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                        }
                }
        }

        // automatically closing
        if (m_currentLevel == 0) Close();
}
void CPGFImage::Read ( PGFRect rect,
int  level = 0,
CallbackPtr  cb = NULL,
void *  data = NULL 
)

Read a rectangular region of interest of a PGF image at current stream position. The origin of the coordinate axis is the top-left corner of the image. All coordinates are measured in pixels. It might throw an IOException.

Parameters:
rect[inout] Rectangular region of interest (ROI). The rect might be cropped.
level[0, nLevels) The image level of the resulting image in the internal image buffer.
cbA pointer to a callback procedure. The procedure is called after reading a single level. If cb returns true, then it stops proceeding.
dataData Pointer to C++ class container to host callback procedure.
UINT32 CPGFImage::ReadEncodedData ( int  level,
UINT8 *  target,
UINT32  targetLen 
) const

Reads the data of an encoded PGF level and copies it to a target buffer without decoding. Precondition: The PGF image has been opened with a call of Open(...). It might throw an IOException.

Parameters:
levelThe image level
targetThe target buffer
targetLenThe length of the target buffer in bytes
Returns:
The number of bytes copied to the target buffer

Definition at line 638 of file PGFimage.cpp.

                                                                                         {
        ASSERT(level >= 0 && level < m_header.nLevels);
        ASSERT(target);
        ASSERT(targetLen > 0);
        ASSERT(m_decoder);

        // reset stream position
        m_decoder->SetStreamPosToData();

        // position stream
        UINT64 offset = 0;

        for (int i=m_header.nLevels - 1; i > level; i--) {
                offset += m_levelLength[m_header.nLevels - 1 - i];
        }
        m_decoder->Skip(offset);

        // compute number of bytes to read
        UINT32 len = __min(targetLen, GetEncodedLevelLength(level));

        // read data
        len = m_decoder->ReadEncodedData(target, len);
        ASSERT(len >= 0 && len <= targetLen);

        return len;
}
UINT32 CPGFImage::ReadEncodedHeader ( UINT8 *  target,
UINT32  targetLen 
) const

Reads the encoded PGF headers and copies it to a target buffer. Precondition: The PGF image has been opened with a call of Open(...). It might throw an IOException.

Parameters:
targetThe target buffer
targetLenThe length of the target buffer in bytes
Returns:
The number of bytes copied to the target buffer

Definition at line 604 of file PGFimage.cpp.

                                                                                {
        ASSERT(target);
        ASSERT(targetLen > 0);
        ASSERT(m_decoder);

        // reset stream position
        m_decoder->SetStreamPosToStart();

        // compute number of bytes to read
        UINT32 len = __min(targetLen, GetEncodedHeaderLength());

        // read data
        len = m_decoder->ReadEncodedData(target, len);
        ASSERT(len >= 0 && len <= targetLen);

        return len;
}
void CPGFImage::ReadPreview ( ) [inline]

Read and decode smallest level of a PGF image at current stream position. For details, please refert to Read(...) Precondition: The PGF image has been opened with a call of Open(...). It might throw an IOException.

Definition at line 115 of file PGFimage.h.

{ Read(Levels() - 1); }
void CPGFImage::Reconstruct ( int  level = 0)

After you've written a PGF image, you can call this method followed by GetBitmap/GetYUV to get a quick reconstruction (coded -> decoded image). It might throw an IOException.

Parameters:
levelThe image level of the resulting image in the internal image buffer.

Definition at line 319 of file PGFimage.cpp.

                                              {
        if (m_header.nLevels == 0) {
                // image didn't use wavelet transform
                if (level == 0) {
                        for (int i=0; i < m_header.channels; i++) {
                                ASSERT(m_wtChannel[i]);
                                m_channel[i] = m_wtChannel[i]->GetSubband(0, LL)->GetBuffer();
                        }
                }
        } else {
                int currentLevel = m_header.nLevels;

                if (ROIisSupported()) {
                        // enable ROI reading
                        SetROI(PGFRect(0, 0, m_header.width, m_header.height));
                }

                while (currentLevel > level) {
                        for (int i=0; i < m_header.channels; i++) {
                                ASSERT(m_wtChannel[i]);
                                // dequantize subbands
                                if (currentLevel == m_header.nLevels) { 
                                        // last level also has LL band
                                        m_wtChannel[i]->GetSubband(currentLevel, LL)->Dequantize(m_quant);
                                }
                                m_wtChannel[i]->GetSubband(currentLevel, HL)->Dequantize(m_quant);
                                m_wtChannel[i]->GetSubband(currentLevel, LH)->Dequantize(m_quant);
                                m_wtChannel[i]->GetSubband(currentLevel, HH)->Dequantize(m_quant);

                                // inverse transform from m_wtChannel to m_channel
                                if (!m_wtChannel[i]->InverseTransform(currentLevel, &m_width[i], &m_height[i], &m_channel[i])) ReturnWithError(InsufficientMemory);
                                ASSERT(m_channel[i]);
                        }

                        currentLevel--;
                }
        }
}

Reset stream position to start of PGF pre-header

Definition at line 624 of file PGFimage.cpp.

                                      {
        ASSERT(m_decoder);
        return m_decoder->SetStreamPosToStart(); 
}
void CPGFImage::RgbToYuv ( int  pitch,
UINT8 *  rgbBuff,
BYTE  bpp,
int  channelMap[],
CallbackPtr  cb,
void *  data 
) [private]

Definition at line 1279 of file PGFimage.cpp.

                                                                                                                {
        ASSERT(buff);
        int yPos = 0, cnt = 0;
        double percent = 0;
        const double dP = 1.0/m_header.height;
        int defMap[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; ASSERT(sizeof(defMap)/sizeof(defMap[0]) == MaxChannels);

        if (channelMap == NULL) channelMap = defMap;

        switch(m_header.mode) {
        case ImageModeBitmap:
                {
                        ASSERT(m_header.channels == 1);
                        ASSERT(m_header.bpp == 1);
                        ASSERT(bpp == 1);
                        
                        const UINT32 w = m_header.width;
                        const UINT32 w2 = (m_header.width + 7)/8;
                        DataT* y = m_channel[0]; ASSERT(y);

                        for (UINT32 h=0; h < m_header.height; h++) {
                                if (cb) {
                                        if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                        percent += dP;
                                }
                                
                                for (UINT32 j=0; j < w2; j++) {
                                        y[yPos++] = buff[j] - YUVoffset8;
                                }
                                for (UINT32 j=w2; j < w; j++) {
                                        y[yPos++] = YUVoffset8;
                                }
                                
                                //UINT cnt = w;
                                //for (UINT32 j=0; j < w2; j++) {
                                //      for (int k=7; k >= 0; k--) {
                                //              if (cnt) { 
                                //                      y[yPos++] = YUVoffset8 + (1 & (buff[j] >> k));
                                //                      cnt--;
                                //              }
                                //      }
                                //}
                                buff += pitch;  
                        }
                }
                break;
        case ImageModeIndexedColor:
        case ImageModeGrayScale:
        case ImageModeHSLColor:
        case ImageModeHSBColor:
        case ImageModeLabColor:
                {
                        ASSERT(m_header.channels >= 1);
                        ASSERT(m_header.bpp == m_header.channels*8);
                        ASSERT(bpp%8 == 0);
                        const int channels = bpp/8; ASSERT(channels >= m_header.channels);

                        for (UINT32 h=0; h < m_header.height; h++) {
                                if (cb) {
                                        if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                        percent += dP;
                                }

                                cnt = 0;
                                for (UINT32 w=0; w < m_header.width; w++) {
                                        for (int c=0; c < m_header.channels; c++) {
                                                m_channel[c][yPos] = buff[cnt + channelMap[c]] - YUVoffset8;
                                        }
                                        cnt += channels;
                                        yPos++;
                                }
                                buff += pitch;  
                        }
                }
                break;
        case ImageModeGray16:
        case ImageModeLab48:
                {
                        ASSERT(m_header.channels >= 1);
                        ASSERT(m_header.bpp == m_header.channels*16);
                        ASSERT(bpp%16 == 0);

                        UINT16 *buff16 = (UINT16 *)buff;
                        const int pitch16 = pitch/2;
                        const int channels = bpp/16; ASSERT(channels >= m_header.channels);
                        const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
                        const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);

                        for (UINT32 h=0; h < m_header.height; h++) {
                                if (cb) {
                                        if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                        percent += dP;
                                }

                                cnt = 0;
                                for (UINT32 w=0; w < m_header.width; w++) {
                                        for (int c=0; c < m_header.channels; c++) {
                                                m_channel[c][yPos] = (buff16[cnt + channelMap[c]] >> shift) - yuvOffset16;
                                        }
                                        cnt += channels;
                                        yPos++;
                                }
                                buff16 += pitch16;
                        }
                }
                break;
        case ImageModeRGBColor:
                {
                        ASSERT(m_header.channels == 3);
                        ASSERT(m_header.bpp == m_header.channels*8);
                        ASSERT(bpp%8 == 0);

                        DataT* y = m_channel[0]; ASSERT(y);
                        DataT* u = m_channel[1]; ASSERT(u);
                        DataT* v = m_channel[2]; ASSERT(v);
                        const int channels = bpp/8; ASSERT(channels >= m_header.channels);
                        UINT8 b, g, r;

                        for (UINT32 h=0; h < m_header.height; h++) {
                                if (cb) {
                                        if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                        percent += dP;
                                }

                                cnt = 0;
                                for (UINT32 w=0; w < m_header.width; w++) {
                                        b = buff[cnt + channelMap[0]];
                                        g = buff[cnt + channelMap[1]];
                                        r = buff[cnt + channelMap[2]];
                                        // Yuv
                                        y[yPos] = ((b + (g << 1) + r) >> 2) - YUVoffset8;
                                        u[yPos] = r - g;
                                        v[yPos] = b - g;
                                        yPos++;
                                        cnt += channels;
                                }
                                buff += pitch;
                        }       
                }
                break;
        case ImageModeRGB48:
                {
                        ASSERT(m_header.channels == 3);
                        ASSERT(m_header.bpp == m_header.channels*16);
                        ASSERT(bpp%16 == 0);

                        UINT16 *buff16 = (UINT16 *)buff;
                        const int pitch16 = pitch/2;
                        const int channels = bpp/16; ASSERT(channels >= m_header.channels);
                        const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
                        const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);

                        DataT* y = m_channel[0]; ASSERT(y);
                        DataT* u = m_channel[1]; ASSERT(u);
                        DataT* v = m_channel[2]; ASSERT(v);
                        UINT16 b, g, r;

                        for (UINT32 h=0; h < m_header.height; h++) {
                                if (cb) {
                                        if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                        percent += dP;
                                }

                                cnt = 0;
                                for (UINT32 w=0; w < m_header.width; w++) {
                                        b = buff16[cnt + channelMap[0]] >> shift;
                                        g = buff16[cnt + channelMap[1]] >> shift;
                                        r = buff16[cnt + channelMap[2]] >> shift;
                                        // Yuv
                                        y[yPos] = ((b + (g << 1) + r) >> 2) - yuvOffset16;
                                        u[yPos] = r - g;
                                        v[yPos] = b - g;
                                        yPos++;
                                        cnt += channels;
                                }
                                buff16 += pitch16;
                        }       
                }
                break;
        case ImageModeRGBA:
        case ImageModeCMYKColor:
                {
                        ASSERT(m_header.channels == 4);
                        ASSERT(m_header.bpp == m_header.channels*8);
                        ASSERT(bpp%8 == 0);
                        const int channels = bpp/8; ASSERT(channels >= m_header.channels);

                        DataT* y = m_channel[0]; ASSERT(y);
                        DataT* u = m_channel[1]; ASSERT(u);
                        DataT* v = m_channel[2]; ASSERT(v);
                        DataT* a = m_channel[3]; ASSERT(a);
                        UINT8 b, g, r;

                        for (UINT32 h=0; h < m_header.height; h++) {
                                if (cb) {
                                        if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                        percent += dP;
                                }

                                cnt = 0;
                                for (UINT32 w=0; w < m_header.width; w++) {
                                        b = buff[cnt + channelMap[0]];
                                        g = buff[cnt + channelMap[1]];
                                        r = buff[cnt + channelMap[2]];
                                        // Yuv
                                        y[yPos] = ((b + (g << 1) + r) >> 2) - YUVoffset8;
                                        u[yPos] = r - g;
                                        v[yPos] = b - g;
                                        a[yPos++] = buff[cnt + channelMap[3]] - YUVoffset8;
                                        cnt += channels;
                                }
                                buff += pitch;
                        }       
                }
                break;
        case ImageModeCMYK64:
                {
                        ASSERT(m_header.channels == 4);
                        ASSERT(m_header.bpp == m_header.channels*16);
                        ASSERT(bpp%16 == 0);

                        UINT16 *buff16 = (UINT16 *)buff;
                        const int pitch16 = pitch/2;
                        const int channels = bpp/16; ASSERT(channels >= m_header.channels);
                        const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
                        const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
                        
                        DataT* y = m_channel[0]; ASSERT(y);
                        DataT* u = m_channel[1]; ASSERT(u);
                        DataT* v = m_channel[2]; ASSERT(v);
                        DataT* a = m_channel[3]; ASSERT(a);
                        UINT16 b, g, r;

                        for (UINT32 h=0; h < m_header.height; h++) {
                                if (cb) {
                                        if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                        percent += dP;
                                }

                                cnt = 0;
                                for (UINT32 w=0; w < m_header.width; w++) {
                                        b = buff16[cnt + channelMap[0]] >> shift;
                                        g = buff16[cnt + channelMap[1]] >> shift;
                                        r = buff16[cnt + channelMap[2]] >> shift;
                                        // Yuv
                                        y[yPos] = ((b + (g << 1) + r) >> 2) - yuvOffset16;
                                        u[yPos] = r - g;
                                        v[yPos] = b - g;
                                        a[yPos++] = (buff16[cnt + channelMap[3]] >> shift) - yuvOffset16;
                                        cnt += channels;
                                }
                                buff16 += pitch16;
                        }       
                }
                break;
#ifdef __PGF32SUPPORT__
        case ImageModeGray32:
                {
                        ASSERT(m_header.channels == 1);
                        ASSERT(m_header.bpp == 32);
                        ASSERT(bpp == 32);
                        ASSERT(DataTSize == sizeof(UINT32));

                        DataT* y = m_channel[0]; ASSERT(y);

                        UINT32 *buff32 = (UINT32 *)buff;
                        const int pitch32 = pitch/4;
                        const int shift = 32 - UsedBitsPerChannel(); ASSERT(shift >= 0);
                        const DataT yuvOffset32 = 1 << (UsedBitsPerChannel() - 1);

                        for (UINT32 h=0; h < m_header.height; h++) {
                                if (cb) {
                                        if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                        percent += dP;
                                }

                                for (UINT32 w=0; w < m_header.width; w++) {
                                        y[yPos++] = (buff32[w] >> shift) - yuvOffset32;
                                }
                                buff32 += pitch32;
                        }
                }
                break;
#endif
        case ImageModeRGB12:
                {
                        ASSERT(m_header.channels == 3);
                        ASSERT(m_header.bpp == m_header.channels*4);
                        ASSERT(bpp == m_header.channels*4);

                        DataT* y = m_channel[0]; ASSERT(y);
                        DataT* u = m_channel[1]; ASSERT(u);
                        DataT* v = m_channel[2]; ASSERT(v);

                        UINT8 rgb = 0, b, g, r;

                        for (UINT32 h=0; h < m_header.height; h++) {
                                if (cb) {
                                        if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                        percent += dP;
                                }

                                cnt = 0;
                                for (UINT32 w=0; w < m_header.width; w++) {
                                        if (w%2 == 0) {
                                                // even pixel position
                                                rgb = buff[cnt];
                                                b = rgb & 0x0F;
                                                g = (rgb & 0xF0) >> 4;
                                                cnt++;
                                                rgb = buff[cnt];
                                                r = rgb & 0x0F;
                                        } else {
                                                // odd pixel position
                                                b = (rgb & 0xF0) >> 4;
                                                cnt++;
                                                rgb = buff[cnt];
                                                g = rgb & 0x0F;
                                                r = (rgb & 0xF0) >> 4;
                                                cnt++;
                                        }

                                        // Yuv
                                        y[yPos] = ((b + (g << 1) + r) >> 2) - YUVoffset4;
                                        u[yPos] = r - g;
                                        v[yPos] = b - g;
                                        yPos++;
                                }
                                buff += pitch;
                        }       
                }
                break;
        case ImageModeRGB16:
                {
                        ASSERT(m_header.channels == 3);
                        ASSERT(m_header.bpp == 16);
                        ASSERT(bpp == 16);
                        
                        DataT* y = m_channel[0]; ASSERT(y);
                        DataT* u = m_channel[1]; ASSERT(u);
                        DataT* v = m_channel[2]; ASSERT(v);

                        UINT16 *buff16 = (UINT16 *)buff;
                        UINT16 rgb, b, g, r;
                        const int pitch16 = pitch/2;

                        for (UINT32 h=0; h < m_header.height; h++) {
                                if (cb) {
                                        if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                                        percent += dP;
                                }
                                for (UINT32 w=0; w < m_header.width; w++) {
                                        rgb = buff16[w]; 
                                        r = (rgb & 0xF800) >> 10;       // highest 5 bits
                                        g = (rgb & 0x07E0) >> 5;        // middle 6 bits
                                        b = (rgb & 0x001F) << 1;        // lowest 5 bits
                                        // Yuv
                                        y[yPos] = ((b + (g << 1) + r) >> 2) - YUVoffset6;
                                        u[yPos] = r - g;
                                        v[yPos] = b - g;
                                        yPos++;
                                }

                                buff16 += pitch16;
                        }       
                }
                break;
        default:
                ASSERT(false);
        }
}
bool CPGFImage::ROIisSupported ( ) const [inline]

Return true if the pgf image supports Region Of Interest (ROI).

Returns:
true if the pgf image supports ROI.

Definition at line 457 of file PGFimage.h.

{ return (m_preHeader.version & PGFROI) == PGFROI; }
void CPGFImage::SetChannel ( DataT channel,
int  c = 0 
) [inline]

Set background of an RGB image with transparency channel or reset to default background.

Parameters:
bgA pointer to a background color or NULL (reset to default background) Set background of an RGB image with transparency channel.
redA red value (0..255)
greenA green value (0..255)
blueA blue value (0..255) Set internal PGF image buffer channel.
channelA YUV data channel
cA channel index

Definition at line 267 of file PGFimage.h.

{ ASSERT(c >= 0 && c < MaxChannels); m_channel[c] = channel; }
void CPGFImage::SetColorTable ( UINT32  iFirstColor,
UINT32  nColors,
const RGBQUAD *  prgbColors 
)

Sets the red, green, blue (RGB) color values for a range of entries in the palette (clut). It might throw an IOException.

Parameters:
iFirstColorThe color table index of the first entry to set.
nColorsThe number of color table entries to set.
prgbColorsA pointer to the array of RGBQUAD structures to set the color table entries.

Definition at line 1254 of file PGFimage.cpp.

                                                                                                  {
        if (iFirstColor + nColors > ColorTableLen)      ReturnWithError(ColorTableError);

        for (UINT32 i=iFirstColor, j=0; j < nColors; i++, j++) {
                m_postHeader.clut[i] = prgbColors[j];
        }
}
void CPGFImage::SetHeader ( const PGFHeader header,
BYTE  flags = 0,
UINT8 *  userData = 0,
UINT32  userDataLength = 0 
)

Set PGF header and user data. Precondition: The PGF image has been closed with Close(...) or never opened with Open(...). It might throw an IOException.

Parameters:
headerA valid and already filled in PGF header structure
flagsA combination of additional version flags
userDataA user-defined memory block
userDataLengthThe size of user-defined memory block in bytes

Definition at line 836 of file PGFimage.cpp.

                                                                                                                  {
        ASSERT(!m_decoder);     // current image must be closed
        ASSERT(header.quality <= MaxQuality);

        // init state
#ifdef __PGFROISUPPORT__
        m_levelwise = true;
        m_streamReinitialized = false;
#endif

        // init preHeader
        memcpy(m_preHeader.magic, Magic, 3);
        m_preHeader.version = PGFVersion | flags;
        m_preHeader.hSize = HeaderSize;

        // copy header
        memcpy(&m_header, &header, HeaderSize);

        // complete header
        CompleteHeader();

        // check and set number of levels
        ComputeLevels();

        // check for downsample
        if (m_header.quality > DownsampleThreshold &&  (m_header.mode == ImageModeRGBColor || 
                                                                                                        m_header.mode == ImageModeRGBA || 
                                                                                                        m_header.mode == ImageModeRGB48 || 
                                                                                                        m_header.mode == ImageModeCMYKColor || 
                                                                                                        m_header.mode == ImageModeCMYK64 || 
                                                                                                        m_header.mode == ImageModeLabColor || 
                                                                                                        m_header.mode == ImageModeLab48)) {
                m_downsample = true;
                m_quant = m_header.quality - 1;
        } else {
                m_downsample = false;
                m_quant = m_header.quality;
        }

        // update header size and copy user data
        if (m_header.mode == ImageModeIndexedColor) {
                m_preHeader.hSize += ColorTableSize;
        }
        if (userDataLength && userData) {
                m_postHeader.userData = new(std::nothrow) UINT8[userDataLength];
                if (!m_postHeader.userData) ReturnWithError(InsufficientMemory);
                m_postHeader.userDataLen = userDataLength;
                memcpy(m_postHeader.userData, userData, userDataLength);
                m_preHeader.hSize += userDataLength;
        }

        // allocate channels
        for (int i=0; i < m_header.channels; i++) {
                // set current width and height
                m_width[i] = m_header.width;
                m_height[i] = m_header.height;

                // allocate channels
                ASSERT(!m_channel[i]);
                m_channel[i] = new(std::nothrow) DataT[m_header.width*m_header.height];
                if (!m_channel[i]) {
                        if (i) i--;
                        while(i) {
                                delete[] m_channel[i]; m_channel[i] = 0;
                                i--;
                        }
                        ReturnWithError(InsufficientMemory);
                }
        }
}
void CPGFImage::SetMaxValue ( UINT32  maxValue)

Set maximum intensity value for image modes with more than eight bits per channel. Call this method after SetHeader, but before ImportBitmap.

Parameters:
maxValueThe maximum intensity value.

Definition at line 684 of file PGFimage.cpp.

                                           {
        const BYTE bpc = m_header.bpp/m_header.channels;
        BYTE pot = 0;

        while(maxValue > 0) {
                pot++;
                maxValue >>= 1;
        }
        // store bits per channel
        if (pot > bpc) pot = bpc;
        if (pot > 31) pot = 31;
        m_header.usedBitsPerChannel = pot;
}
void CPGFImage::SetRefreshCallback ( RefreshCB  callback,
void *  arg 
) [inline]

Set refresh callback procedure and its parameter. The refresh callback is called during Read(...) after each level read.

Parameters:
callbackA refresh callback procedure
argA parameter of the refresh callback procedure

Definition at line 296 of file PGFimage.h.

{ m_cb = callback; m_cbArg = arg; }
void CPGFImage::SetROI ( PGFRect  rect) [private]

Returns number of used bits per input/output image channel. Precondition: header must be initialized.

Returns:
number of used bits per input/output image channel.

Definition at line 702 of file PGFimage.cpp.

                                         {
        const BYTE bpc = m_header.bpp/m_header.channels;

        if (bpc > 8) {
                return m_header.usedBitsPerChannel;
        } else {
                return bpc;
        }
}
BYTE CPGFImage::Version ( ) const [inline]

Returns images' PGF version

Returns:
PGF codec version of the image

Definition at line 462 of file PGFimage.h.

UINT32 CPGFImage::Width ( int  level = 0) const [inline]

Return image width of channel 0 at given level in pixels. The returned width is independent of any Read-operations and ROI.

Parameters:
levelA level
Returns:
Image level width in pixels

Definition at line 408 of file PGFimage.h.

{ ASSERT(level >= 0); return LevelWidth(m_header.width, level); }
void CPGFImage::Write ( CPGFStream stream,
UINT32 *  nWrittenBytes = NULL,
CallbackPtr  cb = NULL,
void *  data = NULL 
)

Encode and write a PGF image at current stream position. A PGF image is structered in levels, numbered between 0 and Levels() - 1. Each level can be seen as a single image, containing the same content as all other levels, but in a different size (width, height). The image size at level i is double the size (width, height) of the image at level i+1. The image at level 0 contains the original size. Precondition: the PGF image contains a valid header (see also SetHeader(...)). Please note: the earlier parameter nLevels has now to be set with SetHeader. Either specify the number of levels or use the value 0 for automatic setting. It might throw an IOException.

Parameters:
streamA PGF stream
nWrittenBytes[in-out] The number of bytes written into stream are added to the input value.
cbA pointer to a callback procedure. The procedure is called after writing a single level. If cb returns true, then it stops proceeding.
dataData Pointer to C++ class container to host callback procedure.

Definition at line 1077 of file PGFimage.cpp.

                                                                                                        {
        ASSERT(stream);
        ASSERT(m_preHeader.hSize);

#ifdef __PGFROISUPPORT__
        // don't use level-wise writing
        m_levelwise = false;
#endif

        // create wavelet transform channels and encoder
        WriteHeader(stream);

        int levels = m_header.nLevels;
        double percent = pow(0.25, levels - 1);

        if (levels == 0) {
                // data has been written in WriteHeader
                // now update progress
                if (cb) {
                        if ((*cb)(1, true, data)) ReturnWithError(EscapePressed);
                }
        } else {
                // encode quantized wavelet coefficients and write to PGF file
                // encode subbands, higher levels first
                // color channels are interleaved

                // encode all levels
                for (m_currentLevel = levels; m_currentLevel > 0; ) {
                        WriteLevel(); // decrements m_currentLevel

                        // now update progress
                        if (cb) {
                                percent *= 4;
                                if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
                        }
                }

                // flush encoder and write level lengths
                m_encoder->Flush();
                UINT32 nBytes = m_encoder->WriteLevelLength(); // inclusive header

                // delete encoder
                delete m_encoder; m_encoder = NULL;

                // return written bytes
                if (nWrittenBytes) *nWrittenBytes += nBytes;
        }

        ASSERT(!m_encoder);
}
UINT32 CPGFImage::Write ( int  level,
CallbackPtr  cb = NULL,
void *  data = NULL 
)

Encode and write down to given level at current stream position. A PGF image is structered in levels, numbered between 0 and Levels() - 1. Each level can be seen as a single image, containing the same content as all other levels, but in a different size (width, height). The image size at level i is double the size (width, height) of the image at level i+1. The image at level 0 contains the original size. Precondition: the PGF image contains a valid header (see also SetHeader(...)) and WriteHeader() has been called before Write(). The ROI encoding scheme is used. It might throw an IOException.

Parameters:
level[0, nLevels) The image level of the resulting image in the internal image buffer.
cbA pointer to a callback procedure. The procedure is called after writing a single level. If cb returns true, then it stops proceeding.
dataData Pointer to C++ class container to host callback procedure.
Returns:
The number of bytes written into stream.
UINT32 CPGFImage::WriteHeader ( CPGFStream stream)

Create wavelet transform channels and encoder. Call this method before your first call of Write(int level), but after SetHeader(). Don't use this method when you call Write(). It might throw an IOException.

Parameters:
streamA PGF stream
Returns:
The number of bytes written into stream.

Definition at line 914 of file PGFimage.cpp.

                                                       {
        ASSERT(m_header.nLevels <= MaxLevel);
        ASSERT(m_header.quality <= MaxQuality); // quality is already initialized

        if (m_header.nLevels > 0) {
                volatile OSError error = NoError; // volatile prevents optimizations
                // create new wt channels
                #pragma omp parallel for default(shared)
                for (int i=0; i < m_header.channels; i++) {
                        DataT *temp = NULL;
                        if (error == NoError) {
                                if (m_wtChannel[i]) {
                                        ASSERT(m_channel[i]);
                                        // copy m_channel to temp
                                        int size = m_height[i]*m_width[i];
                                        temp = new(std::nothrow) DataT[size];
                                        if (temp) {
                                                memcpy(temp, m_channel[i], size*DataTSize);
                                                delete m_wtChannel[i];  // also deletes m_channel
                                        } else {
                                                error = InsufficientMemory;
                                        }
                                }
                                if (error == NoError) {
                                        if (temp) m_channel[i] = temp;
                                        m_wtChannel[i] = new CWaveletTransform(m_width[i], m_height[i], m_header.nLevels, m_channel[i]);
                                        
                                        // wavelet subband decomposition 
                                        for (int l=0; error == NoError && l < m_header.nLevels; l++) {
                                                OSError err = m_wtChannel[i]->ForwardTransform(l, m_quant);
                                                if (err != NoError) error = err;
                                        }
                                }
                        }
                }
                if (error != NoError) ReturnWithError(error);

                m_currentLevel = m_header.nLevels;

        #ifdef __PGFROISUPPORT__
                if (m_levelwise) {
                        m_preHeader.version |= PGFROI;
                }
        #endif

                // create encoder and eventually write headers and levelLength
                m_encoder = new CEncoder(stream, m_preHeader, m_header, m_postHeader, m_levelLength, m_useOMPinEncoder);
                if (m_favorSpeedOverSize) m_encoder->FavorSpeedOverSize();

        #ifdef __PGFROISUPPORT__
                if (ROIisSupported()) {
                        // new encoding scheme supporting ROI
                        m_encoder->SetROI();
                }
        #endif

                // return number of written bytes
                return m_encoder->ComputeHeaderLength();

        } else {
                // very small image: we don't use DWT and encoding

                // create encoder and eventually write headers and levelLength
                m_encoder = new CEncoder(stream, m_preHeader, m_header, m_postHeader, m_levelLength, m_useOMPinEncoder);

                // write channels
                for (int c=0; c < m_header.channels; c++) {
                        const UINT32 size = m_width[c]*m_height[c];

                        // write channel data into stream
                        for (UINT32 i=0; i < size; i++) {
                                int count = DataTSize;
                                stream->Write(&count, &m_channel[c][i]);
                        }
                }

                // write level lengths
                UINT32 nBytes = m_encoder->WriteLevelLength(); // return written bytes inclusive header

                // delete encoder
                delete m_encoder; m_encoder = NULL;

                // return number of written bytes
                return nBytes;
        }
}
void CPGFImage::WriteLevel ( ) [private]

Definition at line 1009 of file PGFimage.cpp.

                                  {
        ASSERT(m_encoder);
        ASSERT(m_currentLevel > 0);
        ASSERT(m_header.nLevels > 0);

#ifdef __PGFROISUPPORT__
        if (ROIisSupported()) {
                const int lastChannel = m_header.channels - 1;

                for (int i=0; i < m_header.channels; i++) {
                        m_wtChannel[i]->SetROI();

                        // get number of tiles and tile indices
                        const UINT32 nTiles = m_wtChannel[i]->GetNofTiles(m_currentLevel);
                        const UINT32 lastTile = nTiles - 1;

                        if (m_currentLevel == m_header.nLevels) {
                                // last level also has LL band
                                ASSERT(nTiles == 1);
                                m_wtChannel[i]->GetSubband(m_currentLevel, LL)->ExtractTile(*m_encoder);
                                m_encoder->EncodeTileBuffer();
                        }
                        for (UINT32 tileY=0; tileY < nTiles; tileY++) {
                                for (UINT32 tileX=0; tileX < nTiles; tileX++) {
                                        m_wtChannel[i]->GetSubband(m_currentLevel, HL)->ExtractTile(*m_encoder, true, tileX, tileY);
                                        m_wtChannel[i]->GetSubband(m_currentLevel, LH)->ExtractTile(*m_encoder, true, tileX, tileY);
                                        m_wtChannel[i]->GetSubband(m_currentLevel, HH)->ExtractTile(*m_encoder, true, tileX, tileY);
                                        if (i == lastChannel && tileY == lastTile && tileX == lastTile) {
                                                // all necessary data are buffered. next call of EncodeBuffer will write the last piece of data of the current level.
                                                m_encoder->SetEncodedLevel(--m_currentLevel);
                                        }
                                        m_encoder->EncodeTileBuffer();
                                }
                        }
                }
        } else 
#endif
        {
                for (int i=0; i < m_header.channels; i++) {
                        ASSERT(m_wtChannel[i]);
                        if (m_currentLevel == m_header.nLevels) { 
                                // last level also has LL band
                                m_wtChannel[i]->GetSubband(m_currentLevel, LL)->ExtractTile(*m_encoder);
                        }
                        //encoder.EncodeInterleaved(m_wtChannel[i], m_currentLevel, m_quant); // until version 4
                        m_wtChannel[i]->GetSubband(m_currentLevel, HL)->ExtractTile(*m_encoder); // since version 5
                        m_wtChannel[i]->GetSubband(m_currentLevel, LH)->ExtractTile(*m_encoder); // since version 5
                        m_wtChannel[i]->GetSubband(m_currentLevel, HH)->ExtractTile(*m_encoder);
                }

                // all necessary data are buffered. next call of EncodeBuffer will write the last piece of data of the current level.
                m_encoder->SetEncodedLevel(--m_currentLevel);
        }
}

Member Data Documentation

pointer to refresh callback procedure

Definition at line 520 of file PGFimage.h.

void* CPGFImage::m_cbArg [private]

refresh callback argument

Definition at line 521 of file PGFimage.h.

untransformed channels in YUV format

Definition at line 498 of file PGFimage.h.

int CPGFImage::m_currentLevel [protected]

transform level of current image

Definition at line 507 of file PGFimage.h.

PGF decoder.

Definition at line 499 of file PGFimage.h.

bool CPGFImage::m_downsample [protected]

chrominance channels are downsampled

Definition at line 509 of file PGFimage.h.

PGF encoder.

Definition at line 500 of file PGFimage.h.

favor encoding speed over compression ratio

Definition at line 510 of file PGFimage.h.

PGF file header.

Definition at line 505 of file PGFimage.h.

UINT32 CPGFImage::m_height[MaxChannels] [protected]

height of each channel at current level

Definition at line 503 of file PGFimage.h.

UINT32* CPGFImage::m_levelLength [protected]

length of each level in bytes; first level starts immediately after this array

Definition at line 501 of file PGFimage.h.

bool CPGFImage::m_levelwise [protected]

write level-wise (only used with WriteNextLevel)

Definition at line 514 of file PGFimage.h.

PGF post header.

Definition at line 506 of file PGFimage.h.

PGF pre header.

Definition at line 504 of file PGFimage.h.

BYTE CPGFImage::m_quant [protected]

quantization parameter

Definition at line 508 of file PGFimage.h.

region of interest

Definition at line 516 of file PGFimage.h.

stream has been reinitialized

Definition at line 515 of file PGFimage.h.

bool CPGFImage::m_useOMPinDecoder [protected]

use Open MP in decoder

Definition at line 512 of file PGFimage.h.

bool CPGFImage::m_useOMPinEncoder [protected]

use Open MP in encoder

Definition at line 511 of file PGFimage.h.

UINT32 CPGFImage::m_width[MaxChannels] [protected]

width of each channel at current level

Definition at line 502 of file PGFimage.h.

wavelet transformed color channels

Definition at line 497 of file PGFimage.h.


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