libpgf  6.14.12
PGF - Progressive Graphics File
CPGFImage Class Reference

PGF main class. More...

#include <PGFimage.h>

Public Member Functions

 CPGFImage ()
 Standard constructor: It is used to create a PGF instance for opening and reading. More...
 
virtual ~CPGFImage ()
 Destructor: Destroy internal data structures. More...
 
virtual void Close ()
 
virtual void Destroy ()
 
void Open (CPGFStream *stream) THROW_
 
bool IsOpen () const
 Returns true if the PGF has been opened and not closed. More...
 
void Read (int level=0, CallbackPtr cb=NULL, void *data=NULL) THROW_
 
void Read (PGFRect &rect, int level=0, CallbackPtr cb=NULL, void *data=NULL) THROW_
 
void ReadPreview () THROW_
 
void Reconstruct (int level=0) THROW_
 
void GetBitmap (int pitch, UINT8 *buff, BYTE bpp, int channelMap[]=NULL, CallbackPtr cb=NULL, void *data=NULL) const THROW_
 
void GetYUV (int pitch, DataT *buff, BYTE bpp, int channelMap[]=NULL, CallbackPtr cb=NULL, void *data=NULL) const THROW_
 
void ImportBitmap (int pitch, UINT8 *buff, BYTE bpp, int channelMap[]=NULL, CallbackPtr cb=NULL, void *data=NULL) THROW_
 
void ImportYUV (int pitch, DataT *buff, BYTE bpp, int channelMap[]=NULL, CallbackPtr cb=NULL, void *data=NULL) THROW_
 
void Write (CPGFStream *stream, UINT32 *nWrittenBytes=NULL, CallbackPtr cb=NULL, void *data=NULL) THROW_
 
UINT32 WriteHeader (CPGFStream *stream) THROW_
 
UINT32 WriteImage (CPGFStream *stream, CallbackPtr cb=NULL, void *data=NULL) THROW_
 
UINT32 Write (int level, CallbackPtr cb=NULL, void *data=NULL) THROW_
 
void ConfigureEncoder (bool useOMP=true, bool favorSpeedOverSize=false)
 
void ConfigureDecoder (bool useOMP=true, bool skipUserData=false)
 
void ResetStreamPos () THROW_
 Reset stream position to start of PGF pre-header. More...
 
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)
 Return version. More...
 
static BYTE CurrentChannelDepth (BYTE version=PGFVersion)
 

Protected Attributes

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

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_
 
void SetROI (PGFRect rect)
 
UINT8 Clamp4 (DataT v) const
 
UINT16 Clamp6 (DataT v) const
 
UINT8 Clamp8 (DataT v) const
 
UINT16 Clamp16 (DataT v) const
 
UINT32 Clamp31 (DataT v) const
 

Private Attributes

RefreshCB m_cb
 pointer to refresh callback procedure More...
 
void * m_cbArg
 refresh callback argument More...
 
double m_percent
 progress [0..1] More...
 
ProgressMode m_progressMode
 progress mode used in Read and Write; PM_Relative is default mode More...
 

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::CPGFImage ( )

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

Definition at line 55 of file PGFimage.cpp.

56 : m_decoder(0)
57 , m_encoder(0)
58 , m_levelLength(0)
59 , m_currentLevel(0)
60 , m_quant(0)
61 , m_userDataPos(0)
62 , m_downsample(false)
63 , m_favorSpeedOverSize(false)
64 , m_useOMPinEncoder(true)
65 , m_useOMPinDecoder(true)
66 , m_skipUserData(false)
67 #ifdef __PGFROISUPPORT__
68 , m_streamReinitialized(false)
69 #endif
70 , m_cb(0)
71 , m_cbArg(0)
73 , m_percent(0)
74 {
75 
76  // init preHeader
77  memcpy(m_preHeader.magic, PGFMagic, 3);
79  m_preHeader.hSize = 0;
80 
81  // init postHeader
84 
85  // init channels
86  for (int i=0; i < MaxChannels; i++) {
87  m_channel[i] = 0;
88  m_wtChannel[i] = 0;
89  }
90 
91  // set image width and height
92  m_width[0] = 0;
93  m_height[0] = 0;
94 }
@ PM_Relative
Definition: PGFimage.h:36
#define PGFMagic
PGF identification.
Definition: PGFtypes.h:55
#define MaxChannels
maximum number of (color) channels
Definition: PGFtypes.h:58
#define PGFVersion
current standard version
Definition: PGFtypes.h:69
bool m_useOMPinDecoder
use Open MP in decoder
Definition: PGFimage.h:527
CDecoder * m_decoder
PGF decoder.
Definition: PGFimage.h:513
bool m_useOMPinEncoder
use Open MP in encoder
Definition: PGFimage.h:526
UINT32 * m_levelLength
length of each level in bytes; first level starts immediately after this array
Definition: PGFimage.h:515
UINT32 m_height[MaxChannels]
height of each channel at current level
Definition: PGFimage.h:517
int m_currentLevel
transform level of current image
Definition: PGFimage.h:522
DataT * m_channel[MaxChannels]
untransformed channels in YUV format
Definition: PGFimage.h:512
void * m_cbArg
refresh callback argument
Definition: PGFimage.h:536
BYTE m_quant
quantization parameter
Definition: PGFimage.h:523
bool m_favorSpeedOverSize
favor encoding speed over compression ratio
Definition: PGFimage.h:525
CEncoder * m_encoder
PGF encoder.
Definition: PGFimage.h:514
ProgressMode m_progressMode
progress mode used in Read and Write; PM_Relative is default mode
Definition: PGFimage.h:538
bool m_downsample
chrominance channels are downsampled
Definition: PGFimage.h:524
UINT32 m_width[MaxChannels]
width of each channel at current level
Definition: PGFimage.h:516
PGFPostHeader m_postHeader
PGF post-header.
Definition: PGFimage.h:520
RefreshCB m_cb
pointer to refresh callback procedure
Definition: PGFimage.h:535
UINT64 m_userDataPos
stream position of user data
Definition: PGFimage.h:521
bool m_skipUserData
skip user data (metadata) during open
Definition: PGFimage.h:528
PGFPreHeader m_preHeader
PGF pre-header.
Definition: PGFimage.h:518
double m_percent
progress [0..1]
Definition: PGFimage.h:537
CWaveletTransform * m_wtChannel[MaxChannels]
wavelet transformed color channels
Definition: PGFimage.h:511
bool m_streamReinitialized
stream has been reinitialized
Definition: PGFimage.h:530
char magic[3]
PGF identification = "PGF".
Definition: PGFtypes.h:105
UINT8 version
PGF version.
Definition: PGFtypes.h:106
UINT32 userDataLen
user data size in bytes
Definition: PGFtypes.h:144
UINT8 * userData
user data of size userDataLen
Definition: PGFtypes.h:143
UINT32 hSize
total size of PGFHeader, [ColorTable], and [UserData] in bytes
Definition: PGFtypes.h:115

◆ ~CPGFImage()

CPGFImage::~CPGFImage ( )
virtual

Destructor: Destroy internal data structures.

Definition at line 98 of file PGFimage.cpp.

98  {
99  Destroy();
100 }
virtual void Destroy()
Definition: PGFimage.cpp:105

Member Function Documentation

◆ BPP()

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.

460 { return m_header.bpp; }
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:519
UINT8 bpp
bits per pixel
Definition: PGFtypes.h:129

◆ ChannelDepth()

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.

static BYTE CurrentChannelDepth(BYTE version=PGFVersion)
Definition: PGFimage.h:508

◆ ChannelHeight()

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

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

Parameters
cA channel index
Returns
Channel height in pixels

Definition at line 404 of file PGFimage.h.

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

◆ Channels()

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.

447 { return m_header.channels; }
UINT8 channels
number of channels
Definition: PGFtypes.h:130

◆ ChannelWidth()

UINT32 CPGFImage::ChannelWidth ( int  c = 0) const
inline

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

Parameters
cA channel index
Returns
Channel width in pixels

Definition at line 397 of file PGFimage.h.

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

◆ Clamp16()

UINT16 CPGFImage::Clamp16 ( DataT  v) const
inlineprivate

Definition at line 561 of file PGFimage.h.

561  {
562  if (v & 0xFFFF0000) return (v < 0) ? (UINT16)0: (UINT16)65535; else return (UINT16)v;
563  }

◆ Clamp31()

UINT32 CPGFImage::Clamp31 ( DataT  v) const
inlineprivate

Definition at line 564 of file PGFimage.h.

564  {
565  return (v < 0) ? 0 : (UINT32)v;
566  }

◆ Clamp4()

UINT8 CPGFImage::Clamp4 ( DataT  v) const
inlineprivate

Definition at line 551 of file PGFimage.h.

551  {
552  if (v & 0xFFFFFFF0) return (v < 0) ? (UINT8)0: (UINT8)15; else return (UINT8)v;
553  }

◆ Clamp6()

UINT16 CPGFImage::Clamp6 ( DataT  v) const
inlineprivate

Definition at line 554 of file PGFimage.h.

554  {
555  if (v & 0xFFFFFFC0) return (v < 0) ? (UINT16)0: (UINT16)63; else return (UINT16)v;
556  }

◆ Clamp8()

UINT8 CPGFImage::Clamp8 ( DataT  v) const
inlineprivate

Definition at line 557 of file PGFimage.h.

557  {
558  // needs only one test in the normal case
559  if (v & 0xFFFFFF00) return (v < 0) ? (UINT8)0 : (UINT8)255; else return (UINT8)v;
560  }

◆ Close()

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.

122  {
123  delete m_decoder; m_decoder = 0;
124 }

◆ CompleteHeader()

bool CPGFImage::CompleteHeader ( )
private

Definition at line 208 of file PGFimage.cpp.

208  {
209  if (m_header.mode == ImageModeUnknown) {
210  // undefined mode
211  switch(m_header.bpp) {
212  case 1: m_header.mode = ImageModeBitmap; break;
213  case 8: m_header.mode = ImageModeGrayScale; break;
214  case 12: m_header.mode = ImageModeRGB12; break;
215  case 16: m_header.mode = ImageModeRGB16; break;
216  case 24: m_header.mode = ImageModeRGBColor; break;
217  case 32: m_header.mode = ImageModeRGBA; break;
218  case 48: m_header.mode = ImageModeRGB48; break;
219  default: m_header.mode = ImageModeRGBColor; break;
220  }
221  }
222  if (!m_header.bpp) {
223  // undefined bpp
224  switch(m_header.mode) {
225  case ImageModeBitmap:
226  m_header.bpp = 1;
227  break;
229  case ImageModeGrayScale:
230  m_header.bpp = 8;
231  break;
232  case ImageModeRGB12:
233  m_header.bpp = 12;
234  break;
235  case ImageModeRGB16:
236  case ImageModeGray16:
237  m_header.bpp = 16;
238  break;
239  case ImageModeRGBColor:
240  case ImageModeLabColor:
241  m_header.bpp = 24;
242  break;
243  case ImageModeRGBA:
244  case ImageModeCMYKColor:
245  case ImageModeGray32:
246  m_header.bpp = 32;
247  break;
248  case ImageModeRGB48:
249  case ImageModeLab48:
250  m_header.bpp = 48;
251  break;
252  case ImageModeCMYK64:
253  m_header.bpp = 64;
254  break;
255  default:
256  ASSERT(false);
257  m_header.bpp = 24;
258  }
259  }
260  if (m_header.mode == ImageModeRGBColor && m_header.bpp == 32) {
261  // change mode
263  }
264 
265  if (m_header.mode == ImageModeBitmap && m_header.bpp != 1) return false;
266  if (m_header.mode == ImageModeIndexedColor && m_header.bpp != 8) return false;
267  if (m_header.mode == ImageModeGrayScale && m_header.bpp != 8) return false;
268  if (m_header.mode == ImageModeGray16 && m_header.bpp != 16) return false;
269  if (m_header.mode == ImageModeGray32 && m_header.bpp != 32) return false;
270  if (m_header.mode == ImageModeRGBColor && m_header.bpp != 24) return false;
271  if (m_header.mode == ImageModeRGBA && m_header.bpp != 32) return false;
272  if (m_header.mode == ImageModeRGB12 && m_header.bpp != 12) return false;
273  if (m_header.mode == ImageModeRGB16 && m_header.bpp != 16) return false;
274  if (m_header.mode == ImageModeRGB48 && m_header.bpp != 48) return false;
275  if (m_header.mode == ImageModeLabColor && m_header.bpp != 24) return false;
276  if (m_header.mode == ImageModeLab48 && m_header.bpp != 48) return false;
277  if (m_header.mode == ImageModeCMYKColor && m_header.bpp != 32) return false;
278  if (m_header.mode == ImageModeCMYK64 && m_header.bpp != 64) return false;
279 
280  // set number of channels
281  if (!m_header.channels) {
282  switch(m_header.mode) {
283  case ImageModeBitmap:
285  case ImageModeGrayScale:
286  case ImageModeGray16:
287  case ImageModeGray32:
288  m_header.channels = 1;
289  break;
290  case ImageModeRGBColor:
291  case ImageModeRGB12:
292  case ImageModeRGB16:
293  case ImageModeRGB48:
294  case ImageModeLabColor:
295  case ImageModeLab48:
296  m_header.channels = 3;
297  break;
298  case ImageModeRGBA:
299  case ImageModeCMYKColor:
300  case ImageModeCMYK64:
301  m_header.channels = 4;
302  break;
303  default:
304  return false;
305  }
306  }
307 
308  // store used bits per channel
309  UINT8 bpc = m_header.bpp/m_header.channels;
310  if (bpc > 31) bpc = 31;
313  }
314 
315  return true;
316 }
#define ImageModeRGBColor
Definition: PGFplatform.h:101
#define ImageModeRGB12
Definition: PGFplatform.h:117
#define ImageModeGray32
Definition: PGFplatform.h:116
#define ImageModeUnknown
Definition: PGFplatform.h:119
#define ImageModeBitmap
Definition: PGFplatform.h:98
#define ImageModeLabColor
Definition: PGFplatform.h:107
#define ImageModeRGB16
Definition: PGFplatform.h:118
#define ImageModeRGBA
Definition: PGFplatform.h:115
#define ImageModeRGB48
Definition: PGFplatform.h:109
#define ImageModeCMYK64
Definition: PGFplatform.h:111
#define ImageModeGrayScale
Definition: PGFplatform.h:99
#define ImageModeLab48
Definition: PGFplatform.h:110
#define ImageModeGray16
Definition: PGFplatform.h:108
#define ImageModeIndexedColor
Definition: PGFplatform.h:100
#define ImageModeCMYKColor
Definition: PGFplatform.h:102
UINT8 mode
image mode according to Adobe's image modes
Definition: PGFtypes.h:131
UINT8 usedBitsPerChannel
number of used bits per channel in 16- and 32-bit per channel modes
Definition: PGFtypes.h:132

◆ ComputeLevels()

void CPGFImage::ComputeLevels ( )
private

Definition at line 805 of file PGFimage.cpp.

805  {
806  const int maxThumbnailWidth = 20*FilterWidth;
807  const int m = __min(m_header.width, m_header.height);
808  int s = m;
809 
810  if (m_header.nLevels < 1 || m_header.nLevels > MaxLevel) {
811  m_header.nLevels = 1;
812  // compute a good value depending on the size of the image
813  while (s > maxThumbnailWidth) {
814  m_header.nLevels++;
815  s = s/2;
816  }
817  }
818 
819  int levels = m_header.nLevels; // we need a signed value during level reduction
820 
821  // reduce number of levels if the image size is smaller than FilterWidth*2^levels
822  s = FilterWidth*(1 << levels); // must be at least the double filter size because of subsampling
823  while (m < s) {
824  levels--;
825  s = s/2;
826  }
827  if (levels > MaxLevel) m_header.nLevels = MaxLevel;
828  else if (levels < 0) m_header.nLevels = 0;
829  else m_header.nLevels = (UINT8)levels;
830 
831  // used in Write when PM_Absolute
832  m_percent = pow(0.25, m_header.nLevels);
833 
834  ASSERT(0 <= m_header.nLevels && m_header.nLevels <= MaxLevel);
835 }
#define __min(x, y)
Definition: PGFplatform.h:91
#define MaxLevel
maximum number of transform levels
Definition: PGFtypes.h:56
#define FilterWidth
number of coefficients of the row wavelet filter
UINT32 height
image height in pixels
Definition: PGFtypes.h:126
UINT32 width
image width in pixels
Definition: PGFtypes.h:125
UINT8 nLevels
number of DWT levels
Definition: PGFtypes.h:127

◆ ConfigureDecoder()

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

Configures the decoder.

Parameters
useOMPUse parallel threading with Open MP during decoding. Default value: true. Influences the decoding only if the codec has been compiled with OpenMP support.
skipUserDataThe 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.

266 { m_useOMPinDecoder = useOMP; m_skipUserData = skipUserData; }

◆ ConfigureEncoder()

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

Configures the encoder.

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

Definition at line 260 of file PGFimage.h.

260 { m_useOMPinEncoder = useOMP; m_favorSpeedOverSize = favorSpeedOverSize; }

◆ CurrentChannelDepth()

static BYTE CPGFImage::CurrentChannelDepth ( BYTE  version = PGFVersion)
inlinestatic

Compute and return codec version.

Returns
current PGF codec version

Definition at line 508 of file PGFimage.h.

508 { return (version & PGF32) ? 32 : 16; }
#define PGF32
32 bit values are used -> allows at maximum 31 bits, otherwise 16 bit values are used -> allows at ma...
Definition: PGFtypes.h:63

◆ CurrentVersion()

BYTE CPGFImage::CurrentVersion ( BYTE  version = PGFVersion)
static

Return version.

Compute and return codec version.

Returns
current PGF codec version

Definition at line 721 of file PGFimage.cpp.

721  {
722  if (version & Version6) return 6;
723  if (version & Version5) return 5;
724  if (version & Version2) return 2;
725  return 1;
726 }
#define Version5
new coding scheme since major version 5
Definition: PGFtypes.h:65
#define Version2
data structure PGFHeader of major version 2
Definition: PGFtypes.h:62
#define Version6
new HeaderSize: 32 bits instead of 16 bits
Definition: PGFtypes.h:66

◆ Destroy()

void CPGFImage::Destroy ( )
virtual

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

Definition at line 105 of file PGFimage.cpp.

105  {
106  Close();
107 
108  for (int i=0; i < m_header.channels; i++) {
109  delete m_wtChannel[i]; m_wtChannel[i]=0; // also deletes m_channel
110  m_channel[i] = 0;
111  }
113  delete[] m_levelLength; m_levelLength = 0;
114  delete m_encoder; m_encoder = NULL;
115 
116  m_userDataPos = 0;
117 }
virtual void Close()
Definition: PGFimage.cpp:122

◆ Downsample()

void CPGFImage::Downsample ( int  nChannel)
private

Definition at line 761 of file PGFimage.cpp.

761  {
762  ASSERT(ch > 0);
763 
764  const int w = m_width[0];
765  const int w2 = w/2;
766  const int h2 = m_height[0]/2;
767  const int oddW = w%2; // don't use bool -> problems with MaxSpeed optimization
768  const int oddH = m_height[0]%2; // "
769  int loPos = 0;
770  int hiPos = w;
771  int sampledPos = 0;
772  DataT* buff = m_channel[ch]; ASSERT(buff);
773 
774  for (int i=0; i < h2; i++) {
775  for (int j=0; j < w2; j++) {
776  // compute average of pixel block
777  buff[sampledPos] = (buff[loPos] + buff[loPos + 1] + buff[hiPos] + buff[hiPos + 1]) >> 2;
778  loPos += 2; hiPos += 2;
779  sampledPos++;
780  }
781  if (oddW) {
782  buff[sampledPos] = (buff[loPos] + buff[hiPos]) >> 1;
783  loPos++; hiPos++;
784  sampledPos++;
785  }
786  loPos += w; hiPos += w;
787  }
788  if (oddH) {
789  for (int j=0; j < w2; j++) {
790  buff[sampledPos] = (buff[loPos] + buff[loPos+1]) >> 1;
791  loPos += 2; hiPos += 2;
792  sampledPos++;
793  }
794  if (oddW) {
795  buff[sampledPos] = buff[loPos];
796  }
797  }
798 
799  // downsampled image has half width and half height
800  m_width[ch] = (m_width[ch] + 1)/2;
801  m_height[ch] = (m_height[ch] + 1)/2;
802 }
INT32 DataT
Definition: PGFtypes.h:219

◆ GetBitmap()

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

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

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

Definition at line 1721 of file PGFimage.cpp.

1721  {
1722  ASSERT(buff);
1723  UINT32 w = m_width[0];
1724  UINT32 h = m_height[0];
1725  UINT8* targetBuff = 0; // used if ROI is used
1726  UINT8* buffStart = 0; // used if ROI is used
1727  int targetPitch = 0; // used if ROI is used
1728 
1729 #ifdef __PGFROISUPPORT__
1730  const PGFRect& roi = (ROIisSupported()) ? m_wtChannel[0]->GetROI(m_currentLevel) : PGFRect(0, 0, w, h); // roi is usually larger than m_roi
1732  ASSERT(w <= roi.Width() && h <= roi.Height());
1733  ASSERT(roi.left <= levelRoi.left && levelRoi.right <= roi.right);
1734  ASSERT(roi.top <= levelRoi.top && levelRoi.bottom <= roi.bottom);
1735 
1736  if (ROIisSupported() && (levelRoi.Width() < w || levelRoi.Height() < h)) {
1737  // ROI is used -> create a temporary image buffer for roi
1738  // compute pitch
1739  targetPitch = pitch;
1740  pitch = AlignWordPos(w*bpp)/8;
1741 
1742  // create temporary output buffer
1743  targetBuff = buff;
1744  buff = buffStart = new(std::nothrow) UINT8[pitch*h];
1745  if (!buff) ReturnWithError(InsufficientMemory);
1746  }
1747 #endif
1748 
1749  const bool wOdd = (1 == w%2);
1750 
1751  const double dP = 1.0/h;
1752  int defMap[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; ASSERT(sizeof(defMap)/sizeof(defMap[0]) == MaxChannels);
1753  if (channelMap == NULL) channelMap = defMap;
1754  int sampledPos = 0, yPos = 0;
1755  DataT uAvg, vAvg;
1756  double percent = 0;
1757  UINT32 i, j;
1758 
1759  switch(m_header.mode) {
1760  case ImageModeBitmap:
1761  {
1762  ASSERT(m_header.channels == 1);
1763  ASSERT(m_header.bpp == 1);
1764  ASSERT(bpp == 1);
1765 
1766  const UINT32 w2 = (w + 7)/8;
1767  DataT* y = m_channel[0]; ASSERT(y);
1768 
1769  for (i=0; i < h; i++) {
1770 
1771  for (j=0; j < w2; j++) {
1772  buff[j] = Clamp8(y[yPos++] + YUVoffset8);
1773  }
1774  yPos += w - w2;
1775 
1776  //UINT32 cnt = w;
1777  //for (j=0; j < w2; j++) {
1778  // buff[j] = 0;
1779  // for (int k=0; k < 8; k++) {
1780  // if (cnt) {
1781  // buff[j] <<= 1;
1782  // buff[j] |= (1 & (y[yPos++] - YUVoffset8));
1783  // cnt--;
1784  // }
1785  // }
1786  //}
1787  buff += pitch;
1788 
1789  if (cb) {
1790  percent += dP;
1791  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1792  }
1793  }
1794  break;
1795  }
1796  case ImageModeIndexedColor:
1797  case ImageModeGrayScale:
1798  case ImageModeHSLColor:
1799  case ImageModeHSBColor:
1800  {
1801  ASSERT(m_header.channels >= 1);
1802  ASSERT(m_header.bpp == m_header.channels*8);
1803  ASSERT(bpp%8 == 0);
1804 
1805  int cnt, channels = bpp/8; ASSERT(channels >= m_header.channels);
1806 
1807  for (i=0; i < h; i++) {
1808  cnt = 0;
1809  for (j=0; j < w; j++) {
1810  for (int c=0; c < m_header.channels; c++) {
1811  buff[cnt + channelMap[c]] = Clamp8(m_channel[c][yPos] + YUVoffset8);
1812  }
1813  cnt += channels;
1814  yPos++;
1815  }
1816  buff += pitch;
1817 
1818  if (cb) {
1819  percent += dP;
1820  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1821  }
1822  }
1823  break;
1824  }
1825  case ImageModeGray16:
1826  {
1827  ASSERT(m_header.channels >= 1);
1828  ASSERT(m_header.bpp == m_header.channels*16);
1829 
1830  const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
1831  int cnt, channels;
1832 
1833  if (bpp%16 == 0) {
1834  const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
1835  UINT16 *buff16 = (UINT16 *)buff;
1836  int pitch16 = pitch/2;
1837  channels = bpp/16; ASSERT(channels >= m_header.channels);
1838 
1839  for (i=0; i < h; i++) {
1840  cnt = 0;
1841  for (j=0; j < w; j++) {
1842  for (int c=0; c < m_header.channels; c++) {
1843  buff16[cnt + channelMap[c]] = Clamp16((m_channel[c][yPos] + yuvOffset16) << shift);
1844  }
1845  cnt += channels;
1846  yPos++;
1847  }
1848  buff16 += pitch16;
1849 
1850  if (cb) {
1851  percent += dP;
1852  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1853  }
1854  }
1855  } else {
1856  ASSERT(bpp%8 == 0);
1857  const int shift = __max(0, UsedBitsPerChannel() - 8);
1858  channels = bpp/8; ASSERT(channels >= m_header.channels);
1859 
1860  for (i=0; i < h; i++) {
1861  cnt = 0;
1862  for (j=0; j < w; j++) {
1863  for (int c=0; c < m_header.channels; c++) {
1864  buff[cnt + channelMap[c]] = Clamp8((m_channel[c][yPos] + yuvOffset16) >> shift);
1865  }
1866  cnt += channels;
1867  yPos++;
1868  }
1869  buff += pitch;
1870 
1871  if (cb) {
1872  percent += dP;
1873  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1874  }
1875  }
1876  }
1877  break;
1878  }
1879  case ImageModeRGBColor:
1880  {
1881  ASSERT(m_header.channels == 3);
1882  ASSERT(m_header.bpp == m_header.channels*8);
1883  ASSERT(bpp%8 == 0);
1884  ASSERT(bpp >= m_header.bpp);
1885 
1886  DataT* y = m_channel[0]; ASSERT(y);
1887  DataT* u = m_channel[1]; ASSERT(u);
1888  DataT* v = m_channel[2]; ASSERT(v);
1889  UINT8 *buffg = &buff[channelMap[1]],
1890  *buffr = &buff[channelMap[2]],
1891  *buffb = &buff[channelMap[0]];
1892  UINT8 g;
1893  int cnt, channels = bpp/8;
1894  if(m_downsample){
1895  for (i=0; i < h; i++) {
1896  if (i%2) sampledPos -= (w + 1)/2;
1897  cnt = 0;
1898  for (j=0; j < w; j++) {
1899  // image was downsampled
1900  uAvg = u[sampledPos];
1901  vAvg = v[sampledPos];
1902  // Yuv
1903  buffg[cnt] = g = Clamp8(y[yPos] + YUVoffset8 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
1904  buffr[cnt] = Clamp8(uAvg + g);
1905  buffb[cnt] = Clamp8(vAvg + g);
1906  yPos++;
1907  cnt += channels;
1908  if (j%2) sampledPos++;
1909  }
1910  buffb += pitch;
1911  buffg += pitch;
1912  buffr += pitch;
1913  if (wOdd) sampledPos++;
1914  if (cb) {
1915  percent += dP;
1916  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1917  }
1918  }
1919  }else{
1920  for (i=0; i < h; i++) {
1921  cnt = 0;
1922  for (j = 0; j < w; j++) {
1923  uAvg = u[yPos];
1924  vAvg = v[yPos];
1925  // Yuv
1926  buffg[cnt] = g = Clamp8(y[yPos] + YUVoffset8 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
1927  buffr[cnt] = Clamp8(uAvg + g);
1928  buffb[cnt] = Clamp8(vAvg + g);
1929  yPos++;
1930  cnt += channels;
1931  }
1932  buffb += pitch;
1933  buffg += pitch;
1934  buffr += pitch;
1935 
1936  if (cb) {
1937  percent += dP;
1938  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1939  }
1940  }
1941  }
1942  break;
1943  }
1944  case ImageModeRGB48:
1945  {
1946  ASSERT(m_header.channels == 3);
1947  ASSERT(m_header.bpp == 48);
1948 
1949  const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
1950 
1951  DataT* y = m_channel[0]; ASSERT(y);
1952  DataT* u = m_channel[1]; ASSERT(u);
1953  DataT* v = m_channel[2]; ASSERT(v);
1954  int cnt, channels;
1955  DataT g;
1956 
1957  if (bpp >= 48 && bpp%16 == 0) {
1958  const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
1959  UINT16 *buff16 = (UINT16 *)buff;
1960  int pitch16 = pitch/2;
1961  channels = bpp/16; ASSERT(channels >= m_header.channels);
1962 
1963  for (i=0; i < h; i++) {
1964  if (i%2) sampledPos -= (w + 1)/2;
1965  cnt = 0;
1966  for (j=0; j < w; j++) {
1967  if (m_downsample) {
1968  // image was downsampled
1969  uAvg = u[sampledPos];
1970  vAvg = v[sampledPos];
1971  } else {
1972  uAvg = u[yPos];
1973  vAvg = v[yPos];
1974  }
1975  // Yuv
1976  g = y[yPos] + yuvOffset16 - ((uAvg + vAvg ) >> 2); // must be logical shift operator
1977  buff16[cnt + channelMap[1]] = Clamp16(g << shift);
1978  buff16[cnt + channelMap[2]] = Clamp16((uAvg + g) << shift);
1979  buff16[cnt + channelMap[0]] = Clamp16((vAvg + g) << shift);
1980  yPos++;
1981  cnt += channels;
1982  if (j%2) sampledPos++;
1983  }
1984  buff16 += pitch16;
1985  if (wOdd) sampledPos++;
1986 
1987  if (cb) {
1988  percent += dP;
1989  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1990  }
1991  }
1992  } else {
1993  ASSERT(bpp%8 == 0);
1994  const int shift = __max(0, UsedBitsPerChannel() - 8);
1995  channels = bpp/8; ASSERT(channels >= m_header.channels);
1996 
1997  for (i=0; i < h; i++) {
1998  if (i%2) sampledPos -= (w + 1)/2;
1999  cnt = 0;
2000  for (j=0; j < w; j++) {
2001  if (m_downsample) {
2002  // image was downsampled
2003  uAvg = u[sampledPos];
2004  vAvg = v[sampledPos];
2005  } else {
2006  uAvg = u[yPos];
2007  vAvg = v[yPos];
2008  }
2009  // Yuv
2010  g = y[yPos] + yuvOffset16 - ((uAvg + vAvg ) >> 2); // must be logical shift operator
2011  buff[cnt + channelMap[1]] = Clamp8(g >> shift);
2012  buff[cnt + channelMap[2]] = Clamp8((uAvg + g) >> shift);
2013  buff[cnt + channelMap[0]] = Clamp8((vAvg + g) >> shift);
2014  yPos++;
2015  cnt += channels;
2016  if (j%2) sampledPos++;
2017  }
2018  buff += pitch;
2019  if (wOdd) sampledPos++;
2020 
2021  if (cb) {
2022  percent += dP;
2023  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2024  }
2025  }
2026  }
2027  break;
2028  }
2029  case ImageModeLabColor:
2030  {
2031  ASSERT(m_header.channels == 3);
2032  ASSERT(m_header.bpp == m_header.channels*8);
2033  ASSERT(bpp%8 == 0);
2034 
2035  DataT* l = m_channel[0]; ASSERT(l);
2036  DataT* a = m_channel[1]; ASSERT(a);
2037  DataT* b = m_channel[2]; ASSERT(b);
2038  int cnt, channels = bpp/8; ASSERT(channels >= m_header.channels);
2039 
2040  for (i=0; i < h; i++) {
2041  if (i%2) sampledPos -= (w + 1)/2;
2042  cnt = 0;
2043  for (j=0; j < w; j++) {
2044  if (m_downsample) {
2045  // image was downsampled
2046  uAvg = a[sampledPos];
2047  vAvg = b[sampledPos];
2048  } else {
2049  uAvg = a[yPos];
2050  vAvg = b[yPos];
2051  }
2052  buff[cnt + channelMap[0]] = Clamp8(l[yPos] + YUVoffset8);
2053  buff[cnt + channelMap[1]] = Clamp8(uAvg + YUVoffset8);
2054  buff[cnt + channelMap[2]] = Clamp8(vAvg + YUVoffset8);
2055  cnt += channels;
2056  yPos++;
2057  if (j%2) sampledPos++;
2058  }
2059  buff += pitch;
2060  if (wOdd) sampledPos++;
2061 
2062  if (cb) {
2063  percent += dP;
2064  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2065  }
2066  }
2067  break;
2068  }
2069  case ImageModeLab48:
2070  {
2071  ASSERT(m_header.channels == 3);
2072  ASSERT(m_header.bpp == m_header.channels*16);
2073 
2074  const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
2075 
2076  DataT* l = m_channel[0]; ASSERT(l);
2077  DataT* a = m_channel[1]; ASSERT(a);
2078  DataT* b = m_channel[2]; ASSERT(b);
2079  int cnt, channels;
2080 
2081  if (bpp%16 == 0) {
2082  const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
2083  UINT16 *buff16 = (UINT16 *)buff;
2084  int pitch16 = pitch/2;
2085  channels = bpp/16; ASSERT(channels >= m_header.channels);
2086 
2087  for (i=0; i < h; i++) {
2088  if (i%2) sampledPos -= (w + 1)/2;
2089  cnt = 0;
2090  for (j=0; j < w; j++) {
2091  if (m_downsample) {
2092  // image was downsampled
2093  uAvg = a[sampledPos];
2094  vAvg = b[sampledPos];
2095  } else {
2096  uAvg = a[yPos];
2097  vAvg = b[yPos];
2098  }
2099  buff16[cnt + channelMap[0]] = Clamp16((l[yPos] + yuvOffset16) << shift);
2100  buff16[cnt + channelMap[1]] = Clamp16((uAvg + yuvOffset16) << shift);
2101  buff16[cnt + channelMap[2]] = Clamp16((vAvg + yuvOffset16) << shift);
2102  cnt += channels;
2103  yPos++;
2104  if (j%2) sampledPos++;
2105  }
2106  buff16 += pitch16;
2107  if (wOdd) sampledPos++;
2108 
2109  if (cb) {
2110  percent += dP;
2111  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2112  }
2113  }
2114  } else {
2115  ASSERT(bpp%8 == 0);
2116  const int shift = __max(0, UsedBitsPerChannel() - 8);
2117  channels = bpp/8; ASSERT(channels >= m_header.channels);
2118 
2119  for (i=0; i < h; i++) {
2120  if (i%2) sampledPos -= (w + 1)/2;
2121  cnt = 0;
2122  for (j=0; j < w; j++) {
2123  if (m_downsample) {
2124  // image was downsampled
2125  uAvg = a[sampledPos];
2126  vAvg = b[sampledPos];
2127  } else {
2128  uAvg = a[yPos];
2129  vAvg = b[yPos];
2130  }
2131  buff[cnt + channelMap[0]] = Clamp8((l[yPos] + yuvOffset16) >> shift);
2132  buff[cnt + channelMap[1]] = Clamp8((uAvg + yuvOffset16) >> shift);
2133  buff[cnt + channelMap[2]] = Clamp8((vAvg + yuvOffset16) >> shift);
2134  cnt += channels;
2135  yPos++;
2136  if (j%2) sampledPos++;
2137  }
2138  buff += pitch;
2139  if (wOdd) sampledPos++;
2140 
2141  if (cb) {
2142  percent += dP;
2143  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2144  }
2145  }
2146  }
2147  break;
2148  }
2149  case ImageModeRGBA:
2150  case ImageModeCMYKColor:
2151  {
2152  ASSERT(m_header.channels == 4);
2153  ASSERT(m_header.bpp == m_header.channels*8);
2154  ASSERT(bpp%8 == 0);
2155 
2156  DataT* y = m_channel[0]; ASSERT(y);
2157  DataT* u = m_channel[1]; ASSERT(u);
2158  DataT* v = m_channel[2]; ASSERT(v);
2159  DataT* a = m_channel[3]; ASSERT(a);
2160  UINT8 g, aAvg;
2161  int cnt, channels = bpp/8; ASSERT(channels >= m_header.channels);
2162 
2163  for (i=0; i < h; i++) {
2164  if (i%2) sampledPos -= (w + 1)/2;
2165  cnt = 0;
2166  for (j=0; j < w; j++) {
2167  if (m_downsample) {
2168  // image was downsampled
2169  uAvg = u[sampledPos];
2170  vAvg = v[sampledPos];
2171  aAvg = Clamp8(a[sampledPos] + YUVoffset8);
2172  } else {
2173  uAvg = u[yPos];
2174  vAvg = v[yPos];
2175  aAvg = Clamp8(a[yPos] + YUVoffset8);
2176  }
2177  // Yuv
2178  buff[cnt + channelMap[1]] = g = Clamp8(y[yPos] + YUVoffset8 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
2179  buff[cnt + channelMap[2]] = Clamp8(uAvg + g);
2180  buff[cnt + channelMap[0]] = Clamp8(vAvg + g);
2181  buff[cnt + channelMap[3]] = aAvg;
2182  yPos++;
2183  cnt += channels;
2184  if (j%2) sampledPos++;
2185  }
2186  buff += pitch;
2187  if (wOdd) sampledPos++;
2188 
2189  if (cb) {
2190  percent += dP;
2191  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2192  }
2193  }
2194  break;
2195  }
2196  case ImageModeCMYK64:
2197  {
2198  ASSERT(m_header.channels == 4);
2199  ASSERT(m_header.bpp == 64);
2200 
2201  const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
2202 
2203  DataT* y = m_channel[0]; ASSERT(y);
2204  DataT* u = m_channel[1]; ASSERT(u);
2205  DataT* v = m_channel[2]; ASSERT(v);
2206  DataT* a = m_channel[3]; ASSERT(a);
2207  DataT g, aAvg;
2208  int cnt, channels;
2209 
2210  if (bpp%16 == 0) {
2211  const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
2212  UINT16 *buff16 = (UINT16 *)buff;
2213  int pitch16 = pitch/2;
2214  channels = bpp/16; ASSERT(channels >= m_header.channels);
2215 
2216  for (i=0; i < h; i++) {
2217  if (i%2) sampledPos -= (w + 1)/2;
2218  cnt = 0;
2219  for (j=0; j < w; j++) {
2220  if (m_downsample) {
2221  // image was downsampled
2222  uAvg = u[sampledPos];
2223  vAvg = v[sampledPos];
2224  aAvg = a[sampledPos] + yuvOffset16;
2225  } else {
2226  uAvg = u[yPos];
2227  vAvg = v[yPos];
2228  aAvg = a[yPos] + yuvOffset16;
2229  }
2230  // Yuv
2231  g = y[yPos] + yuvOffset16 - ((uAvg + vAvg ) >> 2); // must be logical shift operator
2232  buff16[cnt + channelMap[1]] = Clamp16(g << shift);
2233  buff16[cnt + channelMap[2]] = Clamp16((uAvg + g) << shift);
2234  buff16[cnt + channelMap[0]] = Clamp16((vAvg + g) << shift);
2235  buff16[cnt + channelMap[3]] = Clamp16(aAvg << shift);
2236  yPos++;
2237  cnt += channels;
2238  if (j%2) sampledPos++;
2239  }
2240  buff16 += pitch16;
2241  if (wOdd) sampledPos++;
2242 
2243  if (cb) {
2244  percent += dP;
2245  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2246  }
2247  }
2248  } else {
2249  ASSERT(bpp%8 == 0);
2250  const int shift = __max(0, UsedBitsPerChannel() - 8);
2251  channels = bpp/8; ASSERT(channels >= m_header.channels);
2252 
2253  for (i=0; i < h; i++) {
2254  if (i%2) sampledPos -= (w + 1)/2;
2255  cnt = 0;
2256  for (j=0; j < w; j++) {
2257  if (m_downsample) {
2258  // image was downsampled
2259  uAvg = u[sampledPos];
2260  vAvg = v[sampledPos];
2261  aAvg = a[sampledPos] + yuvOffset16;
2262  } else {
2263  uAvg = u[yPos];
2264  vAvg = v[yPos];
2265  aAvg = a[yPos] + yuvOffset16;
2266  }
2267  // Yuv
2268  g = y[yPos] + yuvOffset16 - ((uAvg + vAvg ) >> 2); // must be logical shift operator
2269  buff[cnt + channelMap[1]] = Clamp8(g >> shift);
2270  buff[cnt + channelMap[2]] = Clamp8((uAvg + g) >> shift);
2271  buff[cnt + channelMap[0]] = Clamp8((vAvg + g) >> shift);
2272  buff[cnt + channelMap[3]] = Clamp8(aAvg >> shift);
2273  yPos++;
2274  cnt += channels;
2275  if (j%2) sampledPos++;
2276  }
2277  buff += pitch;
2278  if (wOdd) sampledPos++;
2279 
2280  if (cb) {
2281  percent += dP;
2282  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2283  }
2284  }
2285  }
2286  break;
2287  }
2288 #ifdef __PGF32SUPPORT__
2289  case ImageModeGray32:
2290  {
2291  ASSERT(m_header.channels == 1);
2292  ASSERT(m_header.bpp == 32);
2293 
2294  const int yuvOffset31 = 1 << (UsedBitsPerChannel() - 1);
2295 
2296  DataT* y = m_channel[0]; ASSERT(y);
2297 
2298  if (bpp == 32) {
2299  const int shift = 31 - UsedBitsPerChannel(); ASSERT(shift >= 0);
2300  UINT32 *buff32 = (UINT32 *)buff;
2301  int pitch32 = pitch/4;
2302 
2303  for (i=0; i < h; i++) {
2304  for (j=0; j < w; j++) {
2305  buff32[j] = Clamp31((y[yPos++] + yuvOffset31) << shift);
2306  }
2307  buff32 += pitch32;
2308 
2309  if (cb) {
2310  percent += dP;
2311  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2312  }
2313  }
2314  } else if (bpp == 16) {
2315  const int usedBits = UsedBitsPerChannel();
2316  UINT16 *buff16 = (UINT16 *)buff;
2317  int pitch16 = pitch/2;
2318 
2319  if (usedBits < 16) {
2320  const int shift = 16 - usedBits;
2321  for (i=0; i < h; i++) {
2322  for (j=0; j < w; j++) {
2323  buff16[j] = Clamp16((y[yPos++] + yuvOffset31) << shift);
2324  }
2325  buff16 += pitch16;
2326 
2327  if (cb) {
2328  percent += dP;
2329  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2330  }
2331  }
2332  } else {
2333  const int shift = __max(0, usedBits - 16);
2334  for (i=0; i < h; i++) {
2335  for (j=0; j < w; j++) {
2336  buff16[j] = Clamp16((y[yPos++] + yuvOffset31) >> shift);
2337  }
2338  buff16 += pitch16;
2339 
2340  if (cb) {
2341  percent += dP;
2342  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2343  }
2344  }
2345  }
2346  } else {
2347  ASSERT(bpp == 8);
2348  const int shift = __max(0, UsedBitsPerChannel() - 8);
2349 
2350  for (i=0; i < h; i++) {
2351  for (j=0; j < w; j++) {
2352  buff[j] = Clamp8((y[yPos++] + yuvOffset31) >> shift);
2353  }
2354  buff += pitch;
2355 
2356  if (cb) {
2357  percent += dP;
2358  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2359  }
2360  }
2361  }
2362  break;
2363  }
2364 #endif
2365  case ImageModeRGB12:
2366  {
2367  ASSERT(m_header.channels == 3);
2368  ASSERT(m_header.bpp == m_header.channels*4);
2369  ASSERT(bpp == m_header.channels*4);
2370  ASSERT(!m_downsample);
2371 
2372  DataT* y = m_channel[0]; ASSERT(y);
2373  DataT* u = m_channel[1]; ASSERT(u);
2374  DataT* v = m_channel[2]; ASSERT(v);
2375  UINT16 yval;
2376  int cnt;
2377 
2378  for (i=0; i < h; i++) {
2379  cnt = 0;
2380  for (j=0; j < w; j++) {
2381  // Yuv
2382  uAvg = u[yPos];
2383  vAvg = v[yPos];
2384  yval = Clamp4(y[yPos++] + YUVoffset4 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
2385  if (j%2 == 0) {
2386  buff[cnt] = UINT8(Clamp4(vAvg + yval) | (yval << 4));
2387  cnt++;
2388  buff[cnt] = Clamp4(uAvg + yval);
2389  } else {
2390  buff[cnt] |= Clamp4(vAvg + yval) << 4;
2391  cnt++;
2392  buff[cnt] = UINT8(yval | (Clamp4(uAvg + yval) << 4));
2393  cnt++;
2394  }
2395  }
2396  buff += pitch;
2397 
2398  if (cb) {
2399  percent += dP;
2400  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2401  }
2402  }
2403  break;
2404  }
2405  case ImageModeRGB16:
2406  {
2407  ASSERT(m_header.channels == 3);
2408  ASSERT(m_header.bpp == 16);
2409  ASSERT(bpp == 16);
2410  ASSERT(!m_downsample);
2411 
2412  DataT* y = m_channel[0]; ASSERT(y);
2413  DataT* u = m_channel[1]; ASSERT(u);
2414  DataT* v = m_channel[2]; ASSERT(v);
2415  UINT16 yval;
2416  UINT16 *buff16 = (UINT16 *)buff;
2417  int pitch16 = pitch/2;
2418 
2419  for (i=0; i < h; i++) {
2420  for (j=0; j < w; j++) {
2421  // Yuv
2422  uAvg = u[yPos];
2423  vAvg = v[yPos];
2424  yval = Clamp6(y[yPos++] + YUVoffset6 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
2425  buff16[j] = (yval << 5) | ((Clamp6(uAvg + yval) >> 1) << 11) | (Clamp6(vAvg + yval) >> 1);
2426  }
2427  buff16 += pitch16;
2428 
2429  if (cb) {
2430  percent += dP;
2431  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2432  }
2433  }
2434  break;
2435  }
2436  default:
2437  ASSERT(false);
2438  }
2439 
2440 #ifdef __PGFROISUPPORT__
2441  if (targetBuff) {
2442  // copy valid ROI (m_roi) from temporary buffer (roi) to target buffer
2443  if (bpp%8 == 0) {
2444  BYTE bypp = bpp/8;
2445  buff = buffStart + (levelRoi.top - roi.top)*pitch + (levelRoi.left - roi.left)*bypp;
2446  w = levelRoi.Width()*bypp;
2447  h = levelRoi.Height();
2448 
2449  for (i=0; i < h; i++) {
2450  for (j=0; j < w; j++) {
2451  targetBuff[j] = buff[j];
2452  }
2453  targetBuff += targetPitch;
2454  buff += pitch;
2455  }
2456  } else {
2457  // to do
2458  }
2459 
2460  delete[] buffStart; buffStart = 0;
2461  }
2462 #endif
2463 }
UINT32 AlignWordPos(UINT32 pos)
Definition: BitStream.h:260
#define YUVoffset8
Definition: PGFimage.cpp:37
#define YUVoffset4
Definition: PGFimage.cpp:35
#define YUVoffset6
Definition: PGFimage.cpp:36
#define ImageModeHSLColor
Definition: PGFplatform.h:103
#define ImageModeHSBColor
Definition: PGFplatform.h:104
#define __max(x, y)
Definition: PGFplatform.h:92
UINT32 Clamp31(DataT v) const
Definition: PGFimage.h:564
UINT16 Clamp6(DataT v) const
Definition: PGFimage.h:554
static UINT32 LevelWidth(UINT32 width, int level)
Definition: PGFimage.h:491
static UINT32 LevelHeight(UINT32 height, int level)
Definition: PGFimage.h:498
UINT16 Clamp16(DataT v) const
Definition: PGFimage.h:561
BYTE UsedBitsPerChannel() const
Definition: PGFimage.cpp:709
UINT8 Clamp8(DataT v) const
Definition: PGFimage.h:557
PGFRect m_roi
region of interest
Definition: PGFimage.h:531
bool ROIisSupported() const
Definition: PGFimage.h:465
UINT8 Clamp4(DataT v) const
Definition: PGFimage.h:551
Rectangle.
Definition: PGFtypes.h:194
UINT32 Height() const
Definition: PGFtypes.h:207
UINT32 Width() const
Definition: PGFtypes.h:205
UINT32 top
Definition: PGFtypes.h:215
UINT32 bottom
Definition: PGFtypes.h:215
UINT32 right
Definition: PGFtypes.h:215
UINT32 left
Definition: PGFtypes.h:215

◆ GetChannel()

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

Return an internal YUV image channel.

Parameters
cA channel index
Returns
An internal YUV image channel

Definition at line 321 of file PGFimage.h.

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

◆ GetColorTable() [1/2]

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

Definition at line 334 of file PGFimage.h.

334 { return m_postHeader.clut; }
RGBQUAD clut[ColorTableLen]
color table for indexed color images
Definition: PGFtypes.h:142

◆ GetColorTable() [2/2]

void CPGFImage::GetColorTable ( UINT32  iFirstColor,
UINT32  nColors,
RGBQUAD *  prgbColors 
) const

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

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

Definition at line 1293 of file PGFimage.cpp.

1293  {
1294  if (iFirstColor + nColors > ColorTableLen) ReturnWithError(ColorTableError);
1295 
1296  for (UINT32 i=iFirstColor, j=0; j < nColors; i++, j++) {
1297  prgbColors[j] = m_postHeader.clut[i];
1298  }
1299 }
#define ColorTableLen
size of color lookup table (clut)
Definition: PGFtypes.h:60

◆ GetEncodedHeaderLength()

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

614  {
615  ASSERT(m_decoder);
617 }
UINT32 GetEncodedHeaderLength() const
Definition: Decoder.h:137

◆ GetEncodedLevelLength()

UINT32 CPGFImage::GetEncodedLevelLength ( int  level) const
inline

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

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

Definition at line 370 of file PGFimage.h.

370 { ASSERT(level >= 0 && level < m_header.nLevels); return m_levelLength[m_header.nLevels - level - 1]; }

◆ GetHeader()

const PGFHeader* CPGFImage::GetHeader ( ) const
inline

Return the PGF header structure.

Returns
A PGF header structure

Definition at line 339 of file PGFimage.h.

339 { return &m_header; }

◆ GetMaxValue()

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.

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

◆ GetUserData()

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

323  {
324  size = m_postHeader.userDataLen;
325  return m_postHeader.userData;
326 }

◆ GetUserDataPos()

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.

350 { return m_userDataPos; }

◆ GetYUV()

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

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

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

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

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

Definition at line 2479 of file PGFimage.cpp.

2479  {
2480  ASSERT(buff);
2481  const UINT32 w = m_width[0];
2482  const UINT32 h = m_height[0];
2483  const bool wOdd = (1 == w%2);
2484  const int dataBits = DataTSize*8; ASSERT(dataBits == 16 || dataBits == 32);
2485  const int pitch2 = pitch/DataTSize;
2486  const int yuvOffset = (dataBits == 16) ? YUVoffset8 : YUVoffset16;
2487  const double dP = 1.0/h;
2488 
2489  int defMap[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; ASSERT(sizeof(defMap)/sizeof(defMap[0]) == MaxChannels);
2490  if (channelMap == NULL) channelMap = defMap;
2491  int sampledPos = 0, yPos = 0;
2492  DataT uAvg, vAvg;
2493  double percent = 0;
2494  UINT32 i, j;
2495 
2496  if (m_header.channels == 3) {
2497  ASSERT(bpp%dataBits == 0);
2498 
2499  DataT* y = m_channel[0]; ASSERT(y);
2500  DataT* u = m_channel[1]; ASSERT(u);
2501  DataT* v = m_channel[2]; ASSERT(v);
2502  int cnt, channels = bpp/dataBits; ASSERT(channels >= m_header.channels);
2503 
2504  for (i=0; i < h; i++) {
2505  if (i%2) sampledPos -= (w + 1)/2;
2506  cnt = 0;
2507  for (j=0; j < w; j++) {
2508  if (m_downsample) {
2509  // image was downsampled
2510  uAvg = u[sampledPos];
2511  vAvg = v[sampledPos];
2512  } else {
2513  uAvg = u[yPos];
2514  vAvg = v[yPos];
2515  }
2516  buff[cnt + channelMap[0]] = y[yPos];
2517  buff[cnt + channelMap[1]] = uAvg;
2518  buff[cnt + channelMap[2]] = vAvg;
2519  yPos++;
2520  cnt += channels;
2521  if (j%2) sampledPos++;
2522  }
2523  buff += pitch2;
2524  if (wOdd) sampledPos++;
2525 
2526  if (cb) {
2527  percent += dP;
2528  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2529  }
2530  }
2531  } else if (m_header.channels == 4) {
2532  ASSERT(m_header.bpp == m_header.channels*8);
2533  ASSERT(bpp%dataBits == 0);
2534 
2535  DataT* y = m_channel[0]; ASSERT(y);
2536  DataT* u = m_channel[1]; ASSERT(u);
2537  DataT* v = m_channel[2]; ASSERT(v);
2538  DataT* a = m_channel[3]; ASSERT(a);
2539  UINT8 aAvg;
2540  int cnt, channels = bpp/dataBits; ASSERT(channels >= m_header.channels);
2541 
2542  for (i=0; i < h; i++) {
2543  if (i%2) sampledPos -= (w + 1)/2;
2544  cnt = 0;
2545  for (j=0; j < w; j++) {
2546  if (m_downsample) {
2547  // image was downsampled
2548  uAvg = u[sampledPos];
2549  vAvg = v[sampledPos];
2550  aAvg = Clamp8(a[sampledPos] + yuvOffset);
2551  } else {
2552  uAvg = u[yPos];
2553  vAvg = v[yPos];
2554  aAvg = Clamp8(a[yPos] + yuvOffset);
2555  }
2556  // Yuv
2557  buff[cnt + channelMap[0]] = y[yPos];
2558  buff[cnt + channelMap[1]] = uAvg;
2559  buff[cnt + channelMap[2]] = vAvg;
2560  buff[cnt + channelMap[3]] = aAvg;
2561  yPos++;
2562  cnt += channels;
2563  if (j%2) sampledPos++;
2564  }
2565  buff += pitch2;
2566  if (wOdd) sampledPos++;
2567 
2568  if (cb) {
2569  percent += dP;
2570  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2571  }
2572  }
2573  }
2574 }
#define YUVoffset16
Definition: PGFimage.cpp:38
#define DataTSize
Definition: PGFtypes.h:233

◆ Height()

UINT32 CPGFImage::Height ( int  level = 0) const
inline

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

Parameters
levelA level
Returns
Image level height in pixels

Definition at line 423 of file PGFimage.h.

423 { ASSERT(level >= 0); return LevelHeight(m_header.height, level); }

◆ ImportBitmap()

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

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

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

Definition at line 744 of file PGFimage.cpp.

744  {
745  ASSERT(buff);
746  ASSERT(m_channel[0]);
747 
748  // color transform
749  RgbToYuv(pitch, buff, bpp, channelMap, cb, data);
750 
751  if (m_downsample) {
752  // Subsampling of the chrominance and alpha channels
753  for (int i=1; i < m_header.channels; i++) {
754  Downsample(i);
755  }
756  }
757 }
void RgbToYuv(int pitch, UINT8 *rgbBuff, BYTE bpp, int channelMap[], CallbackPtr cb, void *data) THROW_
Definition: PGFimage.cpp:1332
void Downsample(int nChannel)
Definition: PGFimage.cpp:761

◆ ImportIsSupported()

bool CPGFImage::ImportIsSupported ( BYTE  mode)
static

Check for valid import image mode.

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

Definition at line 1248 of file PGFimage.cpp.

1248  {
1249  size_t size = DataTSize;
1250 
1251  if (size >= 2) {
1252  switch(mode) {
1253  case ImageModeBitmap:
1254  case ImageModeIndexedColor:
1255  case ImageModeGrayScale:
1256  case ImageModeRGBColor:
1257  case ImageModeCMYKColor:
1258  case ImageModeHSLColor:
1259  case ImageModeHSBColor:
1260  //case ImageModeDuotone:
1261  case ImageModeLabColor:
1262  case ImageModeRGB12:
1263  case ImageModeRGB16:
1264  case ImageModeRGBA:
1265  return true;
1266  }
1267  }
1268  if (size >= 3) {
1269  switch(mode) {
1270  case ImageModeGray16:
1271  case ImageModeRGB48:
1272  case ImageModeLab48:
1273  case ImageModeCMYK64:
1274  //case ImageModeDuotone16:
1275  return true;
1276  }
1277  }
1278  if (size >=4) {
1279  switch(mode) {
1280  case ImageModeGray32:
1281  return true;
1282  }
1283  }
1284  return false;
1285 }

◆ ImportYUV()

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

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

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

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

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

Definition at line 2590 of file PGFimage.cpp.

2590  {
2591  ASSERT(buff);
2592  const double dP = 1.0/m_header.height;
2593  const int dataBits = DataTSize*8; ASSERT(dataBits == 16 || dataBits == 32);
2594  const int pitch2 = pitch/DataTSize;
2595  const int yuvOffset = (dataBits == 16) ? YUVoffset8 : YUVoffset16;
2596 
2597  int yPos = 0, cnt = 0;
2598  double percent = 0;
2599  int defMap[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; ASSERT(sizeof(defMap)/sizeof(defMap[0]) == MaxChannels);
2600 
2601  if (channelMap == NULL) channelMap = defMap;
2602 
2603  if (m_header.channels == 3) {
2604  ASSERT(bpp%dataBits == 0);
2605 
2606  DataT* y = m_channel[0]; ASSERT(y);
2607  DataT* u = m_channel[1]; ASSERT(u);
2608  DataT* v = m_channel[2]; ASSERT(v);
2609  const int channels = bpp/dataBits; ASSERT(channels >= m_header.channels);
2610 
2611  for (UINT32 h=0; h < m_header.height; h++) {
2612  if (cb) {
2613  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2614  percent += dP;
2615  }
2616 
2617  cnt = 0;
2618  for (UINT32 w=0; w < m_header.width; w++) {
2619  y[yPos] = buff[cnt + channelMap[0]];
2620  u[yPos] = buff[cnt + channelMap[1]];
2621  v[yPos] = buff[cnt + channelMap[2]];
2622  yPos++;
2623  cnt += channels;
2624  }
2625  buff += pitch2;
2626  }
2627  } else if (m_header.channels == 4) {
2628  ASSERT(bpp%dataBits == 0);
2629 
2630  DataT* y = m_channel[0]; ASSERT(y);
2631  DataT* u = m_channel[1]; ASSERT(u);
2632  DataT* v = m_channel[2]; ASSERT(v);
2633  DataT* a = m_channel[3]; ASSERT(a);
2634  const int channels = bpp/dataBits; ASSERT(channels >= m_header.channels);
2635 
2636  for (UINT32 h=0; h < m_header.height; h++) {
2637  if (cb) {
2638  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2639  percent += dP;
2640  }
2641 
2642  cnt = 0;
2643  for (UINT32 w=0; w < m_header.width; w++) {
2644  y[yPos] = buff[cnt + channelMap[0]];
2645  u[yPos] = buff[cnt + channelMap[1]];
2646  v[yPos] = buff[cnt + channelMap[2]];
2647  a[yPos] = buff[cnt + channelMap[3]] - yuvOffset;
2648  yPos++;
2649  cnt += channels;
2650  }
2651  buff += pitch2;
2652  }
2653  }
2654 
2655  if (m_downsample) {
2656  // Subsampling of the chrominance and alpha channels
2657  for (int i=1; i < m_header.channels; i++) {
2658  Downsample(i);
2659  }
2660  }
2661 }

◆ IsOpen()

bool CPGFImage::IsOpen ( ) const
inline

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

Definition at line 87 of file PGFimage.h.

87 { return m_decoder != NULL; }

◆ Level()

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.

430 { return (BYTE)m_currentLevel; }

◆ LevelHeight()

static UINT32 CPGFImage::LevelHeight ( UINT32  height,
int  level 
)
inlinestatic

Compute and return image height at given level.

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

Definition at line 498 of file PGFimage.h.

498 { ASSERT(level >= 0); UINT32 h = (height >> level); return ((h << level) == height) ? h : h + 1; }

◆ Levels()

BYTE CPGFImage::Levels ( ) const
inline

Return the number of image levels.

Returns
Number of image levels

Definition at line 435 of file PGFimage.h.

435 { return m_header.nLevels; }

◆ LevelWidth()

static UINT32 CPGFImage::LevelWidth ( UINT32  width,
int  level 
)
inlinestatic

Compute and return image width at given level.

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

Definition at line 491 of file PGFimage.h.

491 { ASSERT(level >= 0); UINT32 w = (width >> level); return ((w << level) == width) ? w : w + 1; }

◆ Mode()

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.

454 { return m_header.mode; }

◆ Open()

void CPGFImage::Open ( CPGFStream stream)

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

Parameters
streamA PGF stream

Definition at line 131 of file PGFimage.cpp.

131  {
132  ASSERT(stream);
133 
134  // create decoder and read PGFPreHeader PGFHeader PGFPostHeader LevelLengths
137 
138  if (m_header.nLevels > MaxLevel) ReturnWithError(FormatCannotRead);
139 
140  // set current level
142 
143  // set image width and height
144  m_width[0] = m_header.width;
145  m_height[0] = m_header.height;
146 
147  // complete header
148  if (!CompleteHeader()) ReturnWithError(FormatCannotRead);
149 
150  // interpret quant parameter
159  m_downsample = true;
160  m_quant = m_header.quality - 1;
161  } else {
162  m_downsample = false;
164  }
165 
166  // set channel dimensions (chrominance is subsampled by factor 2)
167  if (m_downsample) {
168  for (int i=1; i < m_header.channels; i++) {
169  m_width[i] = (m_width[0] + 1)/2;
170  m_height[i] = (m_height[0] + 1)/2;
171  }
172  } else {
173  for (int i=1; i < m_header.channels; i++) {
174  m_width[i] = m_width[0];
175  m_height[i] = m_height[0];
176  }
177  }
178 
179  if (m_header.nLevels > 0) {
180  // init wavelet subbands
181  for (int i=0; i < m_header.channels; i++) {
183  }
184 
185  // used in Read when PM_Absolute
186  m_percent = pow(0.25, m_header.nLevels);
187 
188  } else {
189  // very small image: we don't use DWT and encoding
190 
191  // read channels
192  for (int c=0; c < m_header.channels; c++) {
193  const UINT32 size = m_width[c]*m_height[c];
194  m_channel[c] = new(std::nothrow) DataT[size];
195  if (!m_channel[c]) ReturnWithError(InsufficientMemory);
196 
197  // read channel data from stream
198  for (UINT32 i=0; i < size; i++) {
199  int count = DataTSize;
200  stream->Read(&count, &m_channel[c][i]);
201  if (count != DataTSize) ReturnWithError(MissingData);
202  }
203  }
204  }
205 }
#define DownsampleThreshold
if quality is larger than this threshold than downsampling is used
Definition: PGFtypes.h:59
PGF decoder.
Definition: Decoder.h:46
bool CompleteHeader()
Definition: PGFimage.cpp:208
virtual void Read(int *count, void *buffer)=0
PGF wavelet transform.
UINT8 quality
quantization parameter: 0=lossless, 4=standard, 6=poor quality
Definition: PGFtypes.h:128

◆ Quality()

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.

441 { return m_header.quality; }

◆ Read() [1/2]

void CPGFImage::Read ( int  level = 0,
CallbackPtr  cb = NULL,
void *  data = NULL 
)

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

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

Definition at line 385 of file PGFimage.cpp.

385  {
386  ASSERT((level >= 0 && level < m_header.nLevels) || m_header.nLevels == 0); // m_header.nLevels == 0: image didn't use wavelet transform
387  ASSERT(m_decoder);
388 
389 #ifdef __PGFROISUPPORT__
390  if (ROIisSupported() && m_header.nLevels > 0) {
391  // new encoding scheme supporting ROI
392  PGFRect rect(0, 0, m_header.width, m_header.height);
393  Read(rect, level, cb, data);
394  return;
395  }
396 #endif
397 
398  if (m_header.nLevels == 0) {
399  if (level == 0) {
400  // the data has already been read during open
401  // now update progress
402  if (cb) {
403  if ((*cb)(1.0, true, data)) ReturnWithError(EscapePressed);
404  }
405  }
406  } else {
407  const int levelDiff = m_currentLevel - level;
408  double percent = (m_progressMode == PM_Relative) ? pow(0.25, levelDiff) : m_percent;
409 
410  // encoding scheme without ROI
411  while (m_currentLevel > level) {
412  for (int i=0; i < m_header.channels; i++) {
413  ASSERT(m_wtChannel[i]);
414  // decode file and write stream to m_wtChannel
415  if (m_currentLevel == m_header.nLevels) {
416  // last level also has LL band
418  }
419  if (m_preHeader.version & Version5) {
420  // since version 5
423  } else {
424  // until version 4
426  }
428  }
429 
430  volatile OSError error = NoError; // volatile prevents optimizations
431 #ifdef LIBPGF_USE_OPENMP
432  #pragma omp parallel for default(shared)
433 #endif
434  for (int i=0; i < m_header.channels; i++) {
435  // inverse transform from m_wtChannel to m_channel
436  if (error == NoError) {
437  OSError err = m_wtChannel[i]->InverseTransform(m_currentLevel, &m_width[i], &m_height[i], &m_channel[i]);
438  if (err != NoError) error = err;
439  }
440  ASSERT(m_channel[i]);
441  }
442  if (error != NoError) ReturnWithError(error);
443 
444  // set new level: must be done before refresh callback
445  m_currentLevel--;
446 
447  // now we have to refresh the display
448  if (m_cb) m_cb(m_cbArg);
449 
450  // now update progress
451  if (cb) {
452  percent *= 4;
453  if (m_progressMode == PM_Absolute) m_percent = percent;
454  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
455  }
456  }
457  }
458 
459  // automatically closing
460  if (m_currentLevel == 0) Close();
461 }
@ PM_Absolute
Definition: PGFimage.h:36
@ LL
Definition: PGFtypes.h:92
@ HL
Definition: PGFtypes.h:92
@ LH
Definition: PGFtypes.h:92
@ HH
Definition: PGFtypes.h:92
void DecodeInterleaved(CWaveletTransform *wtChannel, int level, int quantParam) THROW_
Definition: Decoder.cpp:319
void Read(int level=0, CallbackPtr cb=NULL, void *data=NULL) THROW_
Definition: PGFimage.cpp:385
void PlaceTile(CDecoder &decoder, int quantParam, bool tile=false, UINT32 tileX=0, UINT32 tileY=0) THROW_
Definition: Subband.cpp:202
OSError InverseTransform(int level, UINT32 *width, UINT32 *height, DataT **data)
CSubband * GetSubband(int level, Orientation orientation)

◆ Read() [2/2]

void CPGFImage::Read ( PGFRect rect,
int  level = 0,
CallbackPtr  cb = NULL,
void *  data = NULL 
)

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

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

◆ ReadEncodedData()

UINT32 CPGFImage::ReadEncodedData ( int  level,
UINT8 *  target,
UINT32  targetLen 
) const

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

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

Definition at line 660 of file PGFimage.cpp.

660  {
661  ASSERT(level >= 0 && level < m_header.nLevels);
662  ASSERT(target);
663  ASSERT(targetLen > 0);
664  ASSERT(m_decoder);
665 
666  // reset stream position
668 
669  // position stream
670  UINT64 offset = 0;
671 
672  for (int i=m_header.nLevels - 1; i > level; i--) {
673  offset += m_levelLength[m_header.nLevels - 1 - i];
674  }
675  m_decoder->Skip(offset);
676 
677  // compute number of bytes to read
678  UINT32 len = __min(targetLen, GetEncodedLevelLength(level));
679 
680  // read data
681  len = m_decoder->ReadEncodedData(target, len);
682  ASSERT(len >= 0 && len <= targetLen);
683 
684  return len;
685 }
void SetStreamPosToData() THROW_
Reset stream position to beginning of data block.
Definition: Decoder.h:145
UINT32 ReadEncodedData(UINT8 *target, UINT32 len) const THROW_
Definition: Decoder.cpp:232
void Skip(UINT64 offset) THROW_
Definition: Decoder.cpp:435
UINT32 GetEncodedLevelLength(int level) const
Definition: PGFimage.h:370

◆ ReadEncodedHeader()

UINT32 CPGFImage::ReadEncodedHeader ( UINT8 *  target,
UINT32  targetLen 
) const

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

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

Definition at line 626 of file PGFimage.cpp.

626  {
627  ASSERT(target);
628  ASSERT(targetLen > 0);
629  ASSERT(m_decoder);
630 
631  // reset stream position
633 
634  // compute number of bytes to read
635  UINT32 len = __min(targetLen, GetEncodedHeaderLength());
636 
637  // read data
638  len = m_decoder->ReadEncodedData(target, len);
639  ASSERT(len >= 0 && len <= targetLen);
640 
641  return len;
642 }
void SetStreamPosToStart() THROW_
Reset stream position to beginning of PGF pre-header.
Definition: Decoder.h:141
UINT32 GetEncodedHeaderLength() const
Definition: PGFimage.cpp:614

◆ ReadPreview()

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.

121 { Read(Levels() - 1); }
BYTE Levels() const
Definition: PGFimage.h:435

◆ Reconstruct()

void CPGFImage::Reconstruct ( int  level = 0)

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

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

Definition at line 333 of file PGFimage.cpp.

333  {
334  if (m_header.nLevels == 0) {
335  // image didn't use wavelet transform
336  if (level == 0) {
337  for (int i=0; i < m_header.channels; i++) {
338  ASSERT(m_wtChannel[i]);
339  m_channel[i] = m_wtChannel[i]->GetSubband(0, LL)->GetBuffer();
340  }
341  }
342  } else {
343  int currentLevel = m_header.nLevels;
344 
345  if (ROIisSupported()) {
346  // enable ROI reading
348  }
349 
350  while (currentLevel > level) {
351  for (int i=0; i < m_header.channels; i++) {
352  ASSERT(m_wtChannel[i]);
353  // dequantize subbands
354  if (currentLevel == m_header.nLevels) {
355  // last level also has LL band
356  m_wtChannel[i]->GetSubband(currentLevel, LL)->Dequantize(m_quant);
357  }
358  m_wtChannel[i]->GetSubband(currentLevel, HL)->Dequantize(m_quant);
359  m_wtChannel[i]->GetSubband(currentLevel, LH)->Dequantize(m_quant);
360  m_wtChannel[i]->GetSubband(currentLevel, HH)->Dequantize(m_quant);
361 
362  // inverse transform from m_wtChannel to m_channel
363  OSError err = m_wtChannel[i]->InverseTransform(currentLevel, &m_width[i], &m_height[i], &m_channel[i]);
364  if (err != NoError) ReturnWithError(err);
365  ASSERT(m_channel[i]);
366  }
367 
368  currentLevel--;
369  }
370  }
371 }
void SetROI(PGFRect rect)
void Dequantize(int quantParam)
Definition: Subband.cpp:154
DataT * GetBuffer()
Definition: Subband.h:106

◆ ResetStreamPos()

void CPGFImage::ResetStreamPos ( )

Reset stream position to start of PGF pre-header.

Definition at line 646 of file PGFimage.cpp.

646  {
647  ASSERT(m_decoder);
648  return m_decoder->SetStreamPosToStart();
649 }

◆ RgbToYuv()

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

Definition at line 1332 of file PGFimage.cpp.

1332  {
1333  ASSERT(buff);
1334  int yPos = 0, cnt = 0;
1335  double percent = 0;
1336  const double dP = 1.0/m_header.height;
1337  int defMap[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; ASSERT(sizeof(defMap)/sizeof(defMap[0]) == MaxChannels);
1338 
1339  if (channelMap == NULL) channelMap = defMap;
1340 
1341  switch(m_header.mode) {
1342  case ImageModeBitmap:
1343  {
1344  ASSERT(m_header.channels == 1);
1345  ASSERT(m_header.bpp == 1);
1346  ASSERT(bpp == 1);
1347 
1348  const UINT32 w = m_header.width;
1349  const UINT32 w2 = (m_header.width + 7)/8;
1350  DataT* y = m_channel[0]; ASSERT(y);
1351 
1352  for (UINT32 h=0; h < m_header.height; h++) {
1353  if (cb) {
1354  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1355  percent += dP;
1356  }
1357 
1358  for (UINT32 j=0; j < w2; j++) {
1359  y[yPos++] = buff[j] - YUVoffset8;
1360  }
1361  for (UINT32 j=w2; j < w; j++) {
1362  y[yPos++] = YUVoffset8;
1363  }
1364 
1365  //UINT cnt = w;
1366  //for (UINT32 j=0; j < w2; j++) {
1367  // for (int k=7; k >= 0; k--) {
1368  // if (cnt) {
1369  // y[yPos++] = YUVoffset8 + (1 & (buff[j] >> k));
1370  // cnt--;
1371  // }
1372  // }
1373  //}
1374  buff += pitch;
1375  }
1376  }
1377  break;
1378  case ImageModeIndexedColor:
1379  case ImageModeGrayScale:
1380  case ImageModeHSLColor:
1381  case ImageModeHSBColor:
1382  case ImageModeLabColor:
1383  {
1384  ASSERT(m_header.channels >= 1);
1385  ASSERT(m_header.bpp == m_header.channels*8);
1386  ASSERT(bpp%8 == 0);
1387  const int channels = bpp/8; ASSERT(channels >= m_header.channels);
1388 
1389  for (UINT32 h=0; h < m_header.height; h++) {
1390  if (cb) {
1391  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1392  percent += dP;
1393  }
1394 
1395  cnt = 0;
1396  for (UINT32 w=0; w < m_header.width; w++) {
1397  for (int c=0; c < m_header.channels; c++) {
1398  m_channel[c][yPos] = buff[cnt + channelMap[c]] - YUVoffset8;
1399  }
1400  cnt += channels;
1401  yPos++;
1402  }
1403  buff += pitch;
1404  }
1405  }
1406  break;
1407  case ImageModeGray16:
1408  case ImageModeLab48:
1409  {
1410  ASSERT(m_header.channels >= 1);
1411  ASSERT(m_header.bpp == m_header.channels*16);
1412  ASSERT(bpp%16 == 0);
1413 
1414  UINT16 *buff16 = (UINT16 *)buff;
1415  const int pitch16 = pitch/2;
1416  const int channels = bpp/16; ASSERT(channels >= m_header.channels);
1417  const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
1418  const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
1419 
1420  for (UINT32 h=0; h < m_header.height; h++) {
1421  if (cb) {
1422  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1423  percent += dP;
1424  }
1425 
1426  cnt = 0;
1427  for (UINT32 w=0; w < m_header.width; w++) {
1428  for (int c=0; c < m_header.channels; c++) {
1429  m_channel[c][yPos] = (buff16[cnt + channelMap[c]] >> shift) - yuvOffset16;
1430  }
1431  cnt += channels;
1432  yPos++;
1433  }
1434  buff16 += pitch16;
1435  }
1436  }
1437  break;
1438  case ImageModeRGBColor:
1439  {
1440  ASSERT(m_header.channels == 3);
1441  ASSERT(m_header.bpp == m_header.channels*8);
1442  ASSERT(bpp%8 == 0);
1443 
1444  DataT* y = m_channel[0]; ASSERT(y);
1445  DataT* u = m_channel[1]; ASSERT(u);
1446  DataT* v = m_channel[2]; ASSERT(v);
1447  const int channels = bpp/8; ASSERT(channels >= m_header.channels);
1448  UINT8 b, g, r;
1449 
1450  for (UINT32 h=0; h < m_header.height; h++) {
1451  if (cb) {
1452  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1453  percent += dP;
1454  }
1455 
1456  cnt = 0;
1457  for (UINT32 w=0; w < m_header.width; w++) {
1458  b = buff[cnt + channelMap[0]];
1459  g = buff[cnt + channelMap[1]];
1460  r = buff[cnt + channelMap[2]];
1461  // Yuv
1462  y[yPos] = ((b + (g << 1) + r) >> 2) - YUVoffset8;
1463  u[yPos] = r - g;
1464  v[yPos] = b - g;
1465  yPos++;
1466  cnt += channels;
1467  }
1468  buff += pitch;
1469  }
1470  }
1471  break;
1472  case ImageModeRGB48:
1473  {
1474  ASSERT(m_header.channels == 3);
1475  ASSERT(m_header.bpp == m_header.channels*16);
1476  ASSERT(bpp%16 == 0);
1477 
1478  UINT16 *buff16 = (UINT16 *)buff;
1479  const int pitch16 = pitch/2;
1480  const int channels = bpp/16; ASSERT(channels >= m_header.channels);
1481  const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
1482  const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
1483 
1484  DataT* y = m_channel[0]; ASSERT(y);
1485  DataT* u = m_channel[1]; ASSERT(u);
1486  DataT* v = m_channel[2]; ASSERT(v);
1487  UINT16 b, g, r;
1488 
1489  for (UINT32 h=0; h < m_header.height; h++) {
1490  if (cb) {
1491  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1492  percent += dP;
1493  }
1494 
1495  cnt = 0;
1496  for (UINT32 w=0; w < m_header.width; w++) {
1497  b = buff16[cnt + channelMap[0]] >> shift;
1498  g = buff16[cnt + channelMap[1]] >> shift;
1499  r = buff16[cnt + channelMap[2]] >> shift;
1500  // Yuv
1501  y[yPos] = ((b + (g << 1) + r) >> 2) - yuvOffset16;
1502  u[yPos] = r - g;
1503  v[yPos] = b - g;
1504  yPos++;
1505  cnt += channels;
1506  }
1507  buff16 += pitch16;
1508  }
1509  }
1510  break;
1511  case ImageModeRGBA:
1512  case ImageModeCMYKColor:
1513  {
1514  ASSERT(m_header.channels == 4);
1515  ASSERT(m_header.bpp == m_header.channels*8);
1516  ASSERT(bpp%8 == 0);
1517  const int channels = bpp/8; ASSERT(channels >= m_header.channels);
1518 
1519  DataT* y = m_channel[0]; ASSERT(y);
1520  DataT* u = m_channel[1]; ASSERT(u);
1521  DataT* v = m_channel[2]; ASSERT(v);
1522  DataT* a = m_channel[3]; ASSERT(a);
1523  UINT8 b, g, r;
1524 
1525  for (UINT32 h=0; h < m_header.height; h++) {
1526  if (cb) {
1527  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1528  percent += dP;
1529  }
1530 
1531  cnt = 0;
1532  for (UINT32 w=0; w < m_header.width; w++) {
1533  b = buff[cnt + channelMap[0]];
1534  g = buff[cnt + channelMap[1]];
1535  r = buff[cnt + channelMap[2]];
1536  // Yuv
1537  y[yPos] = ((b + (g << 1) + r) >> 2) - YUVoffset8;
1538  u[yPos] = r - g;
1539  v[yPos] = b - g;
1540  a[yPos++] = buff[cnt + channelMap[3]] - YUVoffset8;
1541  cnt += channels;
1542  }
1543  buff += pitch;
1544  }
1545  }
1546  break;
1547  case ImageModeCMYK64:
1548  {
1549  ASSERT(m_header.channels == 4);
1550  ASSERT(m_header.bpp == m_header.channels*16);
1551  ASSERT(bpp%16 == 0);
1552 
1553  UINT16 *buff16 = (UINT16 *)buff;
1554  const int pitch16 = pitch/2;
1555  const int channels = bpp/16; ASSERT(channels >= m_header.channels);
1556  const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
1557  const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
1558 
1559  DataT* y = m_channel[0]; ASSERT(y);
1560  DataT* u = m_channel[1]; ASSERT(u);
1561  DataT* v = m_channel[2]; ASSERT(v);
1562  DataT* a = m_channel[3]; ASSERT(a);
1563  UINT16 b, g, r;
1564 
1565  for (UINT32 h=0; h < m_header.height; h++) {
1566  if (cb) {
1567  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1568  percent += dP;
1569  }
1570 
1571  cnt = 0;
1572  for (UINT32 w=0; w < m_header.width; w++) {
1573  b = buff16[cnt + channelMap[0]] >> shift;
1574  g = buff16[cnt + channelMap[1]] >> shift;
1575  r = buff16[cnt + channelMap[2]] >> shift;
1576  // Yuv
1577  y[yPos] = ((b + (g << 1) + r) >> 2) - yuvOffset16;
1578  u[yPos] = r - g;
1579  v[yPos] = b - g;
1580  a[yPos++] = (buff16[cnt + channelMap[3]] >> shift) - yuvOffset16;
1581  cnt += channels;
1582  }
1583  buff16 += pitch16;
1584  }
1585  }
1586  break;
1587 #ifdef __PGF32SUPPORT__
1588  case ImageModeGray32:
1589  {
1590  ASSERT(m_header.channels == 1);
1591  ASSERT(m_header.bpp == 32);
1592  ASSERT(bpp == 32);
1593  ASSERT(DataTSize == sizeof(UINT32));
1594 
1595  DataT* y = m_channel[0]; ASSERT(y);
1596 
1597  UINT32 *buff32 = (UINT32 *)buff;
1598  const int pitch32 = pitch/4;
1599  const int shift = 31 - UsedBitsPerChannel(); ASSERT(shift >= 0);
1600  const DataT yuvOffset31 = 1 << (UsedBitsPerChannel() - 1);
1601 
1602  for (UINT32 h=0; h < m_header.height; h++) {
1603  if (cb) {
1604  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1605  percent += dP;
1606  }
1607 
1608  for (UINT32 w=0; w < m_header.width; w++) {
1609  y[yPos++] = (buff32[w] >> shift) - yuvOffset31;
1610  }
1611  buff32 += pitch32;
1612  }
1613  }
1614  break;
1615 #endif
1616  case ImageModeRGB12:
1617  {
1618  ASSERT(m_header.channels == 3);
1619  ASSERT(m_header.bpp == m_header.channels*4);
1620  ASSERT(bpp == m_header.channels*4);
1621 
1622  DataT* y = m_channel[0]; ASSERT(y);
1623  DataT* u = m_channel[1]; ASSERT(u);
1624  DataT* v = m_channel[2]; ASSERT(v);
1625 
1626  UINT8 rgb = 0, b, g, r;
1627 
1628  for (UINT32 h=0; h < m_header.height; h++) {
1629  if (cb) {
1630  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1631  percent += dP;
1632  }
1633 
1634  cnt = 0;
1635  for (UINT32 w=0; w < m_header.width; w++) {
1636  if (w%2 == 0) {
1637  // even pixel position
1638  rgb = buff[cnt];
1639  b = rgb & 0x0F;
1640  g = (rgb & 0xF0) >> 4;
1641  cnt++;
1642  rgb = buff[cnt];
1643  r = rgb & 0x0F;
1644  } else {
1645  // odd pixel position
1646  b = (rgb & 0xF0) >> 4;
1647  cnt++;
1648  rgb = buff[cnt];
1649  g = rgb & 0x0F;
1650  r = (rgb & 0xF0) >> 4;
1651  cnt++;
1652  }
1653 
1654  // Yuv
1655  y[yPos] = ((b + (g << 1) + r) >> 2) - YUVoffset4;
1656  u[yPos] = r - g;
1657  v[yPos] = b - g;
1658  yPos++;
1659  }
1660  buff += pitch;
1661  }
1662  }
1663  break;
1664  case ImageModeRGB16:
1665  {
1666  ASSERT(m_header.channels == 3);
1667  ASSERT(m_header.bpp == 16);
1668  ASSERT(bpp == 16);
1669 
1670  DataT* y = m_channel[0]; ASSERT(y);
1671  DataT* u = m_channel[1]; ASSERT(u);
1672  DataT* v = m_channel[2]; ASSERT(v);
1673 
1674  UINT16 *buff16 = (UINT16 *)buff;
1675  UINT16 rgb, b, g, r;
1676  const int pitch16 = pitch/2;
1677 
1678  for (UINT32 h=0; h < m_header.height; h++) {
1679  if (cb) {
1680  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1681  percent += dP;
1682  }
1683  for (UINT32 w=0; w < m_header.width; w++) {
1684  rgb = buff16[w];
1685  r = (rgb & 0xF800) >> 10; // highest 5 bits
1686  g = (rgb & 0x07E0) >> 5; // middle 6 bits
1687  b = (rgb & 0x001F) << 1; // lowest 5 bits
1688  // Yuv
1689  y[yPos] = ((b + (g << 1) + r) >> 2) - YUVoffset6;
1690  u[yPos] = r - g;
1691  v[yPos] = b - g;
1692  yPos++;
1693  }
1694 
1695  buff16 += pitch16;
1696  }
1697  }
1698  break;
1699  default:
1700  ASSERT(false);
1701  }
1702 }

◆ ROIisSupported()

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.

465 { return (m_preHeader.version & PGFROI) == PGFROI; }
#define PGFROI
supports Regions Of Interest
Definition: PGFtypes.h:64

◆ SetChannel()

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

Set internal PGF image buffer channel.

Parameters
channelA YUV data channel
cA channel index

Definition at line 276 of file PGFimage.h.

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

◆ SetColorTable()

void CPGFImage::SetColorTable ( UINT32  iFirstColor,
UINT32  nColors,
const RGBQUAD *  prgbColors 
)

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

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

Definition at line 1307 of file PGFimage.cpp.

1307  {
1308  if (iFirstColor + nColors > ColorTableLen) ReturnWithError(ColorTableError);
1309 
1310  for (UINT32 i=iFirstColor, j=0; j < nColors; i++, j++) {
1311  m_postHeader.clut[i] = prgbColors[j];
1312  }
1313 }

◆ SetHeader()

void CPGFImage::SetHeader ( const PGFHeader header,
BYTE  flags = 0,
UINT8 *  userData = 0,
UINT32  userDataLength = 0 
)

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

Parameters
headerA valid and already filled in PGF header structure
flagsA combination of additional version flags. In case you use level-wise encoding then set flag = PGFROI.
userDataA user-defined memory block containing any kind of cached metadata.
userDataLengthThe size of user-defined memory block in bytes

Definition at line 845 of file PGFimage.cpp.

845  {
846  ASSERT(!m_decoder); // current image must be closed
847  ASSERT(header.quality <= MaxQuality);
848 
849  // init state
850 #ifdef __PGFROISUPPORT__
851  m_streamReinitialized = false;
852 #endif
853 
854  // init preHeader
855  memcpy(m_preHeader.magic, PGFMagic, 3);
856  m_preHeader.version = PGFVersion | flags;
858 
859  // copy header
860  memcpy(&m_header, &header, HeaderSize);
861 
862  // complete header
863  CompleteHeader();
864 
865  // check and set number of levels
866  ComputeLevels();
867 
868  // check for downsample
876  m_downsample = true;
877  m_quant = m_header.quality - 1;
878  } else {
879  m_downsample = false;
881  }
882 
883  // update header size and copy user data
885  // update header size
887  }
888  if (userDataLength && userData) {
889  m_postHeader.userData = new(std::nothrow) UINT8[userDataLength];
890  if (!m_postHeader.userData) ReturnWithError(InsufficientMemory);
891  m_postHeader.userDataLen = userDataLength;
892  memcpy(m_postHeader.userData, userData, userDataLength);
893  // update header size
894  m_preHeader.hSize += userDataLength;
895  }
896 
897  // allocate channels
898  for (int i=0; i < m_header.channels; i++) {
899  // set current width and height
900  m_width[i] = m_header.width;
901  m_height[i] = m_header.height;
902 
903  // allocate channels
904  ASSERT(!m_channel[i]);
905  m_channel[i] = new(std::nothrow) DataT[m_header.width*m_header.height];
906  if (!m_channel[i]) {
907  if (i) i--;
908  while(i) {
909  delete[] m_channel[i]; m_channel[i] = 0;
910  i--;
911  }
912  ReturnWithError(InsufficientMemory);
913  }
914  }
915 }
#define HeaderSize
Definition: PGFtypes.h:231
#define ColorTableSize
Definition: PGFtypes.h:232
#define MaxQuality
maximum quality
Definition: PGFtypes.h:87
void ComputeLevels()
Definition: PGFimage.cpp:805

◆ SetMaxValue()

void CPGFImage::SetMaxValue ( UINT32  maxValue)

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

Parameters
maxValueThe maximum intensity value.

Definition at line 691 of file PGFimage.cpp.

691  {
692  const BYTE bpc = m_header.bpp/m_header.channels;
693  BYTE pot = 0;
694 
695  while(maxValue > 0) {
696  pot++;
697  maxValue >>= 1;
698  }
699  // store bits per channel
700  if (pot > bpc) pot = bpc;
701  if (pot > 31) pot = 31;
703 }

◆ SetProgressMode()

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.

300 { m_progressMode = pm; }

◆ SetRefreshCallback()

void CPGFImage::SetRefreshCallback ( RefreshCB  callback,
void *  arg 
)
inline

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

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

Definition at line 307 of file PGFimage.h.

307 { m_cb = callback; m_cbArg = arg; }

◆ SetROI()

void CPGFImage::SetROI ( PGFRect  rect)
private

◆ UpdatePostHeaderSize()

UINT32 CPGFImage::UpdatePostHeaderSize ( )
private

Definition at line 1068 of file PGFimage.cpp.

1068  {
1069  ASSERT(m_encoder);
1070 
1071  INT64 offset = m_encoder->ComputeOffset(); ASSERT(offset >= 0);
1072 
1073  if (offset > 0) {
1074  // update post-header size and rewrite pre-header
1075  m_preHeader.hSize += (UINT32)offset;
1077  }
1078 
1079  // write dummy levelLength into stream
1081 }
INT64 ComputeOffset() const
Definition: Encoder.h:184
UINT32 WriteLevelLength(UINT32 *&levelLength) THROW_
Definition: Encoder.cpp:177
void UpdatePostHeaderSize(PGFPreHeader preHeader) THROW_
Definition: Encoder.cpp:160

◆ UsedBitsPerChannel()

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

709  {
710  const BYTE bpc = m_header.bpp/m_header.channels;
711 
712  if (bpc > 8) {
714  } else {
715  return bpc;
716  }
717 }

◆ Version()

BYTE CPGFImage::Version ( ) const
inline

Returns images' PGF version

Returns
PGF codec version of the image

Definition at line 476 of file PGFimage.h.

static BYTE CurrentVersion(BYTE version=PGFVersion)
Return version.
Definition: PGFimage.cpp:721

◆ Width()

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

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

Parameters
levelA level
Returns
Image level width in pixels

Definition at line 416 of file PGFimage.h.

416 { ASSERT(level >= 0); return LevelWidth(m_header.width, level); }

◆ Write() [1/2]

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

Definition at line 1164 of file PGFimage.cpp.

1164  {
1165  ASSERT(stream);
1166  ASSERT(m_preHeader.hSize);
1167 
1168  // create wavelet transform channels and encoder
1169  UINT32 nBytes = WriteHeader(stream);
1170 
1171  // write image
1172  nBytes += WriteImage(stream, cb, data);
1173 
1174  // return written bytes
1175  if (nWrittenBytes) *nWrittenBytes += nBytes;
1176 }
UINT32 WriteImage(CPGFStream *stream, CallbackPtr cb=NULL, void *data=NULL) THROW_
Definition: PGFimage.cpp:1093
UINT32 WriteHeader(CPGFStream *stream) THROW_
Definition: PGFimage.cpp:924

◆ Write() [2/2]

UINT32 CPGFImage::Write ( int  level,
CallbackPtr  cb = NULL,
void *  data = NULL 
)

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

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

◆ WriteHeader()

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
streamA PGF stream
Returns
The number of bytes written into stream.

Definition at line 924 of file PGFimage.cpp.

924  {
925  ASSERT(m_header.nLevels <= MaxLevel);
926  ASSERT(m_header.quality <= MaxQuality); // quality is already initialized
927 
928  if (m_header.nLevels > 0) {
929  volatile OSError error = NoError; // volatile prevents optimizations
930  // create new wt channels
931 #ifdef LIBPGF_USE_OPENMP
932  #pragma omp parallel for default(shared)
933 #endif
934  for (int i=0; i < m_header.channels; i++) {
935  DataT *temp = NULL;
936  if (error == NoError) {
937  if (m_wtChannel[i]) {
938  ASSERT(m_channel[i]);
939  // copy m_channel to temp
940  int size = m_height[i]*m_width[i];
941  temp = new(std::nothrow) DataT[size];
942  if (temp) {
943  memcpy(temp, m_channel[i], size*DataTSize);
944  delete m_wtChannel[i]; // also deletes m_channel
945  m_channel[i] = NULL;
946  } else {
947  error = InsufficientMemory;
948  }
949  }
950  if (error == NoError) {
951  if (temp) {
952  ASSERT(!m_channel[i]);
953  m_channel[i] = temp;
954  }
956  if (m_wtChannel[i]) {
957  #ifdef __PGFROISUPPORT__
958  m_wtChannel[i]->SetROI(PGFRect(0, 0, m_width[i], m_height[i]));
959  #endif
960 
961  // wavelet subband decomposition
962  for (int l=0; error == NoError && l < m_header.nLevels; l++) {
963  OSError err = m_wtChannel[i]->ForwardTransform(l, m_quant);
964  if (err != NoError) error = err;
965  }
966  } else {
967  delete[] m_channel[i];
968  error = InsufficientMemory;
969  }
970  }
971  }
972  }
973  if (error != NoError) {
974  // free already allocated memory
975  for (int i=0; i < m_header.channels; i++) {
976  delete m_wtChannel[i];
977  }
978  ReturnWithError(error);
979  }
980 
982 
983  // create encoder and eventually write headers and levelLength
986 
987  #ifdef __PGFROISUPPORT__
988  if (ROIisSupported()) {
989  // new encoding scheme supporting ROI
990  m_encoder->SetROI();
991  }
992  #endif
993 
994  } else {
995  // very small image: we don't use DWT and encoding
996 
997  // create encoder and eventually write headers and levelLength
999  }
1000 
1001  INT64 nBytes = m_encoder->ComputeHeaderLength();
1002  return (nBytes > 0) ? (UINT32)nBytes : 0;
1003 }
PGF encoder.
Definition: Encoder.h:46
INT64 ComputeHeaderLength() const
Definition: Encoder.h:174
void FavorSpeedOverSize()
Encoder favors speed over compression size.
Definition: Encoder.h:121
OSError ForwardTransform(int level, int quant)

◆ WriteImage()

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
streamA PGF stream
cbA pointer to a callback procedure. The procedure is called after writing a single level. If cb returns true, then it stops proceeding.
dataData Pointer to C++ class container to host callback procedure.
Returns
The number of bytes written into stream.

Definition at line 1093 of file PGFimage.cpp.

1093  {
1094  ASSERT(stream);
1095  ASSERT(m_preHeader.hSize);
1096 
1097  int levels = m_header.nLevels;
1098  double percent = pow(0.25, levels);
1099 
1100  // update post-header size, rewrite pre-header, and write dummy levelLength
1101  UINT32 nWrittenBytes = UpdatePostHeaderSize();
1102 
1103  if (levels == 0) {
1104  // write channels
1105  for (int c=0; c < m_header.channels; c++) {
1106  const UINT32 size = m_width[c]*m_height[c];
1107 
1108  // write channel data into stream
1109  for (UINT32 i=0; i < size; i++) {
1110  int count = DataTSize;
1111  stream->Write(&count, &m_channel[c][i]);
1112  }
1113  }
1114 
1115  // now update progress
1116  if (cb) {
1117  if ((*cb)(1, true, data)) ReturnWithError(EscapePressed);
1118  }
1119 
1120  } else {
1121  // encode quantized wavelet coefficients and write to PGF file
1122  // encode subbands, higher levels first
1123  // color channels are interleaved
1124 
1125  // encode all levels
1126  for (m_currentLevel = levels; m_currentLevel > 0; ) {
1127  WriteLevel(); // decrements m_currentLevel
1128 
1129  // now update progress
1130  if (cb) {
1131  percent *= 4;
1132  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1133  }
1134  }
1135 
1136  // flush encoder and write level lengths
1137  m_encoder->Flush();
1138  }
1139 
1140  // update level lengths
1141  nWrittenBytes += m_encoder->UpdateLevelLength(); // return written image bytes
1142 
1143  // delete encoder
1144  delete m_encoder; m_encoder = NULL;
1145 
1146  ASSERT(!m_encoder);
1147 
1148  return nWrittenBytes;
1149 }
void Flush() THROW_
Definition: Encoder.cpp:310
UINT32 UpdateLevelLength() THROW_
Definition: Encoder.cpp:202
UINT32 UpdatePostHeaderSize() THROW_
Definition: PGFimage.cpp:1068
void WriteLevel() THROW_
Definition: PGFimage.cpp:1013
virtual void Write(int *count, void *buffer)=0

◆ WriteLevel()

void CPGFImage::WriteLevel ( )
private

Definition at line 1013 of file PGFimage.cpp.

1013  {
1014  ASSERT(m_encoder);
1015  ASSERT(m_currentLevel > 0);
1016  ASSERT(m_header.nLevels > 0);
1017 
1018 #ifdef __PGFROISUPPORT__
1019  if (ROIisSupported()) {
1020  const int lastChannel = m_header.channels - 1;
1021 
1022  for (int i=0; i < m_header.channels; i++) {
1023  // get number of tiles and tile indices
1024  const UINT32 nTiles = m_wtChannel[i]->GetNofTiles(m_currentLevel);
1025  const UINT32 lastTile = nTiles - 1;
1026 
1027  if (m_currentLevel == m_header.nLevels) {
1028  // last level also has LL band
1029  ASSERT(nTiles == 1);
1031  m_encoder->EncodeTileBuffer();
1032  }
1033  for (UINT32 tileY=0; tileY < nTiles; tileY++) {
1034  for (UINT32 tileX=0; tileX < nTiles; tileX++) {
1035  m_wtChannel[i]->GetSubband(m_currentLevel, HL)->ExtractTile(*m_encoder, true, tileX, tileY);
1036  m_wtChannel[i]->GetSubband(m_currentLevel, LH)->ExtractTile(*m_encoder, true, tileX, tileY);
1037  m_wtChannel[i]->GetSubband(m_currentLevel, HH)->ExtractTile(*m_encoder, true, tileX, tileY);
1038  if (i == lastChannel && tileY == lastTile && tileX == lastTile) {
1039  // all necessary data are buffered. next call of EncodeBuffer will write the last piece of data of the current level.
1041  }
1042  m_encoder->EncodeTileBuffer();
1043  }
1044  }
1045  }
1046  } else
1047 #endif
1048  {
1049  for (int i=0; i < m_header.channels; i++) {
1050  ASSERT(m_wtChannel[i]);
1051  if (m_currentLevel == m_header.nLevels) {
1052  // last level also has LL band
1054  }
1055  //encoder.EncodeInterleaved(m_wtChannel[i], m_currentLevel, m_quant); // until version 4
1056  m_wtChannel[i]->GetSubband(m_currentLevel, HL)->ExtractTile(*m_encoder); // since version 5
1057  m_wtChannel[i]->GetSubband(m_currentLevel, LH)->ExtractTile(*m_encoder); // since version 5
1059  }
1060 
1061  // all necessary data are buffered. next call of EncodeBuffer will write the last piece of data of the current level.
1063  }
1064 }
void SetEncodedLevel(int currentLevel)
Definition: Encoder.h:162
void ExtractTile(CEncoder &encoder, bool tile=false, UINT32 tileX=0, UINT32 tileY=0) THROW_
Definition: Subband.cpp:177

Member Data Documentation

◆ m_cb

RefreshCB CPGFImage::m_cb
private

pointer to refresh callback procedure

Definition at line 535 of file PGFimage.h.

◆ m_cbArg

void* CPGFImage::m_cbArg
private

refresh callback argument

Definition at line 536 of file PGFimage.h.

◆ m_channel

DataT* CPGFImage::m_channel[MaxChannels]
protected

untransformed channels in YUV format

Definition at line 512 of file PGFimage.h.

◆ m_currentLevel

int CPGFImage::m_currentLevel
protected

transform level of current image

Definition at line 522 of file PGFimage.h.

◆ m_decoder

CDecoder* CPGFImage::m_decoder
protected

PGF decoder.

Definition at line 513 of file PGFimage.h.

◆ m_downsample

bool CPGFImage::m_downsample
protected

chrominance channels are downsampled

Definition at line 524 of file PGFimage.h.

◆ m_encoder

CEncoder* CPGFImage::m_encoder
protected

PGF encoder.

Definition at line 514 of file PGFimage.h.

◆ m_favorSpeedOverSize

bool CPGFImage::m_favorSpeedOverSize
protected

favor encoding speed over compression ratio

Definition at line 525 of file PGFimage.h.

◆ m_header

PGFHeader CPGFImage::m_header
protected

PGF file header.

Definition at line 519 of file PGFimage.h.

◆ m_height

UINT32 CPGFImage::m_height[MaxChannels]
protected

height of each channel at current level

Definition at line 517 of file PGFimage.h.

◆ m_levelLength

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.

◆ m_percent

double CPGFImage::m_percent
private

progress [0..1]

Definition at line 537 of file PGFimage.h.

◆ m_postHeader

PGFPostHeader CPGFImage::m_postHeader
protected

PGF post-header.

Definition at line 520 of file PGFimage.h.

◆ m_preHeader

PGFPreHeader CPGFImage::m_preHeader
protected

PGF pre-header.

Definition at line 518 of file PGFimage.h.

◆ m_progressMode

ProgressMode CPGFImage::m_progressMode
private

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

Definition at line 538 of file PGFimage.h.

◆ m_quant

BYTE CPGFImage::m_quant
protected

quantization parameter

Definition at line 523 of file PGFimage.h.

◆ m_roi

PGFRect CPGFImage::m_roi
protected

region of interest

Definition at line 531 of file PGFimage.h.

◆ m_skipUserData

bool CPGFImage::m_skipUserData
protected

skip user data (metadata) during open

Definition at line 528 of file PGFimage.h.

◆ m_streamReinitialized

bool CPGFImage::m_streamReinitialized
protected

stream has been reinitialized

Definition at line 530 of file PGFimage.h.

◆ m_useOMPinDecoder

bool CPGFImage::m_useOMPinDecoder
protected

use Open MP in decoder

Definition at line 527 of file PGFimage.h.

◆ m_useOMPinEncoder

bool CPGFImage::m_useOMPinEncoder
protected

use Open MP in encoder

Definition at line 526 of file PGFimage.h.

◆ m_userDataPos

UINT64 CPGFImage::m_userDataPos
protected

stream position of user data

Definition at line 521 of file PGFimage.h.

◆ m_width

UINT32 CPGFImage::m_width[MaxChannels]
protected

width of each channel at current level

Definition at line 516 of file PGFimage.h.

◆ m_wtChannel

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: