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 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 WriteImage (CPGFStream *stream, CallbackPtr cb=NULL, void *data=NULL) THROW_
void ConfigureEncoder (bool useOMP=true, bool favorSpeedOverSize=false)
void ConfigureDecoder (bool useOMP=true, bool skipUserData=false)
void ResetStreamPos () THROW_
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)
void SetProgressMode (ProgressMode pm)
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
UINT64 GetUserDataPos () const
const UINT8 * GetUserData (UINT32 &size) const
UINT32 GetEncodedHeaderLength () const
UINT32 GetEncodedLevelLength (int level) const
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 UsedBitsPerChannel () 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.
UINT64 m_userDataPos
 stream position of user data
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_skipUserData
 skip user data (metadata) during open

Private Member Functions

void ComputeLevels ()
bool CompleteHeader ()
void RgbToYuv (int pitch, UINT8 *rgbBuff, BYTE bpp, int channelMap[], CallbackPtr cb, void *data) THROW_
void Downsample (int nChannel)
UINT32 UpdatePostHeaderSize () THROW_
void WriteLevel () THROW_
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
double m_percent
 progress [0..1]
ProgressMode m_progressMode
 progress mode used in Read and Write; PM_Relative is default mode

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 57 of file PGFimage.h.


Constructor & Destructor Documentation

CPGFImage::CPGFImage (  ) 

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

Definition at line 55 of file PGFimage.cpp.

00056 : m_decoder(0)
00057 , m_encoder(0)
00058 , m_levelLength(0)
00059 , m_currentLevel(0)
00060 , m_quant(0)
00061 , m_userDataPos(0)
00062 , m_downsample(false)
00063 , m_favorSpeedOverSize(false)
00064 , m_useOMPinEncoder(true)
00065 , m_useOMPinDecoder(true)
00066 , m_skipUserData(false)
00067 #ifdef __PGFROISUPPORT__
00068 , m_streamReinitialized(false)
00069 #endif
00070 , m_cb(0)
00071 , m_cbArg(0)
00072 , m_progressMode(PM_Relative)
00073 , m_percent(0)
00074 {
00075 
00076         // init preHeader
00077         memcpy(m_preHeader.magic, PGFMagic, 3);
00078         m_preHeader.version = PGFVersion;
00079         m_preHeader.hSize = 0;
00080 
00081         // init postHeader
00082         m_postHeader.userData = 0;
00083         m_postHeader.userDataLen = 0;
00084 
00085         // init channels
00086         for (int i=0; i < MaxChannels; i++) {
00087                 m_channel[i] = 0;
00088                 m_wtChannel[i] = 0;
00089         }
00090 
00091         // set image width and height
00092         m_width[0] = 0;
00093         m_height[0] = 0;
00094 }

CPGFImage::~CPGFImage (  )  [virtual]

Destructor: Destroy internal data structures.

Definition at line 98 of file PGFimage.cpp.

00098                       {
00099         Destroy();
00100 }


Member Function Documentation

BYTE CPGFImage::BPP (  )  const [inline]

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

Returns:
Number of bits per pixel.

Definition at line 460 of file PGFimage.h.

00460 { 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 409 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:
c A channel index
Returns:
Channel height in pixels

Definition at line 404 of file PGFimage.h.

00404 { 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 447 of file PGFimage.h.

00447 { 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:
c A channel index
Returns:
Channel width in pixels

Definition at line 397 of file PGFimage.h.

00397 { ASSERT(c >= 0 && c < MaxChannels); return m_width[c]; }

UINT16 CPGFImage::Clamp16 ( DataT  v  )  const [inline, private]

Definition at line 561 of file PGFimage.h.

00561                                       {
00562                 if (v & 0xFFFF0000) return (v < 0) ? (UINT16)0: (UINT16)65535; else return (UINT16)v;
00563         }       

UINT32 CPGFImage::Clamp31 ( DataT  v  )  const [inline, private]

Definition at line 564 of file PGFimage.h.

00564                                       {
00565                 return (v < 0) ? 0 : (UINT32)v;
00566         }       

UINT8 CPGFImage::Clamp4 ( DataT  v  )  const [inline, private]

Definition at line 551 of file PGFimage.h.

00551                                     {
00552                 if (v & 0xFFFFFFF0) return (v < 0) ? (UINT8)0: (UINT8)15; else return (UINT8)v;
00553         }       

UINT16 CPGFImage::Clamp6 ( DataT  v  )  const [inline, private]

Definition at line 554 of file PGFimage.h.

00554                                      {
00555                 if (v & 0xFFFFFFC0) return (v < 0) ? (UINT16)0: (UINT16)63; else return (UINT16)v;
00556         }       

UINT8 CPGFImage::Clamp8 ( DataT  v  )  const [inline, private]

Definition at line 557 of file PGFimage.h.

00557                                     {
00558                 // needs only one test in the normal case
00559                 if (v & 0xFFFFFF00) return (v < 0) ? (UINT8)0 : (UINT8)255; else return (UINT8)v;
00560         }

void CPGFImage::Close (  )  [virtual]

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

Definition at line 122 of file PGFimage.cpp.

00122                       {
00123         delete m_decoder; m_decoder = 0;
00124 }

bool CPGFImage::CompleteHeader (  )  [private]

Definition at line 208 of file PGFimage.cpp.

00208                                {
00209         if (m_header.mode == ImageModeUnknown) {
00210                 // undefined mode
00211                 switch(m_header.bpp) {
00212                 case 1: m_header.mode = ImageModeBitmap; break;
00213                 case 8: m_header.mode = ImageModeGrayScale; break;
00214                 case 12: m_header.mode = ImageModeRGB12; break;
00215                 case 16: m_header.mode = ImageModeRGB16; break;
00216                 case 24: m_header.mode = ImageModeRGBColor; break;
00217                 case 32: m_header.mode = ImageModeRGBA; break;
00218                 case 48: m_header.mode = ImageModeRGB48; break;
00219                 default: m_header.mode = ImageModeRGBColor; break;
00220                 }
00221         }
00222         if (!m_header.bpp) {
00223                 // undefined bpp
00224                 switch(m_header.mode) {
00225                 case ImageModeBitmap: 
00226                         m_header.bpp = 1;
00227                         break;
00228                 case ImageModeIndexedColor:
00229                 case ImageModeGrayScale:
00230                         m_header.bpp = 8;
00231                         break;
00232                 case ImageModeRGB12:
00233                         m_header.bpp = 12;
00234                         break;
00235                 case ImageModeRGB16:
00236                 case ImageModeGray16:
00237                         m_header.bpp = 16;
00238                         break;
00239                 case ImageModeRGBColor:
00240                 case ImageModeLabColor:
00241                         m_header.bpp = 24;
00242                         break;
00243                 case ImageModeRGBA:
00244                 case ImageModeCMYKColor:
00245                 case ImageModeGray32:
00246                         m_header.bpp = 32;
00247                         break;
00248                 case ImageModeRGB48:
00249                 case ImageModeLab48:
00250                         m_header.bpp = 48;
00251                         break;
00252                 case ImageModeCMYK64:
00253                         m_header.bpp = 64;
00254                         break;
00255                 default:
00256                         ASSERT(false);
00257                         m_header.bpp = 24;
00258                 }
00259         } 
00260         if (m_header.mode == ImageModeRGBColor && m_header.bpp == 32) {
00261                 // change mode
00262                 m_header.mode = ImageModeRGBA;
00263         }
00264         if (m_header.mode == ImageModeBitmap && m_header.bpp != 1) return false;
00265         if (m_header.mode == ImageModeIndexedColor && m_header.bpp != 8) return false;
00266         if (m_header.mode == ImageModeGrayScale && m_header.bpp != 8) return false;
00267         if (m_header.mode == ImageModeGray16 && m_header.bpp != 16) return false;
00268         if (m_header.mode == ImageModeGray32 && m_header.bpp != 32) return false;
00269         if (m_header.mode == ImageModeRGBColor && m_header.bpp != 24) return false;
00270         if (m_header.mode == ImageModeRGBA && m_header.bpp != 32) return false;
00271         if (m_header.mode == ImageModeRGB12 && m_header.bpp != 12) return false;
00272         if (m_header.mode == ImageModeRGB16 && m_header.bpp != 16) return false;
00273         if (m_header.mode == ImageModeRGB48 && m_header.bpp != 48) return false;
00274         if (m_header.mode == ImageModeLabColor && m_header.bpp != 24) return false;
00275         if (m_header.mode == ImageModeLab48 && m_header.bpp != 48) return false;
00276         if (m_header.mode == ImageModeCMYKColor && m_header.bpp != 32) return false;
00277         if (m_header.mode == ImageModeCMYK64 && m_header.bpp != 64) return false;
00278 
00279         // set number of channels
00280         if (!m_header.channels) {
00281                 switch(m_header.mode) {
00282                 case ImageModeBitmap: 
00283                 case ImageModeIndexedColor:
00284                 case ImageModeGrayScale:
00285                 case ImageModeGray16:
00286                 case ImageModeGray32:
00287                         m_header.channels = 1; 
00288                         break;
00289                 case ImageModeRGBColor:
00290                 case ImageModeRGB12:
00291                 case ImageModeRGB16:
00292                 case ImageModeRGB48:
00293                 case ImageModeLabColor:
00294                 case ImageModeLab48:
00295                         m_header.channels = 3;
00296                         break;
00297                 case ImageModeRGBA:
00298                 case ImageModeCMYKColor:
00299                 case ImageModeCMYK64:
00300                         m_header.channels = 4;
00301                         break;
00302                 default:
00303                         return false;
00304                 }
00305         }
00306 
00307         // store used bits per channel
00308         UINT8 bpc = m_header.bpp/m_header.channels;
00309         if (bpc > 31) bpc = 31;
00310         if (!m_header.usedBitsPerChannel || m_header.usedBitsPerChannel > bpc) {
00311                 m_header.usedBitsPerChannel = bpc;
00312         }
00313 
00314         return true;
00315 }

void CPGFImage::ComputeLevels (  )  [private]

Definition at line 804 of file PGFimage.cpp.

00804                               {
00805         const int maxThumbnailWidth = 20*FilterWidth;
00806         const int m = __min(m_header.width, m_header.height);
00807         int s = m;
00808 
00809         if (m_header.nLevels < 1 || m_header.nLevels > MaxLevel) {
00810                 m_header.nLevels = 1;
00811                 // compute a good value depending on the size of the image
00812                 while (s > maxThumbnailWidth) {
00813                         m_header.nLevels++;
00814                         s = s/2;
00815                 }
00816         }
00817 
00818         int levels = m_header.nLevels; // we need a signed value during level reduction
00819 
00820         // reduce number of levels if the image size is smaller than FilterWidth*2^levels
00821         s = FilterWidth*(1 << levels);  // must be at least the double filter size because of subsampling
00822         while (m < s) {
00823                 levels--;
00824                 s = s/2;
00825         }
00826         if (levels > MaxLevel) m_header.nLevels = MaxLevel;
00827         else if (levels < 0) m_header.nLevels = 0;
00828         else m_header.nLevels = (UINT8)levels;
00829 
00830         // used in Write when PM_Absolute
00831         m_percent = pow(0.25, m_header.nLevels);
00832 
00833         ASSERT(0 <= m_header.nLevels && m_header.nLevels <= MaxLevel);
00834 }

void CPGFImage::ConfigureDecoder ( bool  useOMP = true,
bool  skipUserData = false 
) [inline]

Configures the decoder.

Parameters:
useOMP Use parallel threading with Open MP during decoding. Default value: true. Influences the decoding only if the codec has been compiled with OpenMP support.
skipUserData The file might contain user data (metadata). User data ist usually read during Open and stored in memory. Set this flag to false when storing in memory is not needed.

Definition at line 266 of file PGFimage.h.

00266 { m_useOMPinDecoder = useOMP; m_skipUserData = skipUserData; }

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

Configures the encoder.

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

Definition at line 260 of file PGFimage.h.

00260 { 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 508 of file PGFimage.h.

00508 { 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 720 of file PGFimage.cpp.

00720                                            {
00721         if (version & Version6) return 6;
00722         if (version & Version5) return 5;
00723         if (version & Version2) return 2;
00724         return 1;
00725 }

void CPGFImage::Destroy (  )  [virtual]

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

Definition at line 105 of file PGFimage.cpp.

00105                         {
00106         Close();
00107 
00108         for (int i=0; i < m_header.channels; i++) {
00109                 delete m_wtChannel[i]; m_wtChannel[i]=0; // also deletes m_channel
00110                 m_channel[i] = 0;
00111         }
00112         delete[] m_postHeader.userData; m_postHeader.userData = 0; m_postHeader.userDataLen = 0;
00113         delete[] m_levelLength; m_levelLength = 0;
00114         delete m_encoder; m_encoder = NULL;
00115         
00116         m_userDataPos = 0;
00117 }

void CPGFImage::Downsample ( int  nChannel  )  [private]

Definition at line 760 of file PGFimage.cpp.

00760                                  {
00761         ASSERT(ch > 0);
00762 
00763         const int w = m_width[0];
00764         const int w2 = w/2;
00765         const int h2 = m_height[0]/2;
00766         const int oddW = w%2;                           // don't use bool -> problems with MaxSpeed optimization
00767         const int oddH = m_height[0]%2;         // "
00768         int loPos = 0;
00769         int hiPos = w;
00770         int sampledPos = 0;
00771         DataT* buff = m_channel[ch]; ASSERT(buff);
00772 
00773         for (int i=0; i < h2; i++) {
00774                 for (int j=0; j < w2; j++) {
00775                         // compute average of pixel block
00776                         buff[sampledPos] = (buff[loPos] + buff[loPos + 1] + buff[hiPos] + buff[hiPos + 1]) >> 2;
00777                         loPos += 2; hiPos += 2;
00778                         sampledPos++;
00779                 }
00780                 if (oddW) { 
00781                         buff[sampledPos] = (buff[loPos] + buff[hiPos]) >> 1;
00782                         loPos++; hiPos++;
00783                         sampledPos++;
00784                 }
00785                 loPos += w; hiPos += w;
00786         }
00787         if (oddH) {
00788                 for (int j=0; j < w2; j++) {
00789                         buff[sampledPos] = (buff[loPos] + buff[loPos+1]) >> 1;
00790                         loPos += 2; hiPos += 2;
00791                         sampledPos++;
00792                 }
00793                 if (oddW) {
00794                         buff[sampledPos] = buff[loPos];
00795                 }
00796         }
00797 
00798         // downsampled image has half width and half height
00799         m_width[ch] = (m_width[ch] + 1)/2;
00800         m_height[ch] = (m_height[ch] + 1)/2;
00801 }

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:
pitch The number of bytes of a row of the image buffer.
buff An image buffer.
bpp The number of bits per pixel used in image buffer.
channelMap A integer array containing the mapping of PGF channel ordering to expected channel ordering.
cb A pointer to a callback procedure. The procedure is called after each copied buffer row. If cb returns true, then it stops proceeding.
data Data Pointer to C++ class container to host callback procedure.

Definition at line 1720 of file PGFimage.cpp.

01720                                                                                                                                                       {
01721         ASSERT(buff);
01722         UINT32 w = m_width[0];
01723         UINT32 h = m_height[0];
01724         UINT8* targetBuff = 0;  // used if ROI is used
01725         UINT8* buffStart = 0;   // used if ROI is used
01726         int targetPitch = 0;    // used if ROI is used
01727 
01728 #ifdef __PGFROISUPPORT__
01729         const PGFRect& roi = (ROIisSupported()) ? m_wtChannel[0]->GetROI(m_currentLevel) : PGFRect(0, 0, w, h); // roi is usually larger than m_roi
01730         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));
01731         ASSERT(w <= roi.Width() && h <= roi.Height()); 
01732         ASSERT(roi.left <= levelRoi.left && levelRoi.right <= roi.right); 
01733         ASSERT(roi.top <= levelRoi.top && levelRoi.bottom <= roi.bottom); 
01734 
01735         if (ROIisSupported() && (levelRoi.Width() < w || levelRoi.Height() < h)) {
01736                 // ROI is used -> create a temporary image buffer for roi
01737                 // compute pitch
01738                 targetPitch = pitch;
01739                 pitch = AlignWordPos(w*bpp)/8;
01740 
01741                 // create temporary output buffer
01742                 targetBuff = buff;
01743                 buff = buffStart = new(std::nothrow) UINT8[pitch*h];
01744                 if (!buff) ReturnWithError(InsufficientMemory);
01745         }
01746 #endif
01747 
01748         const bool wOdd = (1 == w%2);
01749 
01750         const double dP = 1.0/h;
01751         int defMap[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; ASSERT(sizeof(defMap)/sizeof(defMap[0]) == MaxChannels);
01752         if (channelMap == NULL) channelMap = defMap;
01753         int sampledPos = 0, yPos = 0;
01754         DataT uAvg, vAvg;
01755         double percent = 0;
01756         UINT32 i, j;
01757 
01758         switch(m_header.mode) {
01759         case ImageModeBitmap:
01760                 {
01761                         ASSERT(m_header.channels == 1);
01762                         ASSERT(m_header.bpp == 1);
01763                         ASSERT(bpp == 1);
01764 
01765                         const UINT32 w2 = (w + 7)/8;
01766                         DataT* y = m_channel[0]; ASSERT(y);
01767 
01768                         for (i=0; i < h; i++) {
01769                                 
01770                                 for (j=0; j < w2; j++) {
01771                                         buff[j] = Clamp8(y[yPos++] + YUVoffset8);
01772                                 }
01773                                 yPos += w - w2;
01774                                 
01775                                 //UINT32 cnt = w;
01776                                 //for (j=0; j < w2; j++) {
01777                                 //      buff[j] = 0;
01778                                 //      for (int k=0; k < 8; k++) {
01779                                 //              if (cnt) {
01780                                 //                      buff[j] <<= 1;
01781                                 //                      buff[j] |= (1 & (y[yPos++] - YUVoffset8)); 
01782                                 //                      cnt--;
01783                                 //              }
01784                                 //      }
01785                                 //}
01786                                 buff += pitch;
01787 
01788                                 if (cb) {
01789                                         percent += dP;
01790                                         if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01791                                 }
01792                         }
01793                         break;
01794                 }
01795         case ImageModeIndexedColor:
01796         case ImageModeGrayScale:
01797         case ImageModeHSLColor:
01798         case ImageModeHSBColor:
01799                 {
01800                         ASSERT(m_header.channels >= 1);
01801                         ASSERT(m_header.bpp == m_header.channels*8);
01802                         ASSERT(bpp%8 == 0);
01803 
01804                         int cnt, channels = bpp/8; ASSERT(channels >= m_header.channels);
01805 
01806                         for (i=0; i < h; i++) {
01807                                 cnt = 0;
01808                                 for (j=0; j < w; j++) {
01809                                         for (int c=0; c < m_header.channels; c++) {
01810                                                 buff[cnt + channelMap[c]] = Clamp8(m_channel[c][yPos] + YUVoffset8);
01811                                         }
01812                                         cnt += channels;
01813                                         yPos++;
01814                                 }
01815                                 buff += pitch;
01816 
01817                                 if (cb) {
01818                                         percent += dP;
01819                                         if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01820                                 }
01821                         }
01822                         break;
01823                 }
01824         case ImageModeGray16:
01825                 {
01826                         ASSERT(m_header.channels >= 1);
01827                         ASSERT(m_header.bpp == m_header.channels*16);
01828 
01829                         const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
01830                         int cnt, channels;
01831 
01832                         if (bpp%16 == 0) {
01833                                 const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
01834                                 UINT16 *buff16 = (UINT16 *)buff;
01835                                 int pitch16 = pitch/2;
01836                                 channels = bpp/16; ASSERT(channels >= m_header.channels);
01837 
01838                                 for (i=0; i < h; i++) {
01839                                         cnt = 0;
01840                                         for (j=0; j < w; j++) {
01841                                                 for (int c=0; c < m_header.channels; c++) {
01842                                                         buff16[cnt + channelMap[c]] = Clamp16((m_channel[c][yPos] + yuvOffset16) << shift);
01843                                                 }
01844                                                 cnt += channels;
01845                                                 yPos++;
01846                                         }
01847                                         buff16 += pitch16;
01848 
01849                                         if (cb) {
01850                                                 percent += dP;
01851                                                 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01852                                         }
01853                                 }
01854                         } else {
01855                                 ASSERT(bpp%8 == 0);
01856                                 const int shift = __max(0, UsedBitsPerChannel() - 8);
01857                                 channels = bpp/8; ASSERT(channels >= m_header.channels);
01858                                 
01859                                 for (i=0; i < h; i++) {
01860                                         cnt = 0;
01861                                         for (j=0; j < w; j++) {
01862                                                 for (int c=0; c < m_header.channels; c++) {
01863                                                         buff[cnt + channelMap[c]] = Clamp8((m_channel[c][yPos] + yuvOffset16) >> shift);
01864                                                 }
01865                                                 cnt += channels;
01866                                                 yPos++;
01867                                         }
01868                                         buff += pitch;
01869 
01870                                         if (cb) {
01871                                                 percent += dP;
01872                                                 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01873                                         }
01874                                 }
01875                         }
01876                         break;
01877                 }
01878         case ImageModeRGBColor:
01879                 {
01880                         ASSERT(m_header.channels == 3);
01881                         ASSERT(m_header.bpp == m_header.channels*8);
01882                         ASSERT(bpp%8 == 0);
01883                         ASSERT(bpp >= m_header.bpp);
01884 
01885                         DataT* y = m_channel[0]; ASSERT(y);
01886                         DataT* u = m_channel[1]; ASSERT(u);
01887                         DataT* v = m_channel[2]; ASSERT(v);
01888                         UINT8 *buffg = &buff[channelMap[1]],
01889                                   *buffr = &buff[channelMap[2]],
01890                                   *buffb = &buff[channelMap[0]];
01891                         UINT8 g;
01892                         int cnt, channels = bpp/8;
01893                         if(m_downsample){
01894                                 for (i=0; i < h; i++) {
01895                                         if (i%2) sampledPos -= (w + 1)/2;
01896                                         cnt = 0;
01897                                         for (j=0; j < w; j++) {
01898                                                 // image was downsampled
01899                                                 uAvg = u[sampledPos];
01900                                                 vAvg = v[sampledPos];
01901                                                 // Yuv
01902                                                 buffg[cnt] = g = Clamp8(y[yPos] + YUVoffset8 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
01903                                                 buffr[cnt] = Clamp8(uAvg + g);
01904                                                 buffb[cnt] = Clamp8(vAvg + g);
01905                                                 yPos++;
01906                                                 cnt += channels;
01907                                                 if (j%2) sampledPos++;
01908                                         }
01909                                         buffb += pitch;
01910                                         buffg += pitch;
01911                                         buffr += pitch;
01912                                         if (wOdd) sampledPos++;
01913                                         if (cb) {
01914                                                 percent += dP;
01915                                                 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01916                                         }
01917                                 }
01918                         }else{
01919                                 for (i=0; i < h; i++) {
01920                                         cnt = 0;
01921                                         for (j = 0; j < w; j++) {
01922                                                 uAvg = u[yPos];
01923                                                 vAvg = v[yPos];
01924                                                 // Yuv
01925                                                 buffg[cnt] = g = Clamp8(y[yPos] + YUVoffset8 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
01926                                                 buffr[cnt] = Clamp8(uAvg + g);
01927                                                 buffb[cnt] = Clamp8(vAvg + g);
01928                                                 yPos++;
01929                                                 cnt += channels;
01930                                         }
01931                                         buffb += pitch;
01932                                         buffg += pitch;
01933                                         buffr += pitch;
01934 
01935                                         if (cb) {
01936                                                 percent += dP;
01937                                                 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01938                                         }
01939                                 }
01940                         }
01941                         break;
01942                 }
01943         case ImageModeRGB48:
01944                 {
01945                         ASSERT(m_header.channels == 3);
01946                         ASSERT(m_header.bpp == 48);
01947 
01948                         const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
01949 
01950                         DataT* y = m_channel[0]; ASSERT(y);
01951                         DataT* u = m_channel[1]; ASSERT(u);
01952                         DataT* v = m_channel[2]; ASSERT(v);
01953                         int cnt, channels;
01954                         DataT g;
01955 
01956                         if (bpp >= 48 && bpp%16 == 0) {
01957                                 const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
01958                                 UINT16 *buff16 = (UINT16 *)buff;
01959                                 int pitch16 = pitch/2;
01960                                 channels = bpp/16; ASSERT(channels >= m_header.channels);
01961 
01962                                 for (i=0; i < h; i++) {
01963                                         if (i%2) sampledPos -= (w + 1)/2;
01964                                         cnt = 0;
01965                                         for (j=0; j < w; j++) {
01966                                                 if (m_downsample) {
01967                                                         // image was downsampled
01968                                                         uAvg = u[sampledPos];
01969                                                         vAvg = v[sampledPos];
01970                                                 } else {
01971                                                         uAvg = u[yPos];
01972                                                         vAvg = v[yPos];
01973                                                 }
01974                                                 // Yuv
01975                                                 g = y[yPos] + yuvOffset16 - ((uAvg + vAvg ) >> 2); // must be logical shift operator
01976                                                 buff16[cnt + channelMap[1]] = Clamp16(g << shift);
01977                                                 buff16[cnt + channelMap[2]] = Clamp16((uAvg + g) << shift);
01978                                                 buff16[cnt + channelMap[0]] = Clamp16((vAvg + g) << shift);
01979                                                 yPos++; 
01980                                                 cnt += channels;
01981                                                 if (j%2) sampledPos++;
01982                                         }
01983                                         buff16 += pitch16;
01984                                         if (wOdd) sampledPos++;
01985 
01986                                         if (cb) {
01987                                                 percent += dP;
01988                                                 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01989                                         }
01990                                 }
01991                         } else {
01992                                 ASSERT(bpp%8 == 0);
01993                                 const int shift = __max(0, UsedBitsPerChannel() - 8);
01994                                 channels = bpp/8; ASSERT(channels >= m_header.channels);
01995 
01996                                 for (i=0; i < h; i++) {
01997                                         if (i%2) sampledPos -= (w + 1)/2;
01998                                         cnt = 0;
01999                                         for (j=0; j < w; j++) {
02000                                                 if (m_downsample) {
02001                                                         // image was downsampled
02002                                                         uAvg = u[sampledPos];
02003                                                         vAvg = v[sampledPos];
02004                                                 } else {
02005                                                         uAvg = u[yPos];
02006                                                         vAvg = v[yPos];
02007                                                 }
02008                                                 // Yuv
02009                                                 g = y[yPos] + yuvOffset16 - ((uAvg + vAvg ) >> 2); // must be logical shift operator
02010                                                 buff[cnt + channelMap[1]] = Clamp8(g >> shift); 
02011                                                 buff[cnt + channelMap[2]] = Clamp8((uAvg + g) >> shift);
02012                                                 buff[cnt + channelMap[0]] = Clamp8((vAvg + g) >> shift);
02013                                                 yPos++; 
02014                                                 cnt += channels;
02015                                                 if (j%2) sampledPos++;
02016                                         }
02017                                         buff += pitch;
02018                                         if (wOdd) sampledPos++;
02019 
02020                                         if (cb) {
02021                                                 percent += dP;
02022                                                 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02023                                         }
02024                                 }
02025                         }
02026                         break;
02027                 }
02028         case ImageModeLabColor:
02029                 {
02030                         ASSERT(m_header.channels == 3);
02031                         ASSERT(m_header.bpp == m_header.channels*8);
02032                         ASSERT(bpp%8 == 0);
02033 
02034                         DataT* l = m_channel[0]; ASSERT(l);
02035                         DataT* a = m_channel[1]; ASSERT(a);
02036                         DataT* b = m_channel[2]; ASSERT(b);
02037                         int cnt, channels = bpp/8; ASSERT(channels >= m_header.channels);
02038 
02039                         for (i=0; i < h; i++) {
02040                                 if (i%2) sampledPos -= (w + 1)/2;
02041                                 cnt = 0;
02042                                 for (j=0; j < w; j++) {
02043                                         if (m_downsample) {
02044                                                 // image was downsampled
02045                                                 uAvg = a[sampledPos];
02046                                                 vAvg = b[sampledPos];
02047                                         } else {
02048                                                 uAvg = a[yPos];
02049                                                 vAvg = b[yPos];
02050                                         }
02051                                         buff[cnt + channelMap[0]] = Clamp8(l[yPos] + YUVoffset8);
02052                                         buff[cnt + channelMap[1]] = Clamp8(uAvg + YUVoffset8); 
02053                                         buff[cnt + channelMap[2]] = Clamp8(vAvg + YUVoffset8);
02054                                         cnt += channels;
02055                                         yPos++;
02056                                         if (j%2) sampledPos++;
02057                                 }
02058                                 buff += pitch;
02059                                 if (wOdd) sampledPos++;
02060 
02061                                 if (cb) {
02062                                         percent += dP;
02063                                         if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02064                                 }
02065                         }
02066                         break;
02067                 }
02068         case ImageModeLab48:
02069                 {
02070                         ASSERT(m_header.channels == 3);
02071                         ASSERT(m_header.bpp == m_header.channels*16);
02072 
02073                         const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
02074 
02075                         DataT* l = m_channel[0]; ASSERT(l);
02076                         DataT* a = m_channel[1]; ASSERT(a);
02077                         DataT* b = m_channel[2]; ASSERT(b);
02078                         int cnt, channels;
02079 
02080                         if (bpp%16 == 0) {
02081                                 const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
02082                                 UINT16 *buff16 = (UINT16 *)buff;
02083                                 int pitch16 = pitch/2;
02084                                 channels = bpp/16; ASSERT(channels >= m_header.channels);
02085 
02086                                 for (i=0; i < h; i++) {
02087                                         if (i%2) sampledPos -= (w + 1)/2;
02088                                         cnt = 0;
02089                                         for (j=0; j < w; j++) {
02090                                                 if (m_downsample) {
02091                                                         // image was downsampled
02092                                                         uAvg = a[sampledPos];
02093                                                         vAvg = b[sampledPos];
02094                                                 } else {
02095                                                         uAvg = a[yPos];
02096                                                         vAvg = b[yPos];
02097                                                 }
02098                                                 buff16[cnt + channelMap[0]] = Clamp16((l[yPos] + yuvOffset16) << shift);
02099                                                 buff16[cnt + channelMap[1]] = Clamp16((uAvg + yuvOffset16) << shift);
02100                                                 buff16[cnt + channelMap[2]] = Clamp16((vAvg + yuvOffset16) << shift);
02101                                                 cnt += channels;
02102                                                 yPos++;
02103                                                 if (j%2) sampledPos++;
02104                                         }
02105                                         buff16 += pitch16;
02106                                         if (wOdd) sampledPos++;
02107 
02108                                         if (cb) {
02109                                                 percent += dP;
02110                                                 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02111                                         }
02112                                 }
02113                         } else {
02114                                 ASSERT(bpp%8 == 0);
02115                                 const int shift = __max(0, UsedBitsPerChannel() - 8);
02116                                 channels = bpp/8; ASSERT(channels >= m_header.channels);
02117 
02118                                 for (i=0; i < h; i++) {
02119                                         if (i%2) sampledPos -= (w + 1)/2;
02120                                         cnt = 0;
02121                                         for (j=0; j < w; j++) {
02122                                                 if (m_downsample) {
02123                                                         // image was downsampled
02124                                                         uAvg = a[sampledPos];
02125                                                         vAvg = b[sampledPos];
02126                                                 } else {
02127                                                         uAvg = a[yPos];
02128                                                         vAvg = b[yPos];
02129                                                 }
02130                                                 buff[cnt + channelMap[0]] = Clamp8((l[yPos] + yuvOffset16) >> shift);
02131                                                 buff[cnt + channelMap[1]] = Clamp8((uAvg + yuvOffset16) >> shift);
02132                                                 buff[cnt + channelMap[2]] = Clamp8((vAvg + yuvOffset16) >> shift);
02133                                                 cnt += channels;
02134                                                 yPos++;
02135                                                 if (j%2) sampledPos++;
02136                                         }
02137                                         buff += pitch;
02138                                         if (wOdd) sampledPos++;
02139 
02140                                         if (cb) {
02141                                                 percent += dP;
02142                                                 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02143                                         }
02144                                 }
02145                         }
02146                         break;
02147                 }
02148         case ImageModeRGBA:
02149         case ImageModeCMYKColor:
02150                 {
02151                         ASSERT(m_header.channels == 4);
02152                         ASSERT(m_header.bpp == m_header.channels*8);
02153                         ASSERT(bpp%8 == 0);
02154 
02155                         DataT* y = m_channel[0]; ASSERT(y);
02156                         DataT* u = m_channel[1]; ASSERT(u);
02157                         DataT* v = m_channel[2]; ASSERT(v);
02158                         DataT* a = m_channel[3]; ASSERT(a);
02159                         UINT8 g, aAvg;
02160                         int cnt, channels = bpp/8; ASSERT(channels >= m_header.channels);
02161 
02162                         for (i=0; i < h; i++) {
02163                                 if (i%2) sampledPos -= (w + 1)/2;
02164                                 cnt = 0;
02165                                 for (j=0; j < w; j++) {
02166                                         if (m_downsample) {
02167                                                 // image was downsampled
02168                                                 uAvg = u[sampledPos];
02169                                                 vAvg = v[sampledPos];
02170                                                 aAvg = Clamp8(a[sampledPos] + YUVoffset8);
02171                                         } else {
02172                                                 uAvg = u[yPos];
02173                                                 vAvg = v[yPos];
02174                                                 aAvg = Clamp8(a[yPos] + YUVoffset8);
02175                                         }
02176                                         // Yuv
02177                                         buff[cnt + channelMap[1]] = g = Clamp8(y[yPos] + YUVoffset8 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
02178                                         buff[cnt + channelMap[2]] = Clamp8(uAvg + g);
02179                                         buff[cnt + channelMap[0]] = Clamp8(vAvg + g);
02180                                         buff[cnt + channelMap[3]] = aAvg;
02181                                         yPos++; 
02182                                         cnt += channels;
02183                                         if (j%2) sampledPos++;
02184                                 }
02185                                 buff += pitch;
02186                                 if (wOdd) sampledPos++;
02187 
02188                                 if (cb) {
02189                                         percent += dP;
02190                                         if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02191                                 }
02192                         }
02193                         break;
02194                 }
02195         case ImageModeCMYK64: 
02196                 {
02197                         ASSERT(m_header.channels == 4);
02198                         ASSERT(m_header.bpp == 64);
02199 
02200                         const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
02201 
02202                         DataT* y = m_channel[0]; ASSERT(y);
02203                         DataT* u = m_channel[1]; ASSERT(u);
02204                         DataT* v = m_channel[2]; ASSERT(v);
02205                         DataT* a = m_channel[3]; ASSERT(a);
02206                         DataT g, aAvg;
02207                         int cnt, channels;
02208 
02209                         if (bpp%16 == 0) {
02210                                 const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
02211                                 UINT16 *buff16 = (UINT16 *)buff;
02212                                 int pitch16 = pitch/2;
02213                                 channels = bpp/16; ASSERT(channels >= m_header.channels);
02214 
02215                                 for (i=0; i < h; i++) {
02216                                         if (i%2) sampledPos -= (w + 1)/2;
02217                                         cnt = 0;
02218                                         for (j=0; j < w; j++) {
02219                                                 if (m_downsample) {
02220                                                         // image was downsampled
02221                                                         uAvg = u[sampledPos];
02222                                                         vAvg = v[sampledPos];
02223                                                         aAvg = a[sampledPos] + yuvOffset16;
02224                                                 } else {
02225                                                         uAvg = u[yPos];
02226                                                         vAvg = v[yPos];
02227                                                         aAvg = a[yPos] + yuvOffset16;
02228                                                 }
02229                                                 // Yuv
02230                                                 g = y[yPos] + yuvOffset16 - ((uAvg + vAvg ) >> 2); // must be logical shift operator
02231                                                 buff16[cnt + channelMap[1]] = Clamp16(g << shift);
02232                                                 buff16[cnt + channelMap[2]] = Clamp16((uAvg + g) << shift);
02233                                                 buff16[cnt + channelMap[0]] = Clamp16((vAvg + g) << shift);
02234                                                 buff16[cnt + channelMap[3]] = Clamp16(aAvg << shift);
02235                                                 yPos++; 
02236                                                 cnt += channels;
02237                                                 if (j%2) sampledPos++;
02238                                         }
02239                                         buff16 += pitch16;
02240                                         if (wOdd) sampledPos++;
02241 
02242                                         if (cb) {
02243                                                 percent += dP;
02244                                                 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02245                                         }
02246                                 }
02247                         } else {
02248                                 ASSERT(bpp%8 == 0);
02249                                 const int shift = __max(0, UsedBitsPerChannel() - 8);
02250                                 channels = bpp/8; ASSERT(channels >= m_header.channels);
02251 
02252                                 for (i=0; i < h; i++) {
02253                                         if (i%2) sampledPos -= (w + 1)/2;
02254                                         cnt = 0;
02255                                         for (j=0; j < w; j++) {
02256                                                 if (m_downsample) {
02257                                                         // image was downsampled
02258                                                         uAvg = u[sampledPos];
02259                                                         vAvg = v[sampledPos];
02260                                                         aAvg = a[sampledPos] + yuvOffset16;
02261                                                 } else {
02262                                                         uAvg = u[yPos];
02263                                                         vAvg = v[yPos];
02264                                                         aAvg = a[yPos] + yuvOffset16;
02265                                                 }
02266                                                 // Yuv
02267                                                 g = y[yPos] + yuvOffset16 - ((uAvg + vAvg ) >> 2); // must be logical shift operator
02268                                                 buff[cnt + channelMap[1]] = Clamp8(g >> shift); 
02269                                                 buff[cnt + channelMap[2]] = Clamp8((uAvg + g) >> shift);
02270                                                 buff[cnt + channelMap[0]] = Clamp8((vAvg + g) >> shift);
02271                                                 buff[cnt + channelMap[3]] = Clamp8(aAvg >> shift);
02272                                                 yPos++; 
02273                                                 cnt += channels;
02274                                                 if (j%2) sampledPos++;
02275                                         }
02276                                         buff += pitch;
02277                                         if (wOdd) sampledPos++;
02278 
02279                                         if (cb) {
02280                                                 percent += dP;
02281                                                 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02282                                         }
02283                                 }
02284                         }
02285                         break;
02286                 }
02287 #ifdef __PGF32SUPPORT__
02288         case ImageModeGray32:
02289                 {
02290                         ASSERT(m_header.channels == 1);
02291                         ASSERT(m_header.bpp == 32);
02292 
02293                         const int yuvOffset31 = 1 << (UsedBitsPerChannel() - 1);
02294 
02295                         DataT* y = m_channel[0]; ASSERT(y);
02296 
02297                         if (bpp == 32) {
02298                                 const int shift = 31 - UsedBitsPerChannel(); ASSERT(shift >= 0);
02299                                 UINT32 *buff32 = (UINT32 *)buff;
02300                                 int pitch32 = pitch/4;
02301 
02302                                 for (i=0; i < h; i++) {
02303                                         for (j=0; j < w; j++) {
02304                                                 buff32[j] = Clamp31((y[yPos++] + yuvOffset31) << shift);
02305                                         }
02306                                         buff32 += pitch32;
02307 
02308                                         if (cb) {
02309                                                 percent += dP;
02310                                                 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02311                                         }
02312                                 }
02313                         } else if (bpp == 16) {
02314                                 const int usedBits = UsedBitsPerChannel();
02315                                 UINT16 *buff16 = (UINT16 *)buff;
02316                                 int pitch16 = pitch/2;
02317 
02318                                 if (usedBits < 16) {
02319                                         const int shift = 16 - usedBits;
02320                                         for (i=0; i < h; i++) {
02321                                                 for (j=0; j < w; j++) {
02322                                                         buff16[j] = Clamp16((y[yPos++] + yuvOffset31) << shift);
02323                                                 }
02324                                                 buff16 += pitch16;
02325 
02326                                                 if (cb) {
02327                                                         percent += dP;
02328                                                         if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02329                                                 }
02330                                         }
02331                                 } else {
02332                                         const int shift = __max(0, usedBits - 16);
02333                                         for (i=0; i < h; i++) {
02334                                                 for (j=0; j < w; j++) {
02335                                                         buff16[j] = Clamp16((y[yPos++] + yuvOffset31) >> shift);
02336                                                 }
02337                                                 buff16 += pitch16;
02338 
02339                                                 if (cb) {
02340                                                         percent += dP;
02341                                                         if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02342                                                 }
02343                                         }
02344                                 }
02345                         } else {
02346                                 ASSERT(bpp == 8);
02347                                 const int shift = __max(0, UsedBitsPerChannel() - 8);
02348                                 
02349                                 for (i=0; i < h; i++) {
02350                                         for (j=0; j < w; j++) {
02351                                                 buff[j] = Clamp8((y[yPos++] + yuvOffset31) >> shift);
02352                                         }
02353                                         buff += pitch;
02354 
02355                                         if (cb) {
02356                                                 percent += dP;
02357                                                 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02358                                         }
02359                                 }
02360                         }
02361                         break;  
02362                 }
02363 #endif
02364         case ImageModeRGB12: 
02365                 {
02366                         ASSERT(m_header.channels == 3);
02367                         ASSERT(m_header.bpp == m_header.channels*4);
02368                         ASSERT(bpp == m_header.channels*4);
02369                         ASSERT(!m_downsample);
02370 
02371                         DataT* y = m_channel[0]; ASSERT(y);
02372                         DataT* u = m_channel[1]; ASSERT(u);
02373                         DataT* v = m_channel[2]; ASSERT(v);
02374                         UINT16 yval;
02375                         int cnt;
02376 
02377                         for (i=0; i < h; i++) {
02378                                 cnt = 0;
02379                                 for (j=0; j < w; j++) {
02380                                         // Yuv
02381                                         uAvg = u[yPos];
02382                                         vAvg = v[yPos];
02383                                         yval = Clamp4(y[yPos++] + YUVoffset4 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
02384                                         if (j%2 == 0) {
02385                                                 buff[cnt] = UINT8(Clamp4(vAvg + yval) | (yval << 4));
02386                                                 cnt++;
02387                                                 buff[cnt] = Clamp4(uAvg + yval);
02388                                         } else {
02389                                                 buff[cnt] |= Clamp4(vAvg + yval) << 4;
02390                                                 cnt++;
02391                                                 buff[cnt] = UINT8(yval | (Clamp4(uAvg + yval) << 4));
02392                                                 cnt++;
02393                                         }
02394                                 }
02395                                 buff += pitch;
02396 
02397                                 if (cb) {
02398                                         percent += dP;
02399                                         if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02400                                 }
02401                         }
02402                         break;
02403                 }
02404         case ImageModeRGB16: 
02405                 {
02406                         ASSERT(m_header.channels == 3);
02407                         ASSERT(m_header.bpp == 16);
02408                         ASSERT(bpp == 16);
02409                         ASSERT(!m_downsample);
02410 
02411                         DataT* y = m_channel[0]; ASSERT(y);
02412                         DataT* u = m_channel[1]; ASSERT(u);
02413                         DataT* v = m_channel[2]; ASSERT(v);
02414                         UINT16 yval;
02415                         UINT16 *buff16 = (UINT16 *)buff;
02416                         int pitch16 = pitch/2;
02417 
02418                         for (i=0; i < h; i++) {
02419                                 for (j=0; j < w; j++) {
02420                                         // Yuv
02421                                         uAvg = u[yPos];
02422                                         vAvg = v[yPos];
02423                                         yval = Clamp6(y[yPos++] + YUVoffset6 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
02424                                         buff16[j] = (yval << 5) | ((Clamp6(uAvg + yval) >> 1) << 11) | (Clamp6(vAvg + yval) >> 1);
02425                                 }
02426                                 buff16 += pitch16;
02427 
02428                                 if (cb) {
02429                                         percent += dP;
02430                                         if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02431                                 }
02432                         }
02433                         break;
02434                 }
02435         default:
02436                 ASSERT(false);
02437         }
02438 
02439 #ifdef __PGFROISUPPORT__
02440         if (targetBuff) {
02441                 // copy valid ROI (m_roi) from temporary buffer (roi) to target buffer
02442                 if (bpp%8 == 0) {
02443                         BYTE bypp = bpp/8;
02444                         buff = buffStart + (levelRoi.top - roi.top)*pitch + (levelRoi.left - roi.left)*bypp;
02445                         w = levelRoi.Width()*bypp;
02446                         h = levelRoi.Height();
02447 
02448                         for (i=0; i < h; i++) {
02449                                 for (j=0; j < w; j++) {
02450                                         targetBuff[j] = buff[j];
02451                                 }
02452                                 targetBuff += targetPitch;
02453                                 buff += pitch;
02454                         }
02455                 } else {
02456                         // to do
02457                 }
02458 
02459                 delete[] buffStart; buffStart = 0;
02460         }
02461 #endif
02462 }                       

DataT* CPGFImage::GetChannel ( int  c = 0  )  [inline]

Return an internal YUV image channel.

Parameters:
c A channel index
Returns:
An internal YUV image channel

Definition at line 321 of file PGFimage.h.

00321 { ASSERT(c >= 0 && c < MaxChannels); return m_channel[c]; }

const RGBQUAD* CPGFImage::GetColorTable (  )  const [inline]
Returns:
Address of color table

Definition at line 334 of file PGFimage.h.

00334 { return m_postHeader.clut; }

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:
iFirstColor The color table index of the first entry to retrieve.
nColors The number of color table entries to retrieve.
prgbColors A pointer to the array of RGBQUAD structures to retrieve the color table entries.

Definition at line 1292 of file PGFimage.cpp.

01292                                                                                                   {
01293         if (iFirstColor + nColors > ColorTableLen)      ReturnWithError(ColorTableError);
01294 
01295         for (UINT32 i=iFirstColor, j=0; j < nColors; i++, j++) {
01296                 prgbColors[j] = m_postHeader.clut[i];
01297         }
01298 }

UINT32 CPGFImage::GetEncodedHeaderLength (  )  const

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 613 of file PGFimage.cpp.

00613                                                { 
00614         ASSERT(m_decoder); 
00615         return m_decoder->GetEncodedHeaderLength(); 
00616 }

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:
level The image level
Returns:
The length of a PGF level in bytes

Definition at line 370 of file PGFimage.h.

00370 { 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 339 of file PGFimage.h.

00339 { 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 345 of file PGFimage.h.

00345 { return (1 << m_header.usedBitsPerChannel) - 1; }

const UINT8 * CPGFImage::GetUserData ( UINT32 &  size  )  const

Return user data and size of user data. Precondition: The PGF image has been opened with a call of Open(...).

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 322 of file PGFimage.cpp.

00322                                                       {
00323         size = m_postHeader.userDataLen;
00324         return m_postHeader.userData;
00325 }

UINT64 CPGFImage::GetUserDataPos (  )  const [inline]

Return the stream position of the user data or 0. Precondition: The PGF image has been opened with a call of Open(...).

Definition at line 350 of file PGFimage.h.

00350 { return m_userDataPos; }                                                                       

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:
pitch The number of bytes of a row of the image buffer.
buff An image buffer.
bpp The number of bits per pixel used in image buffer.
channelMap A integer array containing the mapping of PGF channel ordering to expected channel ordering.
cb A pointer to a callback procedure. The procedure is called after each copied buffer row. If cb returns true, then it stops proceeding.
data Data 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:
pitch The number of bytes of a row of the image buffer.
buff An image buffer.
bpp The number of bits per pixel used in image buffer.
channelMap A integer array containing the mapping of PGF channel ordering to expected channel ordering.
cb A 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 2478 of file PGFimage.cpp.

02478                                                                                                                                                   {
02479         ASSERT(buff);
02480         const UINT32 w = m_width[0];
02481         const UINT32 h = m_height[0];
02482         const bool wOdd = (1 == w%2);
02483         const int dataBits = DataTSize*8; ASSERT(dataBits == 16 || dataBits == 32);
02484         const int pitch2 = pitch/DataTSize;
02485         const int yuvOffset = (dataBits == 16) ? YUVoffset8 : YUVoffset16;
02486         const double dP = 1.0/h;
02487 
02488         int defMap[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; ASSERT(sizeof(defMap)/sizeof(defMap[0]) == MaxChannels);
02489         if (channelMap == NULL) channelMap = defMap;
02490         int sampledPos = 0, yPos = 0;
02491         DataT uAvg, vAvg;
02492         double percent = 0;
02493         UINT32 i, j;
02494 
02495         if (m_header.channels == 3) { 
02496                 ASSERT(bpp%dataBits == 0);
02497 
02498                 DataT* y = m_channel[0]; ASSERT(y);
02499                 DataT* u = m_channel[1]; ASSERT(u);
02500                 DataT* v = m_channel[2]; ASSERT(v);
02501                 int cnt, channels = bpp/dataBits; ASSERT(channels >= m_header.channels);
02502 
02503                 for (i=0; i < h; i++) {
02504                         if (i%2) sampledPos -= (w + 1)/2;
02505                         cnt = 0;
02506                         for (j=0; j < w; j++) {
02507                                 if (m_downsample) {
02508                                         // image was downsampled
02509                                         uAvg = u[sampledPos];
02510                                         vAvg = v[sampledPos];
02511                                 } else {
02512                                         uAvg = u[yPos];
02513                                         vAvg = v[yPos];
02514                                 }
02515                                 buff[cnt + channelMap[0]] = y[yPos];
02516                                 buff[cnt + channelMap[1]] = uAvg;
02517                                 buff[cnt + channelMap[2]] = vAvg;
02518                                 yPos++; 
02519                                 cnt += channels;
02520                                 if (j%2) sampledPos++;
02521                         }
02522                         buff += pitch2;
02523                         if (wOdd) sampledPos++;
02524 
02525                         if (cb) {
02526                                 percent += dP;
02527                                 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02528                         }
02529                 }
02530         } else if (m_header.channels == 4) {
02531                 ASSERT(m_header.bpp == m_header.channels*8);
02532                 ASSERT(bpp%dataBits == 0);
02533 
02534                 DataT* y = m_channel[0]; ASSERT(y);
02535                 DataT* u = m_channel[1]; ASSERT(u);
02536                 DataT* v = m_channel[2]; ASSERT(v);
02537                 DataT* a = m_channel[3]; ASSERT(a);
02538                 UINT8 aAvg;
02539                 int cnt, channels = bpp/dataBits; ASSERT(channels >= m_header.channels);
02540 
02541                 for (i=0; i < h; i++) {
02542                         if (i%2) sampledPos -= (w + 1)/2;
02543                         cnt = 0;
02544                         for (j=0; j < w; j++) {
02545                                 if (m_downsample) {
02546                                         // image was downsampled
02547                                         uAvg = u[sampledPos];
02548                                         vAvg = v[sampledPos];
02549                                         aAvg = Clamp8(a[sampledPos] + yuvOffset);
02550                                 } else {
02551                                         uAvg = u[yPos];
02552                                         vAvg = v[yPos];
02553                                         aAvg = Clamp8(a[yPos] + yuvOffset);
02554                                 }
02555                                 // Yuv
02556                                 buff[cnt + channelMap[0]] = y[yPos];
02557                                 buff[cnt + channelMap[1]] = uAvg;
02558                                 buff[cnt + channelMap[2]] = vAvg;
02559                                 buff[cnt + channelMap[3]] = aAvg;
02560                                 yPos++; 
02561                                 cnt += channels;
02562                                 if (j%2) sampledPos++;
02563                         }
02564                         buff += pitch2;
02565                         if (wOdd) sampledPos++;
02566 
02567                         if (cb) {
02568                                 percent += dP;
02569                                 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02570                         }
02571                 }
02572         }
02573 }

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:
level A level
Returns:
Image level height in pixels

Definition at line 423 of file PGFimage.h.

00423 { 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:
pitch The number of bytes of a row of the image buffer.
buff An image buffer.
bpp The number of bits per pixel used in image buffer.
channelMap A integer array containing the mapping of input channel ordering to expected channel ordering.
cb A pointer to a callback procedure. The procedure is called after each imported buffer row. If cb returns true, then it stops proceeding.
data Data Pointer to C++ class container to host callback procedure.

Definition at line 743 of file PGFimage.cpp.

00743                                                                                                                                                    {
00744         ASSERT(buff);
00745         ASSERT(m_channel[0]);
00746 
00747         // color transform
00748         RgbToYuv(pitch, buff, bpp, channelMap, cb, data);
00749 
00750         if (m_downsample) {
00751                 // Subsampling of the chrominance and alpha channels
00752                 for (int i=1; i < m_header.channels; i++) {
00753                         Downsample(i);
00754                 }
00755         }
00756 }

bool CPGFImage::ImportIsSupported ( BYTE  mode  )  [static]

Check for valid import image mode.

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

Definition at line 1247 of file PGFimage.cpp.

01247                                            {
01248         size_t size = DataTSize;
01249 
01250         if (size >= 2) {
01251                 switch(mode) {
01252                         case ImageModeBitmap:
01253                         case ImageModeIndexedColor:
01254                         case ImageModeGrayScale:
01255                         case ImageModeRGBColor:
01256                         case ImageModeCMYKColor:
01257                         case ImageModeHSLColor:
01258                         case ImageModeHSBColor:
01259                         //case ImageModeDuotone:
01260                         case ImageModeLabColor:
01261                         case ImageModeRGB12:
01262                         case ImageModeRGB16:
01263                         case ImageModeRGBA:
01264                                 return true;
01265                 }
01266         }
01267         if (size >= 3) {
01268                 switch(mode) {
01269                         case ImageModeGray16:
01270                         case ImageModeRGB48:
01271                         case ImageModeLab48:
01272                         case ImageModeCMYK64:
01273                         //case ImageModeDuotone16:
01274                                 return true;
01275                 }
01276         }
01277         if (size >=4) {
01278                 switch(mode) {
01279                         case ImageModeGray32:
01280                                 return true;
01281                 }
01282         }
01283         return false;
01284 }

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:
pitch The number of bytes of a row of the image buffer.
buff An image buffer.
bpp The number of bits per pixel used in image buffer.
channelMap A integer array containing the mapping of input channel ordering to expected channel ordering.
cb A pointer to a callback procedure. The procedure is called after each imported buffer row. If cb returns true, then it stops proceeding.
data Data 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:
pitch The number of bytes of a row of the image buffer.
buff An image buffer.
bpp The number of bits per pixel used in image buffer.
channelMap A integer array containing the mapping of input channel ordering to expected channel ordering.
cb A 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 2589 of file PGFimage.cpp.

02589                                                                                                                                                {
02590         ASSERT(buff);
02591         const double dP = 1.0/m_header.height;
02592         const int dataBits = DataTSize*8; ASSERT(dataBits == 16 || dataBits == 32);
02593         const int pitch2 = pitch/DataTSize;
02594         const int yuvOffset = (dataBits == 16) ? YUVoffset8 : YUVoffset16;
02595 
02596         int yPos = 0, cnt = 0;
02597         double percent = 0;
02598         int defMap[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; ASSERT(sizeof(defMap)/sizeof(defMap[0]) == MaxChannels);
02599 
02600         if (channelMap == NULL) channelMap = defMap;
02601 
02602         if (m_header.channels == 3)     {
02603                 ASSERT(bpp%dataBits == 0);
02604 
02605                 DataT* y = m_channel[0]; ASSERT(y);
02606                 DataT* u = m_channel[1]; ASSERT(u);
02607                 DataT* v = m_channel[2]; ASSERT(v);
02608                 const int channels = bpp/dataBits; ASSERT(channels >= m_header.channels);
02609 
02610                 for (UINT32 h=0; h < m_header.height; h++) {
02611                         if (cb) {
02612                                 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02613                                 percent += dP;
02614                         }
02615 
02616                         cnt = 0;
02617                         for (UINT32 w=0; w < m_header.width; w++) {
02618                                 y[yPos] = buff[cnt + channelMap[0]];
02619                                 u[yPos] = buff[cnt + channelMap[1]];
02620                                 v[yPos] = buff[cnt + channelMap[2]];
02621                                 yPos++;
02622                                 cnt += channels;
02623                         }
02624                         buff += pitch2;
02625                 }       
02626         } else if (m_header.channels == 4) {
02627                 ASSERT(bpp%dataBits == 0);
02628 
02629                 DataT* y = m_channel[0]; ASSERT(y);
02630                 DataT* u = m_channel[1]; ASSERT(u);
02631                 DataT* v = m_channel[2]; ASSERT(v);
02632                 DataT* a = m_channel[3]; ASSERT(a);
02633                 const int channels = bpp/dataBits; ASSERT(channels >= m_header.channels);
02634 
02635                 for (UINT32 h=0; h < m_header.height; h++) {
02636                         if (cb) {
02637                                 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02638                                 percent += dP;
02639                         }
02640 
02641                         cnt = 0;
02642                         for (UINT32 w=0; w < m_header.width; w++) {
02643                                 y[yPos] = buff[cnt + channelMap[0]];
02644                                 u[yPos] = buff[cnt + channelMap[1]];
02645                                 v[yPos] = buff[cnt + channelMap[2]];
02646                                 a[yPos] = buff[cnt + channelMap[3]] - yuvOffset;
02647                                 yPos++;
02648                                 cnt += channels;
02649                         }
02650                         buff += pitch2;
02651                 }       
02652         }
02653 
02654         if (m_downsample) {
02655                 // Subsampling of the chrominance and alpha channels
02656                 for (int i=1; i < m_header.channels; i++) {
02657                         Downsample(i);
02658                 }
02659         }
02660 }

bool CPGFImage::IsOpen (  )  const [inline]

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

Definition at line 87 of file PGFimage.h.

00087 { 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 430 of file PGFimage.h.

00430 { return (BYTE)m_currentLevel; }

static UINT32 CPGFImage::LevelHeight ( UINT32  height,
int  level 
) [inline, static]

Compute and return image height at given level.

Parameters:
height Original image height (at level 0)
level An image level
Returns:
Image level height in pixels

Definition at line 498 of file PGFimage.h.

00498 { 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 435 of file PGFimage.h.

00435 { return m_header.nLevels; }

static UINT32 CPGFImage::LevelWidth ( UINT32  width,
int  level 
) [inline, static]

Compute and return image width at given level.

Parameters:
width Original image width (at level 0)
level An image level
Returns:
Image level width in pixels

Definition at line 491 of file PGFimage.h.

00491 { 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 454 of file PGFimage.h.

00454 { 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:
stream A PGF stream

Definition at line 131 of file PGFimage.cpp.

00131                                               {
00132         ASSERT(stream);
00133 
00134         // create decoder and read PGFPreHeader PGFHeader PGFPostHeader LevelLengths
00135         m_decoder = new CDecoder(stream, m_preHeader, m_header, m_postHeader, m_levelLength, 
00136                 m_userDataPos, m_useOMPinDecoder, m_skipUserData);
00137 
00138         if (m_header.nLevels > MaxLevel) ReturnWithError(FormatCannotRead);
00139 
00140         // set current level
00141         m_currentLevel = m_header.nLevels;
00142 
00143         // set image width and height
00144         m_width[0] = m_header.width;
00145         m_height[0] = m_header.height;
00146 
00147         // complete header
00148         if (!CompleteHeader()) ReturnWithError(FormatCannotRead);
00149 
00150         // interpret quant parameter
00151         if (m_header.quality > DownsampleThreshold && 
00152                 (m_header.mode == ImageModeRGBColor || 
00153                  m_header.mode == ImageModeRGBA || 
00154                  m_header.mode == ImageModeRGB48 || 
00155                  m_header.mode == ImageModeCMYKColor || 
00156                  m_header.mode == ImageModeCMYK64 || 
00157                  m_header.mode == ImageModeLabColor || 
00158                  m_header.mode == ImageModeLab48)) {
00159                 m_downsample = true;
00160                 m_quant = m_header.quality - 1;
00161         } else {
00162                 m_downsample = false;
00163                 m_quant = m_header.quality;
00164         }
00165 
00166         // set channel dimensions (chrominance is subsampled by factor 2)
00167         if (m_downsample) {
00168                 for (int i=1; i < m_header.channels; i++) {
00169                         m_width[i] = (m_width[0] + 1)/2;
00170                         m_height[i] = (m_height[0] + 1)/2;
00171                 }
00172         } else {
00173                 for (int i=1; i < m_header.channels; i++) {
00174                         m_width[i] = m_width[0];
00175                         m_height[i] = m_height[0];
00176                 }
00177         }
00178 
00179         if (m_header.nLevels > 0) {
00180                 // init wavelet subbands
00181                 for (int i=0; i < m_header.channels; i++) {
00182                         m_wtChannel[i] = new CWaveletTransform(m_width[i], m_height[i], m_header.nLevels);
00183                 }
00184 
00185                 // used in Read when PM_Absolute
00186                 m_percent = pow(0.25, m_header.nLevels);
00187 
00188         } else {
00189                 // very small image: we don't use DWT and encoding
00190 
00191                 // read channels
00192                 for (int c=0; c < m_header.channels; c++) {
00193                         const UINT32 size = m_width[c]*m_height[c];
00194                         m_channel[c] = new(std::nothrow) DataT[size];
00195                         if (!m_channel[c]) ReturnWithError(InsufficientMemory);
00196 
00197                         // read channel data from stream
00198                         for (UINT32 i=0; i < size; i++) {
00199                                 int count = DataTSize;
00200                                 stream->Read(&count, &m_channel[c][i]);
00201                                 if (count != DataTSize) ReturnWithError(MissingData);
00202                         }
00203                 }
00204         }
00205 }

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 441 of file PGFimage.h.

00441 { 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.
cb A pointer to a callback procedure. The procedure is called after reading a single level. If cb returns true, then it stops proceeding.
data Data Pointer to C++ class container to host callback procedure.

Definition at line 384 of file PGFimage.cpp.

00384                                                                                               {
00385         ASSERT((level >= 0 && level < m_header.nLevels) || m_header.nLevels == 0); // m_header.nLevels == 0: image didn't use wavelet transform
00386         ASSERT(m_decoder);
00387 
00388 #ifdef __PGFROISUPPORT__
00389         if (ROIisSupported() && m_header.nLevels > 0) {
00390                 // new encoding scheme supporting ROI
00391                 PGFRect rect(0, 0, m_header.width, m_header.height);
00392                 Read(rect, level, cb, data);
00393                 return;
00394         }
00395 #endif
00396 
00397         if (m_header.nLevels == 0) {
00398                 if (level == 0) {
00399                         // the data has already been read during open
00400                         // now update progress
00401                         if (cb) {
00402                                 if ((*cb)(1.0, true, data)) ReturnWithError(EscapePressed);
00403                         }
00404                 }
00405         } else {
00406                 const int levelDiff = m_currentLevel - level;
00407                 double percent = (m_progressMode == PM_Relative) ? pow(0.25, levelDiff) : m_percent;
00408 
00409                 // encoding scheme without ROI
00410                 while (m_currentLevel > level) {
00411                         for (int i=0; i < m_header.channels; i++) {
00412                                 ASSERT(m_wtChannel[i]);
00413                                 // decode file and write stream to m_wtChannel
00414                                 if (m_currentLevel == m_header.nLevels) { 
00415                                         // last level also has LL band
00416                                         m_wtChannel[i]->GetSubband(m_currentLevel, LL)->PlaceTile(*m_decoder, m_quant);
00417                                 }
00418                                 if (m_preHeader.version & Version5) {
00419                                         // since version 5
00420                                         m_wtChannel[i]->GetSubband(m_currentLevel, HL)->PlaceTile(*m_decoder, m_quant);
00421                                         m_wtChannel[i]->GetSubband(m_currentLevel, LH)->PlaceTile(*m_decoder, m_quant);
00422                                 } else {
00423                                         // until version 4
00424                                         m_decoder->DecodeInterleaved(m_wtChannel[i], m_currentLevel, m_quant);
00425                                 }
00426                                 m_wtChannel[i]->GetSubband(m_currentLevel, HH)->PlaceTile(*m_decoder, m_quant);
00427                         }
00428 
00429                         volatile OSError error = NoError; // volatile prevents optimizations
00430 #ifdef LIBPGF_USE_OPENMP
00431                         #pragma omp parallel for default(shared) 
00432 #endif
00433                         for (int i=0; i < m_header.channels; i++) {
00434                                 // inverse transform from m_wtChannel to m_channel
00435                                 if (error == NoError) {
00436                                         OSError err = m_wtChannel[i]->InverseTransform(m_currentLevel, &m_width[i], &m_height[i], &m_channel[i]);       
00437                                         if (err != NoError) error = err;
00438                                 }
00439                                 ASSERT(m_channel[i]);
00440                         }
00441                         if (error != NoError) ReturnWithError(error);
00442 
00443                         // set new level: must be done before refresh callback
00444                         m_currentLevel--;
00445 
00446                         // now we have to refresh the display
00447                         if (m_cb) m_cb(m_cbArg);
00448 
00449                         // now update progress
00450                         if (cb) {
00451                                 percent *= 4;
00452                                 if (m_progressMode == PM_Absolute) m_percent = percent;
00453                                 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
00454                         }
00455                 }
00456         }
00457 
00458         // automatically closing
00459         if (m_currentLevel == 0) Close();
00460 }

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:
level The image level
target The target buffer
targetLen The length of the target buffer in bytes
Returns:
The number of bytes copied to the target buffer

Definition at line 659 of file PGFimage.cpp.

00659                                                                                          {
00660         ASSERT(level >= 0 && level < m_header.nLevels);
00661         ASSERT(target);
00662         ASSERT(targetLen > 0);
00663         ASSERT(m_decoder);
00664 
00665         // reset stream position
00666         m_decoder->SetStreamPosToData();
00667 
00668         // position stream
00669         UINT64 offset = 0;
00670 
00671         for (int i=m_header.nLevels - 1; i > level; i--) {
00672                 offset += m_levelLength[m_header.nLevels - 1 - i];
00673         }
00674         m_decoder->Skip(offset);
00675 
00676         // compute number of bytes to read
00677         UINT32 len = __min(targetLen, GetEncodedLevelLength(level));
00678 
00679         // read data
00680         len = m_decoder->ReadEncodedData(target, len);
00681         ASSERT(len >= 0 && len <= targetLen);
00682 
00683         return len;
00684 }

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:
target The target buffer
targetLen The length of the target buffer in bytes
Returns:
The number of bytes copied to the target buffer

Definition at line 625 of file PGFimage.cpp.

00625                                                                                 {
00626         ASSERT(target);
00627         ASSERT(targetLen > 0);
00628         ASSERT(m_decoder);
00629 
00630         // reset stream position
00631         m_decoder->SetStreamPosToStart();
00632 
00633         // compute number of bytes to read
00634         UINT32 len = __min(targetLen, GetEncodedHeaderLength());
00635 
00636         // read data
00637         len = m_decoder->ReadEncodedData(target, len);
00638         ASSERT(len >= 0 && len <= targetLen);
00639 
00640         return len;
00641 }

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 121 of file PGFimage.h.

00121 { 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:
level The image level of the resulting image in the internal image buffer.

Definition at line 332 of file PGFimage.cpp.

00332                                                     {
00333         if (m_header.nLevels == 0) {
00334                 // image didn't use wavelet transform
00335                 if (level == 0) {
00336                         for (int i=0; i < m_header.channels; i++) {
00337                                 ASSERT(m_wtChannel[i]);
00338                                 m_channel[i] = m_wtChannel[i]->GetSubband(0, LL)->GetBuffer();
00339                         }
00340                 }
00341         } else {
00342                 int currentLevel = m_header.nLevels;
00343 
00344                 if (ROIisSupported()) {
00345                         // enable ROI reading
00346                         SetROI(PGFRect(0, 0, m_header.width, m_header.height));
00347                 }
00348 
00349                 while (currentLevel > level) {
00350                         for (int i=0; i < m_header.channels; i++) {
00351                                 ASSERT(m_wtChannel[i]);
00352                                 // dequantize subbands
00353                                 if (currentLevel == m_header.nLevels) { 
00354                                         // last level also has LL band
00355                                         m_wtChannel[i]->GetSubband(currentLevel, LL)->Dequantize(m_quant);
00356                                 }
00357                                 m_wtChannel[i]->GetSubband(currentLevel, HL)->Dequantize(m_quant);
00358                                 m_wtChannel[i]->GetSubband(currentLevel, LH)->Dequantize(m_quant);
00359                                 m_wtChannel[i]->GetSubband(currentLevel, HH)->Dequantize(m_quant);
00360 
00361                                 // inverse transform from m_wtChannel to m_channel
00362                                 OSError err = m_wtChannel[i]->InverseTransform(currentLevel, &m_width[i], &m_height[i], &m_channel[i]);
00363                                 if (err != NoError) ReturnWithError(err);
00364                                 ASSERT(m_channel[i]);
00365                         }
00366 
00367                         currentLevel--;
00368                 }
00369         }
00370 }

void CPGFImage::ResetStreamPos (  ) 

Reset stream position to start of PGF pre-header

Definition at line 645 of file PGFimage.cpp.

00645                                       {
00646         ASSERT(m_decoder);
00647         return m_decoder->SetStreamPosToStart(); 
00648 }

void CPGFImage::RgbToYuv ( int  pitch,
UINT8 *  rgbBuff,
BYTE  bpp,
int  channelMap[],
CallbackPtr  cb,
void *  data 
) [private]

Definition at line 1331 of file PGFimage.cpp.

01331                                                                                                                         {
01332         ASSERT(buff);
01333         int yPos = 0, cnt = 0;
01334         double percent = 0;
01335         const double dP = 1.0/m_header.height;
01336         int defMap[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; ASSERT(sizeof(defMap)/sizeof(defMap[0]) == MaxChannels);
01337 
01338         if (channelMap == NULL) channelMap = defMap;
01339 
01340         switch(m_header.mode) {
01341         case ImageModeBitmap:
01342                 {
01343                         ASSERT(m_header.channels == 1);
01344                         ASSERT(m_header.bpp == 1);
01345                         ASSERT(bpp == 1);
01346                         
01347                         const UINT32 w = m_header.width;
01348                         const UINT32 w2 = (m_header.width + 7)/8;
01349                         DataT* y = m_channel[0]; ASSERT(y);
01350 
01351                         for (UINT32 h=0; h < m_header.height; h++) {
01352                                 if (cb) {
01353                                         if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01354                                         percent += dP;
01355                                 }
01356                                 
01357                                 for (UINT32 j=0; j < w2; j++) {
01358                                         y[yPos++] = buff[j] - YUVoffset8;
01359                                 }
01360                                 for (UINT32 j=w2; j < w; j++) {
01361                                         y[yPos++] = YUVoffset8;
01362                                 }
01363                                 
01364                                 //UINT cnt = w;
01365                                 //for (UINT32 j=0; j < w2; j++) {
01366                                 //      for (int k=7; k >= 0; k--) {
01367                                 //              if (cnt) { 
01368                                 //                      y[yPos++] = YUVoffset8 + (1 & (buff[j] >> k));
01369                                 //                      cnt--;
01370                                 //              }
01371                                 //      }
01372                                 //}
01373                                 buff += pitch;  
01374                         }
01375                 }
01376                 break;
01377         case ImageModeIndexedColor:
01378         case ImageModeGrayScale:
01379         case ImageModeHSLColor:
01380         case ImageModeHSBColor:
01381         case ImageModeLabColor:
01382                 {
01383                         ASSERT(m_header.channels >= 1);
01384                         ASSERT(m_header.bpp == m_header.channels*8);
01385                         ASSERT(bpp%8 == 0);
01386                         const int channels = bpp/8; ASSERT(channels >= m_header.channels);
01387 
01388                         for (UINT32 h=0; h < m_header.height; h++) {
01389                                 if (cb) {
01390                                         if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01391                                         percent += dP;
01392                                 }
01393 
01394                                 cnt = 0;
01395                                 for (UINT32 w=0; w < m_header.width; w++) {
01396                                         for (int c=0; c < m_header.channels; c++) {
01397                                                 m_channel[c][yPos] = buff[cnt + channelMap[c]] - YUVoffset8;
01398                                         }
01399                                         cnt += channels;
01400                                         yPos++;
01401                                 }
01402                                 buff += pitch;  
01403                         }
01404                 }
01405                 break;
01406         case ImageModeGray16:
01407         case ImageModeLab48:
01408                 {
01409                         ASSERT(m_header.channels >= 1);
01410                         ASSERT(m_header.bpp == m_header.channels*16);
01411                         ASSERT(bpp%16 == 0);
01412 
01413                         UINT16 *buff16 = (UINT16 *)buff;
01414                         const int pitch16 = pitch/2;
01415                         const int channels = bpp/16; ASSERT(channels >= m_header.channels);
01416                         const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
01417                         const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
01418 
01419                         for (UINT32 h=0; h < m_header.height; h++) {
01420                                 if (cb) {
01421                                         if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01422                                         percent += dP;
01423                                 }
01424 
01425                                 cnt = 0;
01426                                 for (UINT32 w=0; w < m_header.width; w++) {
01427                                         for (int c=0; c < m_header.channels; c++) {
01428                                                 m_channel[c][yPos] = (buff16[cnt + channelMap[c]] >> shift) - yuvOffset16;
01429                                         }
01430                                         cnt += channels;
01431                                         yPos++;
01432                                 }
01433                                 buff16 += pitch16;
01434                         }
01435                 }
01436                 break;
01437         case ImageModeRGBColor:
01438                 {
01439                         ASSERT(m_header.channels == 3);
01440                         ASSERT(m_header.bpp == m_header.channels*8);
01441                         ASSERT(bpp%8 == 0);
01442 
01443                         DataT* y = m_channel[0]; ASSERT(y);
01444                         DataT* u = m_channel[1]; ASSERT(u);
01445                         DataT* v = m_channel[2]; ASSERT(v);
01446                         const int channels = bpp/8; ASSERT(channels >= m_header.channels);
01447                         UINT8 b, g, r;
01448 
01449                         for (UINT32 h=0; h < m_header.height; h++) {
01450                                 if (cb) {
01451                                         if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01452                                         percent += dP;
01453                                 }
01454 
01455                                 cnt = 0;
01456                                 for (UINT32 w=0; w < m_header.width; w++) {
01457                                         b = buff[cnt + channelMap[0]];
01458                                         g = buff[cnt + channelMap[1]];
01459                                         r = buff[cnt + channelMap[2]];
01460                                         // Yuv
01461                                         y[yPos] = ((b + (g << 1) + r) >> 2) - YUVoffset8;
01462                                         u[yPos] = r - g;
01463                                         v[yPos] = b - g;
01464                                         yPos++;
01465                                         cnt += channels;
01466                                 }
01467                                 buff += pitch;
01468                         }       
01469                 }
01470                 break;
01471         case ImageModeRGB48:
01472                 {
01473                         ASSERT(m_header.channels == 3);
01474                         ASSERT(m_header.bpp == m_header.channels*16);
01475                         ASSERT(bpp%16 == 0);
01476 
01477                         UINT16 *buff16 = (UINT16 *)buff;
01478                         const int pitch16 = pitch/2;
01479                         const int channels = bpp/16; ASSERT(channels >= m_header.channels);
01480                         const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
01481                         const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
01482 
01483                         DataT* y = m_channel[0]; ASSERT(y);
01484                         DataT* u = m_channel[1]; ASSERT(u);
01485                         DataT* v = m_channel[2]; ASSERT(v);
01486                         UINT16 b, g, r;
01487 
01488                         for (UINT32 h=0; h < m_header.height; h++) {
01489                                 if (cb) {
01490                                         if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01491                                         percent += dP;
01492                                 }
01493 
01494                                 cnt = 0;
01495                                 for (UINT32 w=0; w < m_header.width; w++) {
01496                                         b = buff16[cnt + channelMap[0]] >> shift;
01497                                         g = buff16[cnt + channelMap[1]] >> shift;
01498                                         r = buff16[cnt + channelMap[2]] >> shift;
01499                                         // Yuv
01500                                         y[yPos] = ((b + (g << 1) + r) >> 2) - yuvOffset16;
01501                                         u[yPos] = r - g;
01502                                         v[yPos] = b - g;
01503                                         yPos++;
01504                                         cnt += channels;
01505                                 }
01506                                 buff16 += pitch16;
01507                         }       
01508                 }
01509                 break;
01510         case ImageModeRGBA:
01511         case ImageModeCMYKColor:
01512                 {
01513                         ASSERT(m_header.channels == 4);
01514                         ASSERT(m_header.bpp == m_header.channels*8);
01515                         ASSERT(bpp%8 == 0);
01516                         const int channels = bpp/8; ASSERT(channels >= m_header.channels);
01517 
01518                         DataT* y = m_channel[0]; ASSERT(y);
01519                         DataT* u = m_channel[1]; ASSERT(u);
01520                         DataT* v = m_channel[2]; ASSERT(v);
01521                         DataT* a = m_channel[3]; ASSERT(a);
01522                         UINT8 b, g, r;
01523 
01524                         for (UINT32 h=0; h < m_header.height; h++) {
01525                                 if (cb) {
01526                                         if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01527                                         percent += dP;
01528                                 }
01529 
01530                                 cnt = 0;
01531                                 for (UINT32 w=0; w < m_header.width; w++) {
01532                                         b = buff[cnt + channelMap[0]];
01533                                         g = buff[cnt + channelMap[1]];
01534                                         r = buff[cnt + channelMap[2]];
01535                                         // Yuv
01536                                         y[yPos] = ((b + (g << 1) + r) >> 2) - YUVoffset8;
01537                                         u[yPos] = r - g;
01538                                         v[yPos] = b - g;
01539                                         a[yPos++] = buff[cnt + channelMap[3]] - YUVoffset8;
01540                                         cnt += channels;
01541                                 }
01542                                 buff += pitch;
01543                         }       
01544                 }
01545                 break;
01546         case ImageModeCMYK64:
01547                 {
01548                         ASSERT(m_header.channels == 4);
01549                         ASSERT(m_header.bpp == m_header.channels*16);
01550                         ASSERT(bpp%16 == 0);
01551 
01552                         UINT16 *buff16 = (UINT16 *)buff;
01553                         const int pitch16 = pitch/2;
01554                         const int channels = bpp/16; ASSERT(channels >= m_header.channels);
01555                         const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
01556                         const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
01557                         
01558                         DataT* y = m_channel[0]; ASSERT(y);
01559                         DataT* u = m_channel[1]; ASSERT(u);
01560                         DataT* v = m_channel[2]; ASSERT(v);
01561                         DataT* a = m_channel[3]; ASSERT(a);
01562                         UINT16 b, g, r;
01563 
01564                         for (UINT32 h=0; h < m_header.height; h++) {
01565                                 if (cb) {
01566                                         if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01567                                         percent += dP;
01568                                 }
01569 
01570                                 cnt = 0;
01571                                 for (UINT32 w=0; w < m_header.width; w++) {
01572                                         b = buff16[cnt + channelMap[0]] >> shift;
01573                                         g = buff16[cnt + channelMap[1]] >> shift;
01574                                         r = buff16[cnt + channelMap[2]] >> shift;
01575                                         // Yuv
01576                                         y[yPos] = ((b + (g << 1) + r) >> 2) - yuvOffset16;
01577                                         u[yPos] = r - g;
01578                                         v[yPos] = b - g;
01579                                         a[yPos++] = (buff16[cnt + channelMap[3]] >> shift) - yuvOffset16;
01580                                         cnt += channels;
01581                                 }
01582                                 buff16 += pitch16;
01583                         }       
01584                 }
01585                 break;
01586 #ifdef __PGF32SUPPORT__
01587         case ImageModeGray32:
01588                 {
01589                         ASSERT(m_header.channels == 1);
01590                         ASSERT(m_header.bpp == 32);
01591                         ASSERT(bpp == 32);
01592                         ASSERT(DataTSize == sizeof(UINT32));
01593 
01594                         DataT* y = m_channel[0]; ASSERT(y);
01595 
01596                         UINT32 *buff32 = (UINT32 *)buff;
01597                         const int pitch32 = pitch/4;
01598                         const int shift = 31 - UsedBitsPerChannel(); ASSERT(shift >= 0);
01599                         const DataT yuvOffset31 = 1 << (UsedBitsPerChannel() - 1);
01600 
01601                         for (UINT32 h=0; h < m_header.height; h++) {
01602                                 if (cb) {
01603                                         if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01604                                         percent += dP;
01605                                 }
01606 
01607                                 for (UINT32 w=0; w < m_header.width; w++) {
01608                                         y[yPos++] = (buff32[w] >> shift) - yuvOffset31;
01609                                 }
01610                                 buff32 += pitch32;
01611                         }
01612                 }
01613                 break;
01614 #endif
01615         case ImageModeRGB12:
01616                 {
01617                         ASSERT(m_header.channels == 3);
01618                         ASSERT(m_header.bpp == m_header.channels*4);
01619                         ASSERT(bpp == m_header.channels*4);
01620 
01621                         DataT* y = m_channel[0]; ASSERT(y);
01622                         DataT* u = m_channel[1]; ASSERT(u);
01623                         DataT* v = m_channel[2]; ASSERT(v);
01624 
01625                         UINT8 rgb = 0, b, g, r;
01626 
01627                         for (UINT32 h=0; h < m_header.height; h++) {
01628                                 if (cb) {
01629                                         if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01630                                         percent += dP;
01631                                 }
01632 
01633                                 cnt = 0;
01634                                 for (UINT32 w=0; w < m_header.width; w++) {
01635                                         if (w%2 == 0) {
01636                                                 // even pixel position
01637                                                 rgb = buff[cnt];
01638                                                 b = rgb & 0x0F;
01639                                                 g = (rgb & 0xF0) >> 4;
01640                                                 cnt++;
01641                                                 rgb = buff[cnt];
01642                                                 r = rgb & 0x0F;
01643                                         } else {
01644                                                 // odd pixel position
01645                                                 b = (rgb & 0xF0) >> 4;
01646                                                 cnt++;
01647                                                 rgb = buff[cnt];
01648                                                 g = rgb & 0x0F;
01649                                                 r = (rgb & 0xF0) >> 4;
01650                                                 cnt++;
01651                                         }
01652 
01653                                         // Yuv
01654                                         y[yPos] = ((b + (g << 1) + r) >> 2) - YUVoffset4;
01655                                         u[yPos] = r - g;
01656                                         v[yPos] = b - g;
01657                                         yPos++;
01658                                 }
01659                                 buff += pitch;
01660                         }       
01661                 }
01662                 break;
01663         case ImageModeRGB16:
01664                 {
01665                         ASSERT(m_header.channels == 3);
01666                         ASSERT(m_header.bpp == 16);
01667                         ASSERT(bpp == 16);
01668                         
01669                         DataT* y = m_channel[0]; ASSERT(y);
01670                         DataT* u = m_channel[1]; ASSERT(u);
01671                         DataT* v = m_channel[2]; ASSERT(v);
01672 
01673                         UINT16 *buff16 = (UINT16 *)buff;
01674                         UINT16 rgb, b, g, r;
01675                         const int pitch16 = pitch/2;
01676 
01677                         for (UINT32 h=0; h < m_header.height; h++) {
01678                                 if (cb) {
01679                                         if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01680                                         percent += dP;
01681                                 }
01682                                 for (UINT32 w=0; w < m_header.width; w++) {
01683                                         rgb = buff16[w]; 
01684                                         r = (rgb & 0xF800) >> 10;       // highest 5 bits
01685                                         g = (rgb & 0x07E0) >> 5;        // middle 6 bits
01686                                         b = (rgb & 0x001F) << 1;        // lowest 5 bits
01687                                         // Yuv
01688                                         y[yPos] = ((b + (g << 1) + r) >> 2) - YUVoffset6;
01689                                         u[yPos] = r - g;
01690                                         v[yPos] = b - g;
01691                                         yPos++;
01692                                 }
01693 
01694                                 buff16 += pitch16;
01695                         }       
01696                 }
01697                 break;
01698         default:
01699                 ASSERT(false);
01700         }
01701 }

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 465 of file PGFimage.h.

00465 { return (m_preHeader.version & PGFROI) == PGFROI; }

void CPGFImage::SetChannel ( DataT channel,
int  c = 0 
) [inline]

Set internal PGF image buffer channel.

Parameters:
channel A YUV data channel
c A channel index

Definition at line 276 of file PGFimage.h.

00276 { 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:
iFirstColor The color table index of the first entry to set.
nColors The number of color table entries to set.
prgbColors A pointer to the array of RGBQUAD structures to set the color table entries.

Definition at line 1306 of file PGFimage.cpp.

01306                                                                                                   {
01307         if (iFirstColor + nColors > ColorTableLen)      ReturnWithError(ColorTableError);
01308 
01309         for (UINT32 i=iFirstColor, j=0; j < nColors; i++, j++) {
01310                 m_postHeader.clut[i] = prgbColors[j];
01311         }
01312 }

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:
header A valid and already filled in PGF header structure
flags A combination of additional version flags. In case you use level-wise encoding then set flag = PGFROI.
userData A user-defined memory block containing any kind of cached metadata.
userDataLength The size of user-defined memory block in bytes

Definition at line 844 of file PGFimage.cpp.

00844                                                                                                                                    {
00845         ASSERT(!m_decoder);     // current image must be closed
00846         ASSERT(header.quality <= MaxQuality);
00847 
00848         // init state
00849 #ifdef __PGFROISUPPORT__
00850         m_streamReinitialized = false;
00851 #endif
00852 
00853         // init preHeader
00854         memcpy(m_preHeader.magic, PGFMagic, 3);
00855         m_preHeader.version = PGFVersion | flags;
00856         m_preHeader.hSize = HeaderSize;
00857 
00858         // copy header
00859         memcpy(&m_header, &header, HeaderSize);
00860 
00861         // complete header
00862         CompleteHeader();
00863 
00864         // check and set number of levels
00865         ComputeLevels();
00866 
00867         // check for downsample
00868         if (m_header.quality > DownsampleThreshold &&  (m_header.mode == ImageModeRGBColor || 
00869                                                                                                         m_header.mode == ImageModeRGBA || 
00870                                                                                                         m_header.mode == ImageModeRGB48 || 
00871                                                                                                         m_header.mode == ImageModeCMYKColor || 
00872                                                                                                         m_header.mode == ImageModeCMYK64 || 
00873                                                                                                         m_header.mode == ImageModeLabColor || 
00874                                                                                                         m_header.mode == ImageModeLab48)) {
00875                 m_downsample = true;
00876                 m_quant = m_header.quality - 1;
00877         } else {
00878                 m_downsample = false;
00879                 m_quant = m_header.quality;
00880         }
00881 
00882         // update header size and copy user data
00883         if (m_header.mode == ImageModeIndexedColor) {
00884                 // update header size
00885                 m_preHeader.hSize += ColorTableSize;
00886         }
00887         if (userDataLength && userData) {
00888                 m_postHeader.userData = new(std::nothrow) UINT8[userDataLength];
00889                 if (!m_postHeader.userData) ReturnWithError(InsufficientMemory);
00890                 m_postHeader.userDataLen = userDataLength;
00891                 memcpy(m_postHeader.userData, userData, userDataLength);
00892                 // update header size
00893                 m_preHeader.hSize += userDataLength;
00894         }
00895 
00896         // allocate channels
00897         for (int i=0; i < m_header.channels; i++) {
00898                 // set current width and height
00899                 m_width[i] = m_header.width;
00900                 m_height[i] = m_header.height;
00901 
00902                 // allocate channels
00903                 ASSERT(!m_channel[i]);
00904                 m_channel[i] = new(std::nothrow) DataT[m_header.width*m_header.height];
00905                 if (!m_channel[i]) {
00906                         if (i) i--;
00907                         while(i) {
00908                                 delete[] m_channel[i]; m_channel[i] = 0;
00909                                 i--;
00910                         }
00911                         ReturnWithError(InsufficientMemory);
00912                 }
00913         }
00914 }

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:
maxValue The maximum intensity value.

Definition at line 690 of file PGFimage.cpp.

00690                                            {
00691         const BYTE bpc = m_header.bpp/m_header.channels;
00692         BYTE pot = 0;
00693 
00694         while(maxValue > 0) {
00695                 pot++;
00696                 maxValue >>= 1;
00697         }
00698         // store bits per channel
00699         if (pot > bpc) pot = bpc;
00700         if (pot > 31) pot = 31;
00701         m_header.usedBitsPerChannel = pot;
00702 }

void CPGFImage::SetProgressMode ( ProgressMode  pm  )  [inline]

Set progress mode used in Read and Write. Default mode is PM_Relative. This method must be called before Open() or SetHeader(). PM_Relative: 100% = level difference between current level and target level of Read/Write PM_Absolute: 100% = number of levels

Definition at line 300 of file PGFimage.h.

00300 { m_progressMode = pm; }

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:
callback A refresh callback procedure
arg A parameter of the refresh callback procedure

Definition at line 307 of file PGFimage.h.

00307 { m_cb = callback; m_cbArg = arg; }

UINT32 CPGFImage::UpdatePostHeaderSize (  )  [private]

Definition at line 1067 of file PGFimage.cpp.

01067                                               {
01068         ASSERT(m_encoder);
01069 
01070         INT64 offset = m_encoder->ComputeOffset(); ASSERT(offset >= 0);
01071 
01072         if (offset > 0) {
01073                 // update post-header size and rewrite pre-header
01074                 m_preHeader.hSize += (UINT32)offset;
01075                 m_encoder->UpdatePostHeaderSize(m_preHeader);
01076         }
01077 
01078         // write dummy levelLength into stream
01079         return m_encoder->WriteLevelLength(m_levelLength);
01080 }

BYTE CPGFImage::UsedBitsPerChannel (  )  const

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 708 of file PGFimage.cpp.

00708                                          {
00709         const BYTE bpc = m_header.bpp/m_header.channels;
00710 
00711         if (bpc > 8) {
00712                 return m_header.usedBitsPerChannel;
00713         } else {
00714                 return bpc;
00715         }
00716 }

BYTE CPGFImage::Version (  )  const [inline]

Returns images' PGF version

Returns:
PGF codec version of the image

Definition at line 476 of file PGFimage.h.

00476 { return CurrentVersion(m_preHeader.version); }

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:
level A level
Returns:
Image level width in pixels

Definition at line 416 of file PGFimage.h.

00416 { 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 entire PGF image (header and 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(...)). It might throw an IOException.

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

Definition at line 1163 of file PGFimage.cpp.

01163                                                                                                                                   {
01164         ASSERT(stream);
01165         ASSERT(m_preHeader.hSize);
01166 
01167         // create wavelet transform channels and encoder
01168         UINT32 nBytes = WriteHeader(stream);
01169 
01170         // write image
01171         nBytes += WriteImage(stream, cb, data);
01172 
01173         // return written bytes
01174         if (nWrittenBytes) *nWrittenBytes += nBytes;
01175 }

UINT32 CPGFImage::WriteHeader ( CPGFStream stream  ) 

Create wavelet transform channels and encoder. Write header at current stream position. Call this method before your first call of Write(int level) or WriteImage(), but after SetHeader(). This method is called inside of Write(stream, ...). It might throw an IOException.

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

Definition at line 923 of file PGFimage.cpp.

00923                                                        {
00924         ASSERT(m_header.nLevels <= MaxLevel);
00925         ASSERT(m_header.quality <= MaxQuality); // quality is already initialized
00926 
00927         if (m_header.nLevels > 0) {
00928                 volatile OSError error = NoError; // volatile prevents optimizations
00929                 // create new wt channels
00930 #ifdef LIBPGF_USE_OPENMP
00931                 #pragma omp parallel for default(shared)
00932 #endif
00933                 for (int i=0; i < m_header.channels; i++) {
00934                         DataT *temp = NULL;
00935                         if (error == NoError) {
00936                                 if (m_wtChannel[i]) {
00937                                         ASSERT(m_channel[i]);
00938                                         // copy m_channel to temp
00939                                         int size = m_height[i]*m_width[i];
00940                                         temp = new(std::nothrow) DataT[size];
00941                                         if (temp) {
00942                                                 memcpy(temp, m_channel[i], size*DataTSize);
00943                                                 delete m_wtChannel[i];  // also deletes m_channel
00944                                                 m_channel[i] = NULL;
00945                                         } else {
00946                                                 error = InsufficientMemory;
00947                                         }
00948                                 }
00949                                 if (error == NoError) {
00950                                         if (temp) {
00951                                                 ASSERT(!m_channel[i]);
00952                                                 m_channel[i] = temp;
00953                                         }
00954                                         m_wtChannel[i] = new CWaveletTransform(m_width[i], m_height[i], m_header.nLevels, m_channel[i]);
00955                                         if (m_wtChannel[i]) {
00956                                         #ifdef __PGFROISUPPORT__
00957                                                 m_wtChannel[i]->SetROI(PGFRect(0, 0, m_width[i], m_height[i]));
00958                                         #endif
00959                                         
00960                                                 // wavelet subband decomposition 
00961                                                 for (int l=0; error == NoError && l < m_header.nLevels; l++) {
00962                                                         OSError err = m_wtChannel[i]->ForwardTransform(l, m_quant);
00963                                                         if (err != NoError) error = err;
00964                                                 }
00965                                         } else {
00966                                                 delete[] m_channel[i];
00967                                                 error = InsufficientMemory;
00968                                         }
00969                                 }
00970                         }
00971                 }
00972                 if (error != NoError) {
00973                         // free already allocated memory
00974                         for (int i=0; i < m_header.channels; i++) {
00975                                 delete m_wtChannel[i];
00976                         }
00977                         ReturnWithError(error);
00978                 }
00979 
00980                 m_currentLevel = m_header.nLevels;
00981 
00982                 // create encoder and eventually write headers and levelLength
00983                 m_encoder = new CEncoder(stream, m_preHeader, m_header, m_postHeader, m_userDataPos, m_useOMPinEncoder);
00984                 if (m_favorSpeedOverSize) m_encoder->FavorSpeedOverSize();
00985 
00986         #ifdef __PGFROISUPPORT__
00987                 if (ROIisSupported()) {
00988                         // new encoding scheme supporting ROI
00989                         m_encoder->SetROI();
00990                 }
00991         #endif
00992 
00993         } else {
00994                 // very small image: we don't use DWT and encoding
00995 
00996                 // create encoder and eventually write headers and levelLength
00997                 m_encoder = new CEncoder(stream, m_preHeader, m_header, m_postHeader, m_userDataPos, m_useOMPinEncoder);
00998         }
00999 
01000         INT64 nBytes = m_encoder->ComputeHeaderLength();
01001         return (nBytes > 0) ? (UINT32)nBytes : 0;
01002 }

UINT32 CPGFImage::WriteImage ( CPGFStream stream,
CallbackPtr  cb = NULL,
void *  data = NULL 
)

Encode and write the one and only image at current stream position. Call this method after WriteHeader(). In case you want to write uncached metadata, then do that after WriteHeader() and before WriteImage(). This method is called inside of Write(stream, ...). It might throw an IOException.

Parameters:
stream A PGF stream
cb A pointer to a callback procedure. The procedure is called after writing a single level. If cb returns true, then it stops proceeding.
data Data Pointer to C++ class container to host callback procedure.
Returns:
The number of bytes written into stream.

Definition at line 1092 of file PGFimage.cpp.

01092                                                                                                         {
01093         ASSERT(stream);
01094         ASSERT(m_preHeader.hSize);
01095 
01096         int levels = m_header.nLevels;
01097         double percent = pow(0.25, levels);
01098 
01099         // update post-header size, rewrite pre-header, and write dummy levelLength
01100         UINT32 nWrittenBytes = UpdatePostHeaderSize();
01101 
01102         if (levels == 0) {
01103                 // write channels
01104                 for (int c=0; c < m_header.channels; c++) {
01105                         const UINT32 size = m_width[c]*m_height[c];
01106 
01107                         // write channel data into stream
01108                         for (UINT32 i=0; i < size; i++) {
01109                                 int count = DataTSize;
01110                                 stream->Write(&count, &m_channel[c][i]);
01111                         }
01112                 }
01113 
01114                 // now update progress
01115                 if (cb) {
01116                         if ((*cb)(1, true, data)) ReturnWithError(EscapePressed);
01117                 }
01118 
01119         } else {
01120                 // encode quantized wavelet coefficients and write to PGF file
01121                 // encode subbands, higher levels first
01122                 // color channels are interleaved
01123 
01124                 // encode all levels
01125                 for (m_currentLevel = levels; m_currentLevel > 0; ) {
01126                         WriteLevel(); // decrements m_currentLevel
01127 
01128                         // now update progress
01129                         if (cb) {
01130                                 percent *= 4;
01131                                 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01132                         }
01133                 }
01134 
01135                 // flush encoder and write level lengths
01136                 m_encoder->Flush();
01137         }
01138 
01139         // update level lengths
01140         nWrittenBytes += m_encoder->UpdateLevelLength(); // return written image bytes 
01141 
01142         // delete encoder
01143         delete m_encoder; m_encoder = NULL;
01144 
01145         ASSERT(!m_encoder);
01146 
01147         return nWrittenBytes;
01148 }

void CPGFImage::WriteLevel (  )  [private]

Definition at line 1012 of file PGFimage.cpp.

01012                                   {
01013         ASSERT(m_encoder);
01014         ASSERT(m_currentLevel > 0);
01015         ASSERT(m_header.nLevels > 0);
01016 
01017 #ifdef __PGFROISUPPORT__
01018         if (ROIisSupported()) {
01019                 const int lastChannel = m_header.channels - 1;
01020 
01021                 for (int i=0; i < m_header.channels; i++) {
01022                         // get number of tiles and tile indices
01023                         const UINT32 nTiles = m_wtChannel[i]->GetNofTiles(m_currentLevel);
01024                         const UINT32 lastTile = nTiles - 1;
01025 
01026                         if (m_currentLevel == m_header.nLevels) {
01027                                 // last level also has LL band
01028                                 ASSERT(nTiles == 1);
01029                                 m_wtChannel[i]->GetSubband(m_currentLevel, LL)->ExtractTile(*m_encoder);
01030                                 m_encoder->EncodeTileBuffer();
01031                         }
01032                         for (UINT32 tileY=0; tileY < nTiles; tileY++) {
01033                                 for (UINT32 tileX=0; tileX < nTiles; tileX++) {
01034                                         m_wtChannel[i]->GetSubband(m_currentLevel, HL)->ExtractTile(*m_encoder, true, tileX, tileY);
01035                                         m_wtChannel[i]->GetSubband(m_currentLevel, LH)->ExtractTile(*m_encoder, true, tileX, tileY);
01036                                         m_wtChannel[i]->GetSubband(m_currentLevel, HH)->ExtractTile(*m_encoder, true, tileX, tileY);
01037                                         if (i == lastChannel && tileY == lastTile && tileX == lastTile) {
01038                                                 // all necessary data are buffered. next call of EncodeBuffer will write the last piece of data of the current level.
01039                                                 m_encoder->SetEncodedLevel(--m_currentLevel);
01040                                         }
01041                                         m_encoder->EncodeTileBuffer();
01042                                 }
01043                         }
01044                 }
01045         } else 
01046 #endif
01047         {
01048                 for (int i=0; i < m_header.channels; i++) {
01049                         ASSERT(m_wtChannel[i]);
01050                         if (m_currentLevel == m_header.nLevels) { 
01051                                 // last level also has LL band
01052                                 m_wtChannel[i]->GetSubband(m_currentLevel, LL)->ExtractTile(*m_encoder);
01053                         }
01054                         //encoder.EncodeInterleaved(m_wtChannel[i], m_currentLevel, m_quant); // until version 4
01055                         m_wtChannel[i]->GetSubband(m_currentLevel, HL)->ExtractTile(*m_encoder); // since version 5
01056                         m_wtChannel[i]->GetSubband(m_currentLevel, LH)->ExtractTile(*m_encoder); // since version 5
01057                         m_wtChannel[i]->GetSubband(m_currentLevel, HH)->ExtractTile(*m_encoder);
01058                 }
01059 
01060                 // all necessary data are buffered. next call of EncodeBuffer will write the last piece of data of the current level.
01061                 m_encoder->SetEncodedLevel(--m_currentLevel);
01062         }
01063 }


Member Data Documentation

pointer to refresh callback procedure

Definition at line 535 of file PGFimage.h.

void* CPGFImage::m_cbArg [private]

refresh callback argument

Definition at line 536 of file PGFimage.h.

DataT* CPGFImage::m_channel[MaxChannels] [protected]

untransformed channels in YUV format

Definition at line 512 of file PGFimage.h.

int CPGFImage::m_currentLevel [protected]

transform level of current image

Definition at line 522 of file PGFimage.h.

PGF decoder.

Definition at line 513 of file PGFimage.h.

bool CPGFImage::m_downsample [protected]

chrominance channels are downsampled

Definition at line 524 of file PGFimage.h.

PGF encoder.

Definition at line 514 of file PGFimage.h.

favor encoding speed over compression ratio

Definition at line 525 of file PGFimage.h.

PGF file header.

Definition at line 519 of file PGFimage.h.

UINT32 CPGFImage::m_height[MaxChannels] [protected]

height of each channel at current level

Definition at line 517 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 515 of file PGFimage.h.

double CPGFImage::m_percent [private]

progress [0..1]

Definition at line 537 of file PGFimage.h.

PGF post-header.

Definition at line 520 of file PGFimage.h.

PGF pre-header.

Definition at line 518 of file PGFimage.h.

progress mode used in Read and Write; PM_Relative is default mode

Definition at line 538 of file PGFimage.h.

BYTE CPGFImage::m_quant [protected]

quantization parameter

Definition at line 523 of file PGFimage.h.

bool CPGFImage::m_skipUserData [protected]

skip user data (metadata) during open

Definition at line 528 of file PGFimage.h.

bool CPGFImage::m_useOMPinDecoder [protected]

use Open MP in decoder

Definition at line 527 of file PGFimage.h.

bool CPGFImage::m_useOMPinEncoder [protected]

use Open MP in encoder

Definition at line 526 of file PGFimage.h.

UINT64 CPGFImage::m_userDataPos [protected]

stream position of user data

Definition at line 521 of file PGFimage.h.

UINT32 CPGFImage::m_width[MaxChannels] [protected]

width of each channel at current level

Definition at line 516 of file PGFimage.h.

CWaveletTransform* CPGFImage::m_wtChannel[MaxChannels] [protected]

wavelet transformed color channels

Definition at line 511 of file PGFimage.h.


The documentation for this class was generated from the following files:

Generated on 18 Feb 2019 for libpgf by  doxygen 1.6.1