libpgf  7.21.2
PGF - Progressive Graphics File
CPGFImage Class Reference

PGF main class. More...

#include <PGFimage.h>

Public Member Functions

 CPGFImage ()
 Standard constructor. More...
 
virtual ~CPGFImage ()
 Destructor. More...
 
void Destroy ()
 
void Open (CPGFStream *stream)
 
bool IsOpen () const
 Returns true if the PGF has been opened for reading. More...
 
void Read (int level=0, CallbackPtr cb=nullptr, void *data=nullptr)
 
void Read (PGFRect &rect, int level=0, CallbackPtr cb=nullptr, void *data=nullptr)
 
void ReadPreview ()
 
void Reconstruct (int level=0)
 
void GetBitmap (int pitch, UINT8 *buff, BYTE bpp, int channelMap[]=nullptr, CallbackPtr cb=nullptr, void *data=nullptr) const
 
void GetYUV (int pitch, DataT *buff, BYTE bpp, int channelMap[]=nullptr, CallbackPtr cb=nullptr, void *data=nullptr) const
 
void ImportBitmap (int pitch, UINT8 *buff, BYTE bpp, int channelMap[]=nullptr, CallbackPtr cb=nullptr, void *data=nullptr)
 
void ImportYUV (int pitch, DataT *buff, BYTE bpp, int channelMap[]=nullptr, CallbackPtr cb=nullptr, void *data=nullptr)
 
void Write (CPGFStream *stream, UINT32 *nWrittenBytes=nullptr, CallbackPtr cb=nullptr, void *data=nullptr)
 
UINT32 WriteHeader (CPGFStream *stream)
 
UINT32 WriteImage (CPGFStream *stream, CallbackPtr cb=nullptr, void *data=nullptr)
 
UINT32 Write (int level, CallbackPtr cb=nullptr, void *data=nullptr)
 
void ConfigureEncoder (bool useOMP=true, bool favorSpeedOverSize=false)
 
void ConfigureDecoder (bool useOMP=true, UserdataPolicy policy=UP_CacheAll, UINT32 prefixSize=0)
 
void ResetStreamPos (bool startOfData)
 
void SetChannel (DataT *channel, int c=0)
 
void SetHeader (const PGFHeader &header, BYTE flags=0, const UINT8 *userData=0, UINT32 userDataLength=0)
 
void SetMaxValue (UINT32 maxValue)
 
void SetProgressMode (ProgressMode pm)
 
void SetRefreshCallback (RefreshCB callback, void *arg)
 
void SetColorTable (UINT32 iFirstColor, UINT32 nColors, const RGBQUAD *prgbColors)
 
DataTGetChannel (int c=0)
 
void GetColorTable (UINT32 iFirstColor, UINT32 nColors, RGBQUAD *prgbColors) const
 
const RGBQUAD * GetColorTable () const
 
const PGFHeaderGetHeader () const
 
UINT32 GetMaxValue () const
 
UINT64 GetUserDataPos () const
 
const UINT8 * GetUserData (UINT32 &cachedSize, UINT32 *pTotalSize=nullptr) const
 
UINT32 GetEncodedHeaderLength () const
 
UINT32 GetEncodedLevelLength (int level) const
 
UINT32 ReadEncodedHeader (UINT8 *target, UINT32 targetLen) const
 
UINT32 ReadEncodedData (int level, UINT8 *target, UINT32 targetLen) const
 
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
 
bool IsFullyRead () const
 Return true if all levels have been read. More...
 
BYTE Quality () const
 
BYTE Channels () const
 
BYTE Mode () const
 
BYTE BPP () const
 
bool ROIisSupported () const
 
PGFRect ComputeLevelROI () const
 
BYTE UsedBitsPerChannel () const
 
BYTE Version () const
 

Static Public Member Functions

static bool ImportIsSupported (BYTE mode)
 
static UINT32 LevelSizeL (UINT32 size, int level)
 
static UINT32 LevelSizeH (UINT32 size, int level)
 
static BYTE CodecMajorVersion (BYTE version=PGFVersion)
 Return major version. More...
 
static BYTE MaxChannelDepth (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...
 
UINT32 m_userDataPolicy
 user data (metadata) policy during open 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_streamReinitialized
 stream has been reinitialized More...
 
PGFRect m_roi
 region of interest More...
 

Private Member Functions

void Init ()
 
void ComputeLevels ()
 
bool CompleteHeader ()
 
void RgbToYuv (int pitch, UINT8 *rgbBuff, BYTE bpp, int channelMap[], CallbackPtr cb, void *data)
 
void Downsample (int nChannel)
 
UINT32 UpdatePostHeaderSize ()
 
void WriteLevel ()
 
PGFRect GetAlignedROI (int c=0) const
 
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: Open() Read() GetBitmap() Encoding: SetHeader() ImportBitmap() Write()

Author
C. Stamm, R. Spuler

Definition at line 53 of file PGFimage.h.

Constructor & Destructor Documentation

◆ CPGFImage()

CPGFImage::CPGFImage ( )

Standard constructor.

Definition at line 64 of file PGFimage.cpp.

64  {
65  Init();
66 }
void Init()
Definition: PGFimage.cpp:69

◆ ~CPGFImage()

CPGFImage::~CPGFImage ( )
virtual

Destructor.

Definition at line 117 of file PGFimage.cpp.

117  {
118  m_currentLevel = -100; // unusual value used as marker in Destroy()
119  Destroy();
120 }
void Destroy()
Definition: PGFimage.cpp:124
int m_currentLevel
transform level of current image
Definition: PGFimage.h:532

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

461 { return m_header.bpp; }
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
UINT8 bpp
bits per pixel
Definition: PGFtypes.h:157

◆ ChannelDepth()

BYTE CPGFImage::ChannelDepth ( ) const
inline

Return bits per channel of the image's encoder.

Returns
Bits per channel

Definition at line 406 of file PGFimage.h.

UINT8 version
PGF version.
Definition: PGFtypes.h:115
PGFPreHeader m_preHeader
PGF pre-header.
Definition: PGFimage.h:528
static BYTE MaxChannelDepth(BYTE version=PGFVersion)
Definition: PGFimage.h:518

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

401 { ASSERT(c >= 0 && c < MaxChannels); return m_height[c]; }
#define MaxChannels
maximum number of (color) channels
Definition: PGFtypes.h:64
UINT32 m_height[MaxChannels]
height of each channel at current level
Definition: PGFimage.h:527

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

448 { return m_header.channels; }
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
UINT8 channels
number of channels
Definition: PGFtypes.h:158

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

394 { ASSERT(c >= 0 && c < MaxChannels); return m_width[c]; }
#define MaxChannels
maximum number of (color) channels
Definition: PGFtypes.h:64
UINT32 m_width[MaxChannels]
width of each channel at current level
Definition: PGFimage.h:526

◆ Clamp16()

UINT16 CPGFImage::Clamp16 ( DataT  v) const
inlineprivate

Definition at line 573 of file PGFimage.h.

573  {
574  if (v & 0xFFFF0000) return (v < 0) ? (UINT16)0: (UINT16)65535; else return (UINT16)v;
575  }

◆ Clamp31()

UINT32 CPGFImage::Clamp31 ( DataT  v) const
inlineprivate

Definition at line 576 of file PGFimage.h.

576  {
577  return (v < 0) ? 0 : (UINT32)v;
578  }

◆ Clamp4()

UINT8 CPGFImage::Clamp4 ( DataT  v) const
inlineprivate

Definition at line 563 of file PGFimage.h.

563  {
564  if (v & 0xFFFFFFF0) return (v < 0) ? (UINT8)0: (UINT8)15; else return (UINT8)v;
565  }

◆ Clamp6()

UINT16 CPGFImage::Clamp6 ( DataT  v) const
inlineprivate

Definition at line 566 of file PGFimage.h.

566  {
567  if (v & 0xFFFFFFC0) return (v < 0) ? (UINT16)0: (UINT16)63; else return (UINT16)v;
568  }

◆ Clamp8()

UINT8 CPGFImage::Clamp8 ( DataT  v) const
inlineprivate

Definition at line 569 of file PGFimage.h.

569  {
570  // needs only one test in the normal case
571  if (v & 0xFFFFFF00) return (v < 0) ? (UINT8)0 : (UINT8)255; else return (UINT8)v;
572  }

◆ CodecMajorVersion()

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

Return major version.

Return codec major version.

Parameters
versionpgf pre-header version number
Returns
PGF major of given version

Definition at line 768 of file PGFimage.cpp.

768  {
769  if (version & Version7) return 7;
770  if (version & Version6) return 6;
771  if (version & Version5) return 5;
772  if (version & Version2) return 2;
773  return 1;
774 }
#define Version6
hSize in PGFPreHeader uses 32 bits instead of 16 bits
Definition: PGFtypes.h:72
#define Version2
data structure PGFHeader of major version 2
Definition: PGFtypes.h:68
#define Version7
Codec major and minor version number stored in PGFHeader.
Definition: PGFtypes.h:73
#define Version5
new coding scheme since major version 5
Definition: PGFtypes.h:71

◆ CompleteHeader()

bool CPGFImage::CompleteHeader ( )
private

Definition at line 218 of file PGFimage.cpp.

218  {
219  // set current codec version
221 
222  if (m_header.mode == ImageModeUnknown) {
223  // undefined mode
224  switch(m_header.bpp) {
225  case 1: m_header.mode = ImageModeBitmap; break;
226  case 8: m_header.mode = ImageModeGrayScale; break;
227  case 12: m_header.mode = ImageModeRGB12; break;
228  case 16: m_header.mode = ImageModeRGB16; break;
229  case 24: m_header.mode = ImageModeRGBColor; break;
230  case 32: m_header.mode = ImageModeRGBA; break;
231  case 48: m_header.mode = ImageModeRGB48; break;
232  default: m_header.mode = ImageModeRGBColor; break;
233  }
234  }
235  if (!m_header.bpp) {
236  // undefined bpp
237  switch(m_header.mode) {
238  case ImageModeBitmap:
239  m_header.bpp = 1;
240  break;
242  case ImageModeGrayScale:
243  m_header.bpp = 8;
244  break;
245  case ImageModeRGB12:
246  m_header.bpp = 12;
247  break;
248  case ImageModeRGB16:
249  case ImageModeGray16:
250  m_header.bpp = 16;
251  break;
252  case ImageModeRGBColor:
253  case ImageModeLabColor:
254  m_header.bpp = 24;
255  break;
256  case ImageModeRGBA:
257  case ImageModeCMYKColor:
258  case ImageModeGray32:
259  m_header.bpp = 32;
260  break;
261  case ImageModeRGB48:
262  case ImageModeLab48:
263  m_header.bpp = 48;
264  break;
265  case ImageModeCMYK64:
266  m_header.bpp = 64;
267  break;
268  default:
269  ASSERT(false);
270  m_header.bpp = 24;
271  }
272  }
273  if (m_header.mode == ImageModeRGBColor && m_header.bpp == 32) {
274  // change mode
276  }
277  if (m_header.mode == ImageModeBitmap && m_header.bpp != 1) return false;
278  if (m_header.mode == ImageModeIndexedColor && m_header.bpp != 8) return false;
279  if (m_header.mode == ImageModeGrayScale && m_header.bpp != 8) return false;
280  if (m_header.mode == ImageModeGray16 && m_header.bpp != 16) return false;
281  if (m_header.mode == ImageModeGray32 && m_header.bpp != 32) return false;
282  if (m_header.mode == ImageModeRGBColor && m_header.bpp != 24) return false;
283  if (m_header.mode == ImageModeRGBA && m_header.bpp != 32) return false;
284  if (m_header.mode == ImageModeRGB12 && m_header.bpp != 12) return false;
285  if (m_header.mode == ImageModeRGB16 && m_header.bpp != 16) return false;
286  if (m_header.mode == ImageModeRGB48 && m_header.bpp != 48) return false;
287  if (m_header.mode == ImageModeLabColor && m_header.bpp != 24) return false;
288  if (m_header.mode == ImageModeLab48 && m_header.bpp != 48) return false;
289  if (m_header.mode == ImageModeCMYKColor && m_header.bpp != 32) return false;
290  if (m_header.mode == ImageModeCMYK64 && m_header.bpp != 64) return false;
291 
292  // set number of channels
293  if (!m_header.channels) {
294  switch(m_header.mode) {
295  case ImageModeBitmap:
297  case ImageModeGrayScale:
298  case ImageModeGray16:
299  case ImageModeGray32:
300  m_header.channels = 1;
301  break;
302  case ImageModeRGBColor:
303  case ImageModeRGB12:
304  case ImageModeRGB16:
305  case ImageModeRGB48:
306  case ImageModeLabColor:
307  case ImageModeLab48:
308  m_header.channels = 3;
309  break;
310  case ImageModeRGBA:
311  case ImageModeCMYKColor:
312  case ImageModeCMYK64:
313  m_header.channels = 4;
314  break;
315  default:
316  return false;
317  }
318  }
319 
320  // store used bits per channel
321  UINT8 bpc = m_header.bpp/m_header.channels;
322  if (bpc > 31) bpc = 31;
325  }
326 
327  return true;
328 }
#define ImageModeIndexedColor
Definition: PGFplatform.h:100
#define ImageModeRGB12
Definition: PGFplatform.h:117
UINT8 mode
image mode according to Adobe's image modes
Definition: PGFtypes.h:159
#define PGFYear
Definition: PGFtypes.h:45
#define PGFMajorNumber
Definition: PGFtypes.h:44
#define ImageModeRGBA
Definition: PGFplatform.h:115
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
#define ImageModeLabColor
Definition: PGFplatform.h:107
#define ImageModeGray16
Definition: PGFplatform.h:108
UINT8 usedBitsPerChannel
number of used bits per channel in 16- and 32-bit per channel modes
Definition: PGFtypes.h:160
#define ImageModeLab48
Definition: PGFplatform.h:110
#define ImageModeCMYKColor
Definition: PGFplatform.h:102
#define ImageModeGrayScale
Definition: PGFplatform.h:99
UINT8 bpp
bits per pixel
Definition: PGFtypes.h:157
#define PGFWeek
Definition: PGFtypes.h:46
#define ImageModeGray32
Definition: PGFplatform.h:116
#define ImageModeUnknown
Definition: PGFplatform.h:119
#define ImageModeRGBColor
Definition: PGFplatform.h:101
#define ImageModeBitmap
Definition: PGFplatform.h:98
UINT8 channels
number of channels
Definition: PGFtypes.h:158
PGFVersionNumber version
codec version number: (since Version 7)
Definition: PGFtypes.h:161
#define ImageModeCMYK64
Definition: PGFplatform.h:111
#define ImageModeRGB16
Definition: PGFplatform.h:118
#define ImageModeRGB48
Definition: PGFplatform.h:109
version number stored in header since major version 7
Definition: PGFtypes.h:132

◆ ComputeLevelROI()

PGFRect CPGFImage::ComputeLevelROI ( ) const

Return ROI of channel 0 at current level in pixels. The returned rect is only valid after reading a ROI.

Returns
ROI in pixels

◆ ComputeLevels()

void CPGFImage::ComputeLevels ( )
private

Definition at line 854 of file PGFimage.cpp.

854  {
855  const int maxThumbnailWidth = 20*FilterSize;
856  const int m = __min(m_header.width, m_header.height);
857  int s = m;
858 
859  if (m_header.nLevels < 1 || m_header.nLevels > MaxLevel) {
860  m_header.nLevels = 1;
861  // compute a good value depending on the size of the image
862  while (s > maxThumbnailWidth) {
863  m_header.nLevels++;
864  s >>= 1;
865  }
866  }
867 
868  int levels = m_header.nLevels; // we need a signed value during level reduction
869 
870  // reduce number of levels if the image size is smaller than FilterSize*(2^levels)
871  s = FilterSize*(1 << levels); // must be at least the double filter size because of subsampling
872  while (m < s) {
873  levels--;
874  s >>= 1;
875  }
876  if (levels > MaxLevel) m_header.nLevels = MaxLevel;
877  else if (levels < 0) m_header.nLevels = 0;
878  else m_header.nLevels = (UINT8)levels;
879 
880  // used in Write when PM_Absolute
881  m_percent = pow(0.25, m_header.nLevels);
882 
883  ASSERT(0 <= m_header.nLevels && m_header.nLevels <= MaxLevel);
884 }
UINT32 width
image width in pixels
Definition: PGFtypes.h:153
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
const UINT32 FilterSize
UINT8 nLevels
number of FWT transforms
Definition: PGFtypes.h:155
#define MaxLevel
maximum number of transform levels
Definition: PGFtypes.h:62
#define __min(x, y)
Definition: PGFplatform.h:91
double m_percent
progress [0..1]
Definition: PGFimage.h:547
UINT32 height
image height in pixels
Definition: PGFtypes.h:154

◆ ConfigureDecoder()

void CPGFImage::ConfigureDecoder ( bool  useOMP = true,
UserdataPolicy  policy = UP_CacheAll,
UINT32  prefixSize = 0 
)
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.
policyThe file might contain user data (e.g. metadata). The policy defines the behaviour during Open(). UP_CacheAll: User data is read and stored completely in a new allocated memory block. It can be accessed by GetUserData(). UP_CachePrefix: Only prefixSize bytes at the beginning of the user data are stored in a new allocated memory block. It can be accessed by GetUserData(). UP_Skip: User data is skipped and nothing is cached.
prefixSizeIs only used in combination with UP_CachePrefix. It defines the number of bytes cached.

Definition at line 260 of file PGFimage.h.

260 { ASSERT(prefixSize <= MaxUserDataSize); m_useOMPinDecoder = useOMP; m_userDataPolicy = (UP_CachePrefix) ? prefixSize : 0xFFFFFFFF - policy; }
bool m_useOMPinDecoder
use Open MP in decoder
Definition: PGFimage.h:538
UINT32 m_userDataPolicy
user data (metadata) policy during open
Definition: PGFimage.h:533
#define MaxUserDataSize
Definition: PGFtypes.h:284

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

250 { m_useOMPinEncoder = useOMP; m_favorSpeedOverSize = favorSpeedOverSize; }
bool m_favorSpeedOverSize
favor encoding speed over compression ratio
Definition: PGFimage.h:536
bool m_useOMPinEncoder
use Open MP in encoder
Definition: PGFimage.h:537

◆ Destroy()

void CPGFImage::Destroy ( )

Definition at line 124 of file PGFimage.cpp.

124  {
125  for (int i = 0; i < m_header.channels; i++) {
126  delete m_wtChannel[i]; // also deletes m_channel
127  }
128  delete[] m_postHeader.userData;
129  delete[] m_levelLength;
130  delete m_decoder;
131  delete m_encoder;
132 
133  if (m_currentLevel != -100) Init();
134 }
CDecoder * m_decoder
PGF decoder.
Definition: PGFimage.h:523
UINT8 * userData
user data of size userDataLen (optional part of file header)
Definition: PGFtypes.h:171
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
CWaveletTransform * m_wtChannel[MaxChannels]
wavelet transformed color channels
Definition: PGFimage.h:521
PGFPostHeader m_postHeader
PGF post-header.
Definition: PGFimage.h:530
void Init()
Definition: PGFimage.cpp:69
UINT32 * m_levelLength
length of each level in bytes; first level starts immediately after this array
Definition: PGFimage.h:525
UINT8 channels
number of channels
Definition: PGFtypes.h:158
CEncoder * m_encoder
PGF encoder.
Definition: PGFimage.h:524
int m_currentLevel
transform level of current image
Definition: PGFimage.h:532

◆ Downsample()

void CPGFImage::Downsample ( int  nChannel)
private

Definition at line 810 of file PGFimage.cpp.

810  {
811  ASSERT(ch > 0);
812 
813  const int w = m_width[0];
814  const int w2 = w/2;
815  const int h2 = m_height[0]/2;
816  const int oddW = w%2; // don't use bool -> problems with MaxSpeed optimization
817  const int oddH = m_height[0]%2; // "
818  int loPos = 0;
819  int hiPos = w;
820  int sampledPos = 0;
821  DataT* buff = m_channel[ch]; ASSERT(buff);
822 
823  for (int i=0; i < h2; i++) {
824  for (int j=0; j < w2; j++) {
825  // compute average of pixel block
826  buff[sampledPos] = (buff[loPos] + buff[loPos + 1] + buff[hiPos] + buff[hiPos + 1]) >> 2;
827  loPos += 2; hiPos += 2;
828  sampledPos++;
829  }
830  if (oddW) {
831  buff[sampledPos] = (buff[loPos] + buff[hiPos]) >> 1;
832  loPos++; hiPos++;
833  sampledPos++;
834  }
835  loPos += w; hiPos += w;
836  }
837  if (oddH) {
838  for (int j=0; j < w2; j++) {
839  buff[sampledPos] = (buff[loPos] + buff[loPos+1]) >> 1;
840  loPos += 2; hiPos += 2;
841  sampledPos++;
842  }
843  if (oddW) {
844  buff[sampledPos] = buff[loPos];
845  }
846  }
847 
848  // downsampled image has half width and half height
849  m_width[ch] = (m_width[ch] + 1)/2;
850  m_height[ch] = (m_height[ch] + 1)/2;
851 }
INT32 DataT
Definition: PGFtypes.h:269
DataT * m_channel[MaxChannels]
untransformed channels in YUV format
Definition: PGFimage.h:522
UINT32 m_width[MaxChannels]
width of each channel at current level
Definition: PGFimage.h:526
UINT32 m_height[MaxChannels]
height of each channel at current level
Definition: PGFimage.h:527

◆ GetAlignedROI()

PGFRect CPGFImage::GetAlignedROI ( int  c = 0) const
private

◆ GetBitmap()

void CPGFImage::GetBitmap ( int  pitch,
UINT8 *  buff,
BYTE  bpp,
int  channelMap[] = nullptr,
CallbackPtr  cb = nullptr,
void *  data = nullptr 
) 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 1789 of file PGFimage.cpp.

1789  {
1790  ASSERT(buff);
1791  UINT32 w = m_width[0]; // width of decoded image
1792  UINT32 h = m_height[0]; // height of decoded image
1793  UINT32 yw = w; // y-channel width
1794  UINT32 uw = m_width[1]; // u-channel width
1795  UINT32 roiOffsetX = 0;
1796  UINT32 roiOffsetY = 0;
1797  UINT32 yOffset = 0;
1798  UINT32 uOffset = 0;
1799 
1800 #ifdef __PGFROISUPPORT__
1801  const PGFRect& roi = GetAlignedROI(); // in pixels, roi is usually larger than levelRoi
1802  ASSERT(w == roi.Width() && h == roi.Height());
1803  const PGFRect levelRoi = ComputeLevelROI();
1804  ASSERT(roi.left <= levelRoi.left && levelRoi.right <= roi.right);
1805  ASSERT(roi.top <= levelRoi.top && levelRoi.bottom <= roi.bottom);
1806 
1807  if (ROIisSupported() && (levelRoi.Width() < w || levelRoi.Height() < h)) {
1808  // ROI is used
1809  w = levelRoi.Width();
1810  h = levelRoi.Height();
1811  roiOffsetX = levelRoi.left - roi.left;
1812  roiOffsetY = levelRoi.top - roi.top;
1813  yOffset = roiOffsetX + roiOffsetY*yw;
1814 
1815  if (m_downsample) {
1816  const PGFRect& downsampledRoi = GetAlignedROI(1);
1817  uOffset = levelRoi.left/2 - downsampledRoi.left + (levelRoi.top/2 - downsampledRoi.top)*m_width[1];
1818  } else {
1819  uOffset = yOffset;
1820  }
1821  }
1822 #endif
1823 
1824  const double dP = 1.0/h;
1825  int defMap[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; ASSERT(sizeof(defMap)/sizeof(defMap[0]) == MaxChannels);
1826  if (channelMap == nullptr) channelMap = defMap;
1827  DataT uAvg, vAvg;
1828  double percent = 0;
1829  UINT32 i, j;
1830 
1831  switch(m_header.mode) {
1832  case ImageModeBitmap:
1833  {
1834  ASSERT(m_header.channels == 1);
1835  ASSERT(m_header.bpp == 1);
1836  ASSERT(bpp == 1);
1837 
1838  const UINT32 w2 = (w + 7)/8;
1839  DataT* y = m_channel[0]; ASSERT(y);
1840 
1841  if (m_preHeader.version & Version7) {
1842  // new unpacked version has a little better compression ratio
1843  // since version 7
1844  for (i = 0; i < h; i++) {
1845  UINT32 cnt = 0;
1846  for (j = 0; j < w2; j++) {
1847  UINT8 byte = 0;
1848  for (int k = 0; k < 8; k++) {
1849  byte <<= 1;
1850  UINT8 bit = 0;
1851  if (cnt < w) {
1852  bit = y[yOffset + cnt] & 1;
1853  }
1854  byte |= bit;
1855  cnt++;
1856  }
1857  buff[j] = byte;
1858  }
1859  yOffset += yw;
1860  buff += pitch;
1861 
1862  if (cb) {
1863  percent += dP;
1864  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1865  }
1866  }
1867  } else {
1868  // old versions
1869  // packed pixels: 8 pixel in 1 byte of channel[0]
1870  if (!(m_preHeader.version & Version5)) yw = w2; // not version 5 or 6
1871  yOffset = roiOffsetX/8 + roiOffsetY*yw; // 1 byte in y contains 8 pixel values
1872  for (i = 0; i < h; i++) {
1873  for (j = 0; j < w2; j++) {
1874  buff[j] = Clamp8(y[yOffset + j] + YUVoffset8);
1875  }
1876  yOffset += yw;
1877  buff += pitch;
1878 
1879  if (cb) {
1880  percent += dP;
1881  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1882  }
1883  }
1884  }
1885  break;
1886  }
1887  case ImageModeIndexedColor:
1888  case ImageModeGrayScale:
1889  case ImageModeHSLColor:
1890  case ImageModeHSBColor:
1891  {
1892  ASSERT(m_header.channels >= 1);
1893  ASSERT(m_header.bpp == m_header.channels*8);
1894  ASSERT(bpp%8 == 0);
1895 
1896  UINT32 cnt, channels = bpp/8; ASSERT(channels >= m_header.channels);
1897 
1898  for (i=0; i < h; i++) {
1899  UINT32 yPos = yOffset;
1900  cnt = 0;
1901  for (j=0; j < w; j++) {
1902  for (UINT32 c=0; c < m_header.channels; c++) {
1903  buff[cnt + channelMap[c]] = Clamp8(m_channel[c][yPos] + YUVoffset8);
1904  }
1905  cnt += channels;
1906  yPos++;
1907  }
1908  yOffset += yw;
1909  buff += pitch;
1910 
1911  if (cb) {
1912  percent += dP;
1913  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1914  }
1915  }
1916  break;
1917  }
1918  case ImageModeGray16:
1919  {
1920  ASSERT(m_header.channels >= 1);
1921  ASSERT(m_header.bpp == m_header.channels*16);
1922 
1923  const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
1924  UINT32 cnt, channels;
1925 
1926  if (bpp%16 == 0) {
1927  const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
1928  UINT16 *buff16 = (UINT16 *)buff;
1929  int pitch16 = pitch/2;
1930  channels = bpp/16; ASSERT(channels >= m_header.channels);
1931 
1932  for (i=0; i < h; i++) {
1933  UINT32 yPos = yOffset;
1934  cnt = 0;
1935  for (j=0; j < w; j++) {
1936  for (UINT32 c=0; c < m_header.channels; c++) {
1937  buff16[cnt + channelMap[c]] = Clamp16((m_channel[c][yPos] + yuvOffset16) << shift);
1938  }
1939  cnt += channels;
1940  yPos++;
1941  }
1942  yOffset += yw;
1943  buff16 += pitch16;
1944 
1945  if (cb) {
1946  percent += dP;
1947  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1948  }
1949  }
1950  } else {
1951  ASSERT(bpp%8 == 0);
1952  const int shift = __max(0, UsedBitsPerChannel() - 8);
1953  channels = bpp/8; ASSERT(channels >= m_header.channels);
1954 
1955  for (i=0; i < h; i++) {
1956  UINT32 yPos = yOffset;
1957  cnt = 0;
1958  for (j=0; j < w; j++) {
1959  for (UINT32 c=0; c < m_header.channels; c++) {
1960  buff[cnt + channelMap[c]] = Clamp8((m_channel[c][yPos] + yuvOffset16) >> shift);
1961  }
1962  cnt += channels;
1963  yPos++;
1964  }
1965  yOffset += yw;
1966  buff += pitch;
1967 
1968  if (cb) {
1969  percent += dP;
1970  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1971  }
1972  }
1973  }
1974  break;
1975  }
1976  case ImageModeRGBColor:
1977  {
1978  ASSERT(m_header.channels == 3);
1979  ASSERT(m_header.bpp == m_header.channels*8);
1980  ASSERT(bpp%8 == 0);
1981  ASSERT(bpp >= m_header.bpp);
1982 
1983  DataT* y = m_channel[0]; ASSERT(y);
1984  DataT* u = m_channel[1]; ASSERT(u);
1985  DataT* v = m_channel[2]; ASSERT(v);
1986  UINT8 *buffg = &buff[channelMap[1]],
1987  *buffr = &buff[channelMap[2]],
1988  *buffb = &buff[channelMap[0]];
1989  UINT8 g;
1990  UINT32 cnt, channels = bpp/8;
1991 
1992  if (m_downsample) {
1993  for (i=0; i < h; i++) {
1994  UINT32 uPos = uOffset;
1995  UINT32 yPos = yOffset;
1996  cnt = 0;
1997  for (j=0; j < w; j++) {
1998  // u and v are downsampled
1999  uAvg = u[uPos];
2000  vAvg = v[uPos];
2001  // Yuv
2002  buffg[cnt] = g = Clamp8(y[yPos] + YUVoffset8 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
2003  buffr[cnt] = Clamp8(uAvg + g);
2004  buffb[cnt] = Clamp8(vAvg + g);
2005  cnt += channels;
2006  if (j & 1) uPos++;
2007  yPos++;
2008  }
2009  if (i & 1) uOffset += uw;
2010  yOffset += yw;
2011  buffb += pitch;
2012  buffg += pitch;
2013  buffr += pitch;
2014 
2015  if (cb) {
2016  percent += dP;
2017  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2018  }
2019  }
2020 
2021  } else {
2022  for (i=0; i < h; i++) {
2023  cnt = 0;
2024  UINT32 yPos = yOffset;
2025  for (j = 0; j < w; j++) {
2026  uAvg = u[yPos];
2027  vAvg = v[yPos];
2028  // Yuv
2029  buffg[cnt] = g = Clamp8(y[yPos] + YUVoffset8 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
2030  buffr[cnt] = Clamp8(uAvg + g);
2031  buffb[cnt] = Clamp8(vAvg + g);
2032  cnt += channels;
2033  yPos++;
2034  }
2035  yOffset += yw;
2036  buffb += pitch;
2037  buffg += pitch;
2038  buffr += pitch;
2039 
2040  if (cb) {
2041  percent += dP;
2042  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2043  }
2044  }
2045  }
2046  break;
2047  }
2048  case ImageModeRGB48:
2049  {
2050  ASSERT(m_header.channels == 3);
2051  ASSERT(m_header.bpp == 48);
2052 
2053  const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
2054 
2055  DataT* y = m_channel[0]; ASSERT(y);
2056  DataT* u = m_channel[1]; ASSERT(u);
2057  DataT* v = m_channel[2]; ASSERT(v);
2058  UINT32 cnt, channels;
2059  DataT g;
2060 
2061  if (bpp >= 48 && bpp%16 == 0) {
2062  const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
2063  UINT16 *buff16 = (UINT16 *)buff;
2064  int pitch16 = pitch/2;
2065  channels = bpp/16; ASSERT(channels >= m_header.channels);
2066 
2067  for (i=0; i < h; i++) {
2068  UINT32 uPos = uOffset;
2069  UINT32 yPos = yOffset;
2070  cnt = 0;
2071  for (j=0; j < w; j++) {
2072  uAvg = u[uPos];
2073  vAvg = v[uPos];
2074  // Yuv
2075  g = y[yPos] + yuvOffset16 - ((uAvg + vAvg ) >> 2); // must be logical shift operator
2076  buff16[cnt + channelMap[1]] = Clamp16(g << shift);
2077  buff16[cnt + channelMap[2]] = Clamp16((uAvg + g) << shift);
2078  buff16[cnt + channelMap[0]] = Clamp16((vAvg + g) << shift);
2079  cnt += channels;
2080  if (!m_downsample || (j & 1)) uPos++;
2081  yPos++;
2082  }
2083  if (!m_downsample || (i & 1)) uOffset += uw;
2084  yOffset += yw;
2085  buff16 += pitch16;
2086 
2087  if (cb) {
2088  percent += dP;
2089  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2090  }
2091  }
2092  } else {
2093  ASSERT(bpp%8 == 0);
2094  const int shift = __max(0, UsedBitsPerChannel() - 8);
2095  channels = bpp/8; ASSERT(channels >= m_header.channels);
2096 
2097  for (i=0; i < h; i++) {
2098  UINT32 uPos = uOffset;
2099  UINT32 yPos = yOffset;
2100  cnt = 0;
2101  for (j=0; j < w; j++) {
2102  uAvg = u[uPos];
2103  vAvg = v[uPos];
2104  // Yuv
2105  g = y[yPos] + yuvOffset16 - ((uAvg + vAvg ) >> 2); // must be logical shift operator
2106  buff[cnt + channelMap[1]] = Clamp8(g >> shift);
2107  buff[cnt + channelMap[2]] = Clamp8((uAvg + g) >> shift);
2108  buff[cnt + channelMap[0]] = Clamp8((vAvg + g) >> shift);
2109  cnt += channels;
2110  if (!m_downsample || (j & 1)) uPos++;
2111  yPos++;
2112  }
2113  if (!m_downsample || (i & 1)) uOffset += uw;
2114  yOffset += yw;
2115  buff += pitch;
2116 
2117  if (cb) {
2118  percent += dP;
2119  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2120  }
2121  }
2122  }
2123  break;
2124  }
2125  case ImageModeLabColor:
2126  {
2127  ASSERT(m_header.channels == 3);
2128  ASSERT(m_header.bpp == m_header.channels*8);
2129  ASSERT(bpp%8 == 0);
2130 
2131  DataT* l = m_channel[0]; ASSERT(l);
2132  DataT* a = m_channel[1]; ASSERT(a);
2133  DataT* b = m_channel[2]; ASSERT(b);
2134  UINT32 cnt, channels = bpp/8; ASSERT(channels >= m_header.channels);
2135 
2136  for (i=0; i < h; i++) {
2137  UINT32 uPos = uOffset;
2138  UINT32 yPos = yOffset;
2139  cnt = 0;
2140  for (j=0; j < w; j++) {
2141  uAvg = a[uPos];
2142  vAvg = b[uPos];
2143  buff[cnt + channelMap[0]] = Clamp8(l[yPos] + YUVoffset8);
2144  buff[cnt + channelMap[1]] = Clamp8(uAvg + YUVoffset8);
2145  buff[cnt + channelMap[2]] = Clamp8(vAvg + YUVoffset8);
2146  cnt += channels;
2147  if (!m_downsample || (j & 1)) uPos++;
2148  yPos++;
2149  }
2150  if (!m_downsample || (i & 1)) uOffset += uw;
2151  yOffset += yw;
2152  buff += pitch;
2153 
2154  if (cb) {
2155  percent += dP;
2156  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2157  }
2158  }
2159  break;
2160  }
2161  case ImageModeLab48:
2162  {
2163  ASSERT(m_header.channels == 3);
2164  ASSERT(m_header.bpp == m_header.channels*16);
2165 
2166  const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
2167 
2168  DataT* l = m_channel[0]; ASSERT(l);
2169  DataT* a = m_channel[1]; ASSERT(a);
2170  DataT* b = m_channel[2]; ASSERT(b);
2171  UINT32 cnt, channels;
2172 
2173  if (bpp%16 == 0) {
2174  const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
2175  UINT16 *buff16 = (UINT16 *)buff;
2176  int pitch16 = pitch/2;
2177  channels = bpp/16; ASSERT(channels >= m_header.channels);
2178 
2179  for (i=0; i < h; i++) {
2180  UINT32 uPos = uOffset;
2181  UINT32 yPos = yOffset;
2182  cnt = 0;
2183  for (j=0; j < w; j++) {
2184  uAvg = a[uPos];
2185  vAvg = b[uPos];
2186  buff16[cnt + channelMap[0]] = Clamp16((l[yPos] + yuvOffset16) << shift);
2187  buff16[cnt + channelMap[1]] = Clamp16((uAvg + yuvOffset16) << shift);
2188  buff16[cnt + channelMap[2]] = Clamp16((vAvg + yuvOffset16) << shift);
2189  cnt += channels;
2190  if (!m_downsample || (j & 1)) uPos++;
2191  yPos++;
2192  }
2193  if (!m_downsample || (i & 1)) uOffset += uw;
2194  yOffset += yw;
2195  buff16 += pitch16;
2196 
2197  if (cb) {
2198  percent += dP;
2199  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2200  }
2201  }
2202  } else {
2203  ASSERT(bpp%8 == 0);
2204  const int shift = __max(0, UsedBitsPerChannel() - 8);
2205  channels = bpp/8; ASSERT(channels >= m_header.channels);
2206 
2207  for (i=0; i < h; i++) {
2208  UINT32 uPos = uOffset;
2209  UINT32 yPos = yOffset;
2210  cnt = 0;
2211  for (j=0; j < w; j++) {
2212  uAvg = a[uPos];
2213  vAvg = b[uPos];
2214  buff[cnt + channelMap[0]] = Clamp8((l[yPos] + yuvOffset16) >> shift);
2215  buff[cnt + channelMap[1]] = Clamp8((uAvg + yuvOffset16) >> shift);
2216  buff[cnt + channelMap[2]] = Clamp8((vAvg + yuvOffset16) >> shift);
2217  cnt += channels;
2218  if (!m_downsample || (j & 1)) uPos++;
2219  yPos++;
2220  }
2221  if (!m_downsample || (i & 1)) uOffset += uw;
2222  yOffset += yw;
2223  buff += pitch;
2224 
2225  if (cb) {
2226  percent += dP;
2227  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2228  }
2229  }
2230  }
2231  break;
2232  }
2233  case ImageModeRGBA:
2234  case ImageModeCMYKColor:
2235  {
2236  ASSERT(m_header.channels == 4);
2237  ASSERT(m_header.bpp == m_header.channels*8);
2238  ASSERT(bpp%8 == 0);
2239 
2240  DataT* y = m_channel[0]; ASSERT(y);
2241  DataT* u = m_channel[1]; ASSERT(u);
2242  DataT* v = m_channel[2]; ASSERT(v);
2243  DataT* a = m_channel[3]; ASSERT(a);
2244  UINT8 g, aAvg;
2245  UINT32 cnt, channels = bpp/8; ASSERT(channels >= m_header.channels);
2246 
2247  for (i=0; i < h; i++) {
2248  UINT32 uPos = uOffset;
2249  UINT32 yPos = yOffset;
2250  cnt = 0;
2251  for (j=0; j < w; j++) {
2252  uAvg = u[uPos];
2253  vAvg = v[uPos];
2254  aAvg = Clamp8(a[uPos] + YUVoffset8);
2255  // Yuv
2256  buff[cnt + channelMap[1]] = g = Clamp8(y[yPos] + YUVoffset8 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
2257  buff[cnt + channelMap[2]] = Clamp8(uAvg + g);
2258  buff[cnt + channelMap[0]] = Clamp8(vAvg + g);
2259  buff[cnt + channelMap[3]] = aAvg;
2260  cnt += channels;
2261  if (!m_downsample || (j & 1)) uPos++;
2262  yPos++;
2263  }
2264  if (!m_downsample || (i & 1)) uOffset += uw;
2265  yOffset += yw;
2266  buff += pitch;
2267 
2268  if (cb) {
2269  percent += dP;
2270  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2271  }
2272  }
2273  break;
2274  }
2275  case ImageModeCMYK64:
2276  {
2277  ASSERT(m_header.channels == 4);
2278  ASSERT(m_header.bpp == 64);
2279 
2280  const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
2281 
2282  DataT* y = m_channel[0]; ASSERT(y);
2283  DataT* u = m_channel[1]; ASSERT(u);
2284  DataT* v = m_channel[2]; ASSERT(v);
2285  DataT* a = m_channel[3]; ASSERT(a);
2286  DataT g, aAvg;
2287  UINT32 cnt, channels;
2288 
2289  if (bpp%16 == 0) {
2290  const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
2291  UINT16 *buff16 = (UINT16 *)buff;
2292  int pitch16 = pitch/2;
2293  channels = bpp/16; ASSERT(channels >= m_header.channels);
2294 
2295  for (i=0; i < h; i++) {
2296  UINT32 uPos = uOffset;
2297  UINT32 yPos = yOffset;
2298  cnt = 0;
2299  for (j=0; j < w; j++) {
2300  uAvg = u[uPos];
2301  vAvg = v[uPos];
2302  aAvg = a[uPos] + yuvOffset16;
2303  // Yuv
2304  g = y[yPos] + yuvOffset16 - ((uAvg + vAvg ) >> 2); // must be logical shift operator
2305  buff16[cnt + channelMap[1]] = Clamp16(g << shift);
2306  buff16[cnt + channelMap[2]] = Clamp16((uAvg + g) << shift);
2307  buff16[cnt + channelMap[0]] = Clamp16((vAvg + g) << shift);
2308  buff16[cnt + channelMap[3]] = Clamp16(aAvg << shift);
2309  cnt += channels;
2310  if (!m_downsample || (j & 1)) uPos++;
2311  yPos++;
2312  }
2313  if (!m_downsample || (i & 1)) uOffset += uw;
2314  yOffset += yw;
2315  buff16 += pitch16;
2316 
2317  if (cb) {
2318  percent += dP;
2319  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2320  }
2321  }
2322  } else {
2323  ASSERT(bpp%8 == 0);
2324  const int shift = __max(0, UsedBitsPerChannel() - 8);
2325  channels = bpp/8; ASSERT(channels >= m_header.channels);
2326 
2327  for (i=0; i < h; i++) {
2328  UINT32 uPos = uOffset;
2329  UINT32 yPos = yOffset;
2330  cnt = 0;
2331  for (j=0; j < w; j++) {
2332  uAvg = u[uPos];
2333  vAvg = v[uPos];
2334  aAvg = a[uPos] + yuvOffset16;
2335  // Yuv
2336  g = y[yPos] + yuvOffset16 - ((uAvg + vAvg ) >> 2); // must be logical shift operator
2337  buff[cnt + channelMap[1]] = Clamp8(g >> shift);
2338  buff[cnt + channelMap[2]] = Clamp8((uAvg + g) >> shift);
2339  buff[cnt + channelMap[0]] = Clamp8((vAvg + g) >> shift);
2340  buff[cnt + channelMap[3]] = Clamp8(aAvg >> shift);
2341  cnt += channels;
2342  if (!m_downsample || (j & 1)) uPos++;
2343  yPos++;
2344  }
2345  if (!m_downsample || (i & 1)) uOffset += uw;
2346  yOffset += yw;
2347  buff += pitch;
2348 
2349  if (cb) {
2350  percent += dP;
2351  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2352  }
2353  }
2354  }
2355  break;
2356  }
2357 #ifdef __PGF32SUPPORT__
2358  case ImageModeGray32:
2359  {
2360  ASSERT(m_header.channels == 1);
2361  ASSERT(m_header.bpp == 32);
2362 
2363  const int yuvOffset31 = 1 << (UsedBitsPerChannel() - 1);
2364  DataT* y = m_channel[0]; ASSERT(y);
2365 
2366  if (bpp == 32) {
2367  const int shift = 31 - UsedBitsPerChannel(); ASSERT(shift >= 0);
2368  UINT32 *buff32 = (UINT32 *)buff;
2369  int pitch32 = pitch/4;
2370 
2371  for (i=0; i < h; i++) {
2372  UINT32 yPos = yOffset;
2373  for (j = 0; j < w; j++) {
2374  buff32[j] = Clamp31((y[yPos++] + yuvOffset31) << shift);
2375  }
2376  yOffset += yw;
2377  buff32 += pitch32;
2378 
2379  if (cb) {
2380  percent += dP;
2381  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2382  }
2383  }
2384  } else if (bpp == 16) {
2385  const int usedBits = UsedBitsPerChannel();
2386  UINT16 *buff16 = (UINT16 *)buff;
2387  int pitch16 = pitch/2;
2388 
2389  if (usedBits < 16) {
2390  const int shift = 16 - usedBits;
2391  for (i=0; i < h; i++) {
2392  UINT32 yPos = yOffset;
2393  for (j = 0; j < w; j++) {
2394  buff16[j] = Clamp16((y[yPos++] + yuvOffset31) << shift);
2395  }
2396  yOffset += yw;
2397  buff16 += pitch16;
2398 
2399  if (cb) {
2400  percent += dP;
2401  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2402  }
2403  }
2404  } else {
2405  const int shift = __max(0, usedBits - 16);
2406  for (i=0; i < h; i++) {
2407  UINT32 yPos = yOffset;
2408  for (j = 0; j < w; j++) {
2409  buff16[j] = Clamp16((y[yPos++] + yuvOffset31) >> shift);
2410  }
2411  yOffset += yw;
2412  buff16 += pitch16;
2413 
2414  if (cb) {
2415  percent += dP;
2416  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2417  }
2418  }
2419  }
2420  } else {
2421  ASSERT(bpp == 8);
2422  const int shift = __max(0, UsedBitsPerChannel() - 8);
2423 
2424  for (i=0; i < h; i++) {
2425  UINT32 yPos = yOffset;
2426  for (j = 0; j < w; j++) {
2427  buff[j] = Clamp8((y[yPos++] + yuvOffset31) >> shift);
2428  }
2429  yOffset += yw;
2430  buff += pitch;
2431 
2432  if (cb) {
2433  percent += dP;
2434  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2435  }
2436  }
2437  }
2438  break;
2439  }
2440 #endif
2441  case ImageModeRGB12:
2442  {
2443  ASSERT(m_header.channels == 3);
2444  ASSERT(m_header.bpp == m_header.channels*4);
2445  ASSERT(bpp == m_header.channels*4);
2446  ASSERT(!m_downsample);
2447 
2448  DataT* y = m_channel[0]; ASSERT(y);
2449  DataT* u = m_channel[1]; ASSERT(u);
2450  DataT* v = m_channel[2]; ASSERT(v);
2451  UINT16 yval;
2452  UINT32 cnt;
2453 
2454  for (i=0; i < h; i++) {
2455  UINT32 yPos = yOffset;
2456  cnt = 0;
2457  for (j=0; j < w; j++) {
2458  // Yuv
2459  uAvg = u[yPos];
2460  vAvg = v[yPos];
2461  yval = Clamp4(y[yPos] + YUVoffset4 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
2462  if (j%2 == 0) {
2463  buff[cnt] = UINT8(Clamp4(vAvg + yval) | (yval << 4));
2464  cnt++;
2465  buff[cnt] = Clamp4(uAvg + yval);
2466  } else {
2467  buff[cnt] |= Clamp4(vAvg + yval) << 4;
2468  cnt++;
2469  buff[cnt] = UINT8(yval | (Clamp4(uAvg + yval) << 4));
2470  cnt++;
2471  }
2472  yPos++;
2473  }
2474  yOffset += yw;
2475  buff += pitch;
2476 
2477  if (cb) {
2478  percent += dP;
2479  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2480  }
2481  }
2482  break;
2483  }
2484  case ImageModeRGB16:
2485  {
2486  ASSERT(m_header.channels == 3);
2487  ASSERT(m_header.bpp == 16);
2488  ASSERT(bpp == 16);
2489  ASSERT(!m_downsample);
2490 
2491  DataT* y = m_channel[0]; ASSERT(y);
2492  DataT* u = m_channel[1]; ASSERT(u);
2493  DataT* v = m_channel[2]; ASSERT(v);
2494  UINT16 yval;
2495  UINT16 *buff16 = (UINT16 *)buff;
2496  int pitch16 = pitch/2;
2497 
2498  for (i=0; i < h; i++) {
2499  UINT32 yPos = yOffset;
2500  for (j = 0; j < w; j++) {
2501  // Yuv
2502  uAvg = u[yPos];
2503  vAvg = v[yPos];
2504  yval = Clamp6(y[yPos++] + YUVoffset6 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
2505  buff16[j] = (yval << 5) | ((Clamp6(uAvg + yval) >> 1) << 11) | (Clamp6(vAvg + yval) >> 1);
2506  }
2507  yOffset += yw;
2508  buff16 += pitch16;
2509 
2510  if (cb) {
2511  percent += dP;
2512  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2513  }
2514  }
2515  break;
2516  }
2517  default:
2518  ASSERT(false);
2519  }
2520 
2521 #ifdef _DEBUG
2522  // display ROI (RGB) in debugger
2523  roiimage.width = w;
2524  roiimage.height = h;
2525  if (pitch > 0) {
2526  roiimage.pitch = pitch;
2527  roiimage.data = buff;
2528  } else {
2529  roiimage.pitch = -pitch;
2530  roiimage.data = buff + (h - 1)*pitch;
2531  }
2532 #endif
2533 
2534 }
#define ImageModeIndexedColor
Definition: PGFplatform.h:100
UINT8 version
PGF version.
Definition: PGFtypes.h:115
#define ImageModeRGB12
Definition: PGFplatform.h:117
UINT8 mode
image mode according to Adobe's image modes
Definition: PGFtypes.h:159
#define ImageModeHSBColor
Definition: PGFplatform.h:104
#define MaxChannels
maximum number of (color) channels
Definition: PGFtypes.h:64
BYTE UsedBitsPerChannel() const
Definition: PGFimage.cpp:756
INT32 DataT
Definition: PGFtypes.h:269
#define ImageModeRGBA
Definition: PGFplatform.h:115
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
#define ImageModeLabColor
Definition: PGFplatform.h:107
DataT * m_channel[MaxChannels]
untransformed channels in YUV format
Definition: PGFimage.h:522
PGFPreHeader m_preHeader
PGF pre-header.
Definition: PGFimage.h:528
#define ImageModeGray16
Definition: PGFplatform.h:108
UINT32 right
Definition: PGFtypes.h:226
PGFRect GetAlignedROI(int c=0) const
#define ImageModeLab48
Definition: PGFplatform.h:110
UINT16 Clamp6(DataT v) const
Definition: PGFimage.h:566
#define ImageModeCMYKColor
Definition: PGFplatform.h:102
#define ImageModeGrayScale
Definition: PGFplatform.h:99
UINT8 bpp
bits per pixel
Definition: PGFtypes.h:157
#define YUVoffset6
Definition: PGFimage.cpp:37
UINT32 Clamp31(DataT v) const
Definition: PGFimage.h:576
UINT16 Clamp16(DataT v) const
Definition: PGFimage.h:573
UINT32 Height() const
Definition: PGFtypes.h:259
bool m_downsample
chrominance channels are downsampled
Definition: PGFimage.h:535
#define __max(x, y)
Definition: PGFplatform.h:92
UINT32 m_width[MaxChannels]
width of each channel at current level
Definition: PGFimage.h:526
#define ImageModeGray32
Definition: PGFplatform.h:116
UINT32 top
Definition: PGFtypes.h:226
bool ROIisSupported() const
Definition: PGFimage.h:466
UINT32 left
Definition: PGFtypes.h:226
UINT8 Clamp8(DataT v) const
Definition: PGFimage.h:569
UINT8 Clamp4(DataT v) const
Definition: PGFimage.h:563
#define ImageModeRGBColor
Definition: PGFplatform.h:101
#define ImageModeHSLColor
Definition: PGFplatform.h:103
#define ImageModeBitmap
Definition: PGFplatform.h:98
#define Version7
Codec major and minor version number stored in PGFHeader.
Definition: PGFtypes.h:73
UINT8 channels
number of channels
Definition: PGFtypes.h:158
Rectangle.
Definition: PGFtypes.h:225
UINT32 Width() const
Definition: PGFtypes.h:256
#define ImageModeCMYK64
Definition: PGFplatform.h:111
#define YUVoffset4
Definition: PGFimage.cpp:36
#define ImageModeRGB16
Definition: PGFplatform.h:118
#define YUVoffset8
Definition: PGFimage.cpp:38
PGFRect ComputeLevelROI() const
#define ImageModeRGB48
Definition: PGFplatform.h:109
UINT32 bottom
Definition: PGFtypes.h:226
#define Version5
new coding scheme since major version 5
Definition: PGFtypes.h:71
UINT32 m_height[MaxChannels]
height of each channel at current level
Definition: PGFimage.h:527

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

317 { ASSERT(c >= 0 && c < MaxChannels); return m_channel[c]; }
#define MaxChannels
maximum number of (color) channels
Definition: PGFtypes.h:64
DataT * m_channel[MaxChannels]
untransformed channels in YUV format
Definition: PGFimage.h:522

◆ GetColorTable() [1/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 1350 of file PGFimage.cpp.

1350  {
1351  if (iFirstColor + nColors > ColorTableLen) ReturnWithError(ColorTableError);
1352 
1353  for (UINT32 i=iFirstColor, j=0; j < nColors; i++, j++) {
1354  prgbColors[j] = m_postHeader.clut[i];
1355  }
1356 }
#define ColorTableLen
size of color lookup table (clut)
Definition: PGFtypes.h:66
PGFPostHeader m_postHeader
PGF post-header.
Definition: PGFimage.h:530
RGBQUAD clut[ColorTableLen]
color table for indexed color images (optional part of file header)
Definition: PGFtypes.h:170

◆ GetColorTable() [2/2]

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

Definition at line 330 of file PGFimage.h.

330 { return m_postHeader.clut; }
PGFPostHeader m_postHeader
PGF post-header.
Definition: PGFimage.h:530
RGBQUAD clut[ColorTableLen]
color table for indexed color images (optional part of file header)
Definition: PGFtypes.h:170

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

648  {
649  ASSERT(m_decoder);
651 }
CDecoder * m_decoder
PGF decoder.
Definition: PGFimage.h:523
UINT32 GetEncodedHeaderLength() const
Definition: Decoder.h:136

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

367 { ASSERT(level >= 0 && level < m_header.nLevels); return m_levelLength[m_header.nLevels - level - 1]; }
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
UINT8 nLevels
number of FWT transforms
Definition: PGFtypes.h:155
UINT32 * m_levelLength
length of each level in bytes; first level starts immediately after this array
Definition: PGFimage.h:525

◆ GetHeader()

const PGFHeader* CPGFImage::GetHeader ( ) const
inline

Return the PGF header structure.

Returns
A PGF header structure

Definition at line 335 of file PGFimage.h.

335 { return &m_header; }
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529

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

341 { return (1 << m_header.usedBitsPerChannel) - 1; }
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
UINT8 usedBitsPerChannel
number of used bits per channel in 16- and 32-bit per channel modes
Definition: PGFtypes.h:160

◆ GetUserData()

const UINT8 * CPGFImage::GetUserData ( UINT32 &  cachedSize,
UINT32 *  pTotalSize = nullptr 
) const

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

Parameters
cachedSize[out] Size of returned user data in bytes.
pTotalSize[optional out] Pointer to return the size of user data stored in image header in bytes.
Returns
A pointer to user data or nullptr if there is no user data available.

Return user data and size of user data. Precondition: The PGF image has been opened with a call of Open(...). In an encoder scenario don't call this method before WriteHeader().

Parameters
cachedSize[out] Size of returned user data in bytes.
pTotalSize[optional out] Pointer to return the size of user data stored in image header in bytes.
Returns
A pointer to user data or nullptr if there is no user data available.

Definition at line 337 of file PGFimage.cpp.

337  {
338  cachedSize = m_postHeader.cachedUserDataLen;
339  if (pTotalSize) *pTotalSize = m_postHeader.userDataLen;
340  return m_postHeader.userData;
341 }
UINT32 userDataLen
user data size in bytes (not part of file header)
Definition: PGFtypes.h:172
UINT8 * userData
user data of size userDataLen (optional part of file header)
Definition: PGFtypes.h:171
UINT32 cachedUserDataLen
cached user data size in bytes (not part of file header)
Definition: PGFtypes.h:173
PGFPostHeader m_postHeader
PGF post-header.
Definition: PGFimage.h:530

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

346 { return m_userDataPos; }
UINT64 m_userDataPos
stream position of user data
Definition: PGFimage.h:531

◆ GetYUV()

void CPGFImage::GetYUV ( int  pitch,
DataT buff,
BYTE  bpp,
int  channelMap[] = nullptr,
CallbackPtr  cb = nullptr,
void *  data = nullptr 
) 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 2550 of file PGFimage.cpp.

2550  {
2551  ASSERT(buff);
2552  const UINT32 w = m_width[0];
2553  const UINT32 h = m_height[0];
2554  const bool wOdd = (1 == w%2);
2555  const int dataBits = DataTSize*8; ASSERT(dataBits == 16 || dataBits == 32);
2556  const int pitch2 = pitch/DataTSize;
2557  const int yuvOffset = (dataBits == 16) ? YUVoffset8 : YUVoffset16;
2558  const double dP = 1.0/h;
2559 
2560  int defMap[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; ASSERT(sizeof(defMap)/sizeof(defMap[0]) == MaxChannels);
2561  if (channelMap == nullptr) channelMap = defMap;
2562  int sampledPos = 0, yPos = 0;
2563  DataT uAvg, vAvg;
2564  double percent = 0;
2565  UINT32 i, j;
2566 
2567  if (m_header.channels == 3) {
2568  ASSERT(bpp%dataBits == 0);
2569 
2570  DataT* y = m_channel[0]; ASSERT(y);
2571  DataT* u = m_channel[1]; ASSERT(u);
2572  DataT* v = m_channel[2]; ASSERT(v);
2573  int cnt, channels = bpp/dataBits; ASSERT(channels >= m_header.channels);
2574 
2575  for (i=0; i < h; i++) {
2576  if (i%2) sampledPos -= (w + 1)/2;
2577  cnt = 0;
2578  for (j=0; j < w; j++) {
2579  if (m_downsample) {
2580  // image was downsampled
2581  uAvg = u[sampledPos];
2582  vAvg = v[sampledPos];
2583  } else {
2584  uAvg = u[yPos];
2585  vAvg = v[yPos];
2586  }
2587  buff[cnt + channelMap[0]] = y[yPos];
2588  buff[cnt + channelMap[1]] = uAvg;
2589  buff[cnt + channelMap[2]] = vAvg;
2590  yPos++;
2591  cnt += channels;
2592  if (j%2) sampledPos++;
2593  }
2594  buff += pitch2;
2595  if (wOdd) sampledPos++;
2596 
2597  if (cb) {
2598  percent += dP;
2599  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2600  }
2601  }
2602  } else if (m_header.channels == 4) {
2603  ASSERT(m_header.bpp == m_header.channels*8);
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  DataT* a = m_channel[3]; ASSERT(a);
2610  UINT8 aAvg;
2611  int cnt, channels = bpp/dataBits; ASSERT(channels >= m_header.channels);
2612 
2613  for (i=0; i < h; i++) {
2614  if (i%2) sampledPos -= (w + 1)/2;
2615  cnt = 0;
2616  for (j=0; j < w; j++) {
2617  if (m_downsample) {
2618  // image was downsampled
2619  uAvg = u[sampledPos];
2620  vAvg = v[sampledPos];
2621  aAvg = Clamp8(a[sampledPos] + yuvOffset);
2622  } else {
2623  uAvg = u[yPos];
2624  vAvg = v[yPos];
2625  aAvg = Clamp8(a[yPos] + yuvOffset);
2626  }
2627  // Yuv
2628  buff[cnt + channelMap[0]] = y[yPos];
2629  buff[cnt + channelMap[1]] = uAvg;
2630  buff[cnt + channelMap[2]] = vAvg;
2631  buff[cnt + channelMap[3]] = aAvg;
2632  yPos++;
2633  cnt += channels;
2634  if (j%2) sampledPos++;
2635  }
2636  buff += pitch2;
2637  if (wOdd) sampledPos++;
2638 
2639  if (cb) {
2640  percent += dP;
2641  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2642  }
2643  }
2644  }
2645 }
#define YUVoffset16
Definition: PGFimage.cpp:39
#define MaxChannels
maximum number of (color) channels
Definition: PGFtypes.h:64
INT32 DataT
Definition: PGFtypes.h:269
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
#define DataTSize
Definition: PGFtypes.h:283
DataT * m_channel[MaxChannels]
untransformed channels in YUV format
Definition: PGFimage.h:522
UINT8 bpp
bits per pixel
Definition: PGFtypes.h:157
bool m_downsample
chrominance channels are downsampled
Definition: PGFimage.h:535
UINT32 m_width[MaxChannels]
width of each channel at current level
Definition: PGFimage.h:526
UINT8 Clamp8(DataT v) const
Definition: PGFimage.h:569
UINT8 channels
number of channels
Definition: PGFtypes.h:158
#define YUVoffset8
Definition: PGFimage.cpp:38
UINT32 m_height[MaxChannels]
height of each channel at current level
Definition: PGFimage.h:527

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

420 { ASSERT(level >= 0); return LevelSizeL(m_header.height, level); }
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
static UINT32 LevelSizeL(UINT32 size, int level)
Definition: PGFimage.h:499
UINT32 height
image height in pixels
Definition: PGFtypes.h:154

◆ ImportBitmap()

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

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

792  {
793  ASSERT(buff);
794  ASSERT(m_channel[0]);
795 
796  // color transform
797  RgbToYuv(pitch, buff, bpp, channelMap, cb, data);
798 
799  if (m_downsample) {
800  // Subsampling of the chrominance and alpha channels
801  for (int i=1; i < m_header.channels; i++) {
802  Downsample(i);
803  }
804  }
805 }
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
DataT * m_channel[MaxChannels]
untransformed channels in YUV format
Definition: PGFimage.h:522
bool m_downsample
chrominance channels are downsampled
Definition: PGFimage.h:535
UINT8 channels
number of channels
Definition: PGFtypes.h:158
void RgbToYuv(int pitch, UINT8 *rgbBuff, BYTE bpp, int channelMap[], CallbackPtr cb, void *data)
Definition: PGFimage.cpp:1389
void Downsample(int nChannel)
Definition: PGFimage.cpp:810

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

1305  {
1306  size_t size = DataTSize;
1307 
1308  if (size >= 2) {
1309  switch(mode) {
1310  case ImageModeBitmap:
1311  case ImageModeIndexedColor:
1312  case ImageModeGrayScale:
1313  case ImageModeRGBColor:
1314  case ImageModeCMYKColor:
1315  case ImageModeHSLColor:
1316  case ImageModeHSBColor:
1317  //case ImageModeDuotone:
1318  case ImageModeLabColor:
1319  case ImageModeRGB12:
1320  case ImageModeRGB16:
1321  case ImageModeRGBA:
1322  return true;
1323  }
1324  }
1325  if (size >= 3) {
1326  switch(mode) {
1327  case ImageModeGray16:
1328  case ImageModeRGB48:
1329  case ImageModeLab48:
1330  case ImageModeCMYK64:
1331  //case ImageModeDuotone16:
1332  return true;
1333  }
1334  }
1335  if (size >=4) {
1336  switch(mode) {
1337  case ImageModeGray32:
1338  return true;
1339  }
1340  }
1341  return false;
1342 }
#define ImageModeIndexedColor
Definition: PGFplatform.h:100
#define ImageModeRGB12
Definition: PGFplatform.h:117
#define ImageModeHSBColor
Definition: PGFplatform.h:104
#define ImageModeRGBA
Definition: PGFplatform.h:115
#define DataTSize
Definition: PGFtypes.h:283
#define ImageModeLabColor
Definition: PGFplatform.h:107
#define ImageModeGray16
Definition: PGFplatform.h:108
#define ImageModeLab48
Definition: PGFplatform.h:110
#define ImageModeCMYKColor
Definition: PGFplatform.h:102
#define ImageModeGrayScale
Definition: PGFplatform.h:99
#define ImageModeGray32
Definition: PGFplatform.h:116
#define ImageModeRGBColor
Definition: PGFplatform.h:101
#define ImageModeHSLColor
Definition: PGFplatform.h:103
#define ImageModeBitmap
Definition: PGFplatform.h:98
#define ImageModeCMYK64
Definition: PGFplatform.h:111
#define ImageModeRGB16
Definition: PGFplatform.h:118
#define ImageModeRGB48
Definition: PGFplatform.h:109

◆ ImportYUV()

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

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

2661  {
2662  ASSERT(buff);
2663  const double dP = 1.0/m_header.height;
2664  const int dataBits = DataTSize*8; ASSERT(dataBits == 16 || dataBits == 32);
2665  const int pitch2 = pitch/DataTSize;
2666  const int yuvOffset = (dataBits == 16) ? YUVoffset8 : YUVoffset16;
2667 
2668  int yPos = 0, cnt = 0;
2669  double percent = 0;
2670  int defMap[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; ASSERT(sizeof(defMap)/sizeof(defMap[0]) == MaxChannels);
2671 
2672  if (channelMap == nullptr) channelMap = defMap;
2673 
2674  if (m_header.channels == 3) {
2675  ASSERT(bpp%dataBits == 0);
2676 
2677  DataT* y = m_channel[0]; ASSERT(y);
2678  DataT* u = m_channel[1]; ASSERT(u);
2679  DataT* v = m_channel[2]; ASSERT(v);
2680  const int channels = bpp/dataBits; ASSERT(channels >= m_header.channels);
2681 
2682  for (UINT32 h=0; h < m_header.height; h++) {
2683  if (cb) {
2684  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2685  percent += dP;
2686  }
2687 
2688  cnt = 0;
2689  for (UINT32 w=0; w < m_header.width; w++) {
2690  y[yPos] = buff[cnt + channelMap[0]];
2691  u[yPos] = buff[cnt + channelMap[1]];
2692  v[yPos] = buff[cnt + channelMap[2]];
2693  yPos++;
2694  cnt += channels;
2695  }
2696  buff += pitch2;
2697  }
2698  } else if (m_header.channels == 4) {
2699  ASSERT(bpp%dataBits == 0);
2700 
2701  DataT* y = m_channel[0]; ASSERT(y);
2702  DataT* u = m_channel[1]; ASSERT(u);
2703  DataT* v = m_channel[2]; ASSERT(v);
2704  DataT* a = m_channel[3]; ASSERT(a);
2705  const int channels = bpp/dataBits; ASSERT(channels >= m_header.channels);
2706 
2707  for (UINT32 h=0; h < m_header.height; h++) {
2708  if (cb) {
2709  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
2710  percent += dP;
2711  }
2712 
2713  cnt = 0;
2714  for (UINT32 w=0; w < m_header.width; w++) {
2715  y[yPos] = buff[cnt + channelMap[0]];
2716  u[yPos] = buff[cnt + channelMap[1]];
2717  v[yPos] = buff[cnt + channelMap[2]];
2718  a[yPos] = buff[cnt + channelMap[3]] - yuvOffset;
2719  yPos++;
2720  cnt += channels;
2721  }
2722  buff += pitch2;
2723  }
2724  }
2725 
2726  if (m_downsample) {
2727  // Subsampling of the chrominance and alpha channels
2728  for (int i=1; i < m_header.channels; i++) {
2729  Downsample(i);
2730  }
2731  }
2732 }
#define YUVoffset16
Definition: PGFimage.cpp:39
#define MaxChannels
maximum number of (color) channels
Definition: PGFtypes.h:64
UINT32 width
image width in pixels
Definition: PGFtypes.h:153
INT32 DataT
Definition: PGFtypes.h:269
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
#define DataTSize
Definition: PGFtypes.h:283
DataT * m_channel[MaxChannels]
untransformed channels in YUV format
Definition: PGFimage.h:522
bool m_downsample
chrominance channels are downsampled
Definition: PGFimage.h:535
UINT8 channels
number of channels
Definition: PGFtypes.h:158
void Downsample(int nChannel)
Definition: PGFimage.cpp:810
#define YUVoffset8
Definition: PGFimage.cpp:38
UINT32 height
image height in pixels
Definition: PGFtypes.h:154

◆ Init()

void CPGFImage::Init ( )
private

Definition at line 69 of file PGFimage.cpp.

69  {
70  // init pointers
71  m_decoder = nullptr;
72  m_encoder = nullptr;
73  m_levelLength = nullptr;
74 
75  // init members
76 #ifdef __PGFROISUPPORT__
77  m_streamReinitialized = false;
78 #endif
79  m_currentLevel = 0;
80  m_quant = 0;
81  m_userDataPos = 0;
82  m_downsample = false;
83  m_favorSpeedOverSize = false;
84  m_useOMPinEncoder = true;
85  m_useOMPinDecoder = true;
86  m_cb = nullptr;
87  m_cbArg = nullptr;
89  m_percent = 0;
91 
92  // init preHeader
93  memcpy(m_preHeader.magic, PGFMagic, 3);
95  m_preHeader.hSize = 0;
96 
97  // init postHeader
98  m_postHeader.userData = nullptr;
101 
102  // init channels
103  for (int i = 0; i < MaxChannels; i++) {
104  m_channel[i] = nullptr;
105  m_wtChannel[i] = nullptr;
106  }
107 
108  // set image width and height
109  for (int i = 0; i < MaxChannels; i++) {
110  m_width[0] = 0;
111  m_height[0] = 0;
112  }
113 }
bool m_favorSpeedOverSize
favor encoding speed over compression ratio
Definition: PGFimage.h:536
UINT64 m_userDataPos
stream position of user data
Definition: PGFimage.h:531
bool m_useOMPinDecoder
use Open MP in decoder
Definition: PGFimage.h:538
UINT8 version
PGF version.
Definition: PGFtypes.h:115
#define PGFVersion
current standard version
Definition: PGFtypes.h:76
#define MaxChannels
maximum number of (color) channels
Definition: PGFtypes.h:64
UINT32 userDataLen
user data size in bytes (not part of file header)
Definition: PGFtypes.h:172
CDecoder * m_decoder
PGF decoder.
Definition: PGFimage.h:523
UINT8 * userData
user data of size userDataLen (optional part of file header)
Definition: PGFtypes.h:171
bool m_streamReinitialized
stream has been reinitialized
Definition: PGFimage.h:540
BYTE m_quant
quantization parameter
Definition: PGFimage.h:534
void * m_cbArg
refresh callback argument
Definition: PGFimage.h:546
DataT * m_channel[MaxChannels]
untransformed channels in YUV format
Definition: PGFimage.h:522
PGFPreHeader m_preHeader
PGF pre-header.
Definition: PGFimage.h:528
#define PGFMagic
PGF identification.
Definition: PGFtypes.h:61
UINT32 cachedUserDataLen
cached user data size in bytes (not part of file header)
Definition: PGFtypes.h:173
ProgressMode m_progressMode
progress mode used in Read and Write; PM_Relative is default mode
Definition: PGFimage.h:548
CWaveletTransform * m_wtChannel[MaxChannels]
wavelet transformed color channels
Definition: PGFimage.h:521
char magic[3]
PGF identification = "PGF".
Definition: PGFtypes.h:114
PGFPostHeader m_postHeader
PGF post-header.
Definition: PGFimage.h:530
bool m_downsample
chrominance channels are downsampled
Definition: PGFimage.h:535
UINT32 * m_levelLength
length of each level in bytes; first level starts immediately after this array
Definition: PGFimage.h:525
UINT32 hSize
total size of PGFHeader, [ColorTable], and [UserData] in bytes (since Version 6: 4 Bytes)
Definition: PGFtypes.h:124
UINT32 m_width[MaxChannels]
width of each channel at current level
Definition: PGFimage.h:526
bool m_useOMPinEncoder
use Open MP in encoder
Definition: PGFimage.h:537
UINT32 m_userDataPolicy
user data (metadata) policy during open
Definition: PGFimage.h:533
double m_percent
progress [0..1]
Definition: PGFimage.h:547
RefreshCB m_cb
pointer to refresh callback procedure
Definition: PGFimage.h:545
CEncoder * m_encoder
PGF encoder.
Definition: PGFimage.h:524
int m_currentLevel
transform level of current image
Definition: PGFimage.h:532
UINT32 m_height[MaxChannels]
height of each channel at current level
Definition: PGFimage.h:527

◆ IsFullyRead()

bool CPGFImage::IsFullyRead ( ) const
inline

Return true if all levels have been read.

Definition at line 436 of file PGFimage.h.

436 { return m_currentLevel == 0; }
int m_currentLevel
transform level of current image
Definition: PGFimage.h:532

◆ IsOpen()

bool CPGFImage::IsOpen ( ) const
inline

Returns true if the PGF has been opened for reading.

Definition at line 77 of file PGFimage.h.

77 { return m_decoder != nullptr; }
CDecoder * m_decoder
PGF decoder.
Definition: PGFimage.h:523

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

427 { return (BYTE)m_currentLevel; }
int m_currentLevel
transform level of current image
Definition: PGFimage.h:532

◆ Levels()

BYTE CPGFImage::Levels ( ) const
inline

Return the number of image levels.

Returns
Number of image levels

Definition at line 432 of file PGFimage.h.

432 { return m_header.nLevels; }
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
UINT8 nLevels
number of FWT transforms
Definition: PGFtypes.h:155

◆ LevelSizeH()

static UINT32 CPGFImage::LevelSizeH ( UINT32  size,
int  level 
)
inlinestatic

Compute and return image width/height of HH subband at given level.

Parameters
sizeOriginal image size (e.g. width or height at level 0)
levelAn image level
Returns
high pass size at given level in pixels

Definition at line 506 of file PGFimage.h.

506 { ASSERT(level >= 0); UINT32 d = 1 << (level - 1); return (size + d - 1) >> level; }

◆ LevelSizeL()

static UINT32 CPGFImage::LevelSizeL ( UINT32  size,
int  level 
)
inlinestatic

Compute and return image width/height of LL subband at given level.

Parameters
sizeOriginal image size (e.g. width or height at level 0)
levelAn image level
Returns
Image width/height at given level in pixels

Definition at line 499 of file PGFimage.h.

499 { ASSERT(level >= 0); UINT32 d = 1 << level; return (size + d - 1) >> level; }

◆ MaxChannelDepth()

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

Return maximum channel depth.

Parameters
versionpgf pre-header version number
Returns
maximum channel depth in bit of given version (16 or 32 bit)

Definition at line 518 of file PGFimage.h.

518 { return (version & PGF32) ? 32 : 16; }
#define PGF32
32 bit values are used -> allows at maximum 30 input bits, otherwise 16 bit values are used -> allows...
Definition: PGFtypes.h:69

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

455 { return m_header.mode; }
UINT8 mode
image mode according to Adobe's image modes
Definition: PGFtypes.h:159
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529

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

141  {
142  ASSERT(stream);
143 
144  // create decoder and read PGFPreHeader PGFHeader PGFPostHeader LevelLengths
147 
148  if (m_header.nLevels > MaxLevel) ReturnWithError(FormatCannotRead);
149 
150  // set current level
152 
153  // set image width and height
154  m_width[0] = m_header.width;
155  m_height[0] = m_header.height;
156 
157  // complete header
158  if (!CompleteHeader()) ReturnWithError(FormatCannotRead);
159 
160  // interpret quant parameter
169  m_downsample = true;
170  m_quant = m_header.quality - 1;
171  } else {
172  m_downsample = false;
174  }
175 
176  // set channel dimensions (chrominance is subsampled by factor 2)
177  if (m_downsample) {
178  for (int i=1; i < m_header.channels; i++) {
179  m_width[i] = (m_width[0] + 1) >> 1;
180  m_height[i] = (m_height[0] + 1) >> 1;
181  }
182  } else {
183  for (int i=1; i < m_header.channels; i++) {
184  m_width[i] = m_width[0];
185  m_height[i] = m_height[0];
186  }
187  }
188 
189  if (m_header.nLevels > 0) {
190  // init wavelet subbands
191  for (int i=0; i < m_header.channels; i++) {
193  }
194 
195  // used in Read when PM_Absolute
196  m_percent = pow(0.25, m_header.nLevels);
197 
198  } else {
199  // very small image: we don't use DWT and encoding
200 
201  // read channels
202  for (int c=0; c < m_header.channels; c++) {
203  const UINT32 size = m_width[c]*m_height[c];
204  m_channel[c] = new(std::nothrow) DataT[size];
205  if (!m_channel[c]) ReturnWithError(InsufficientMemory);
206 
207  // read channel data from stream
208  for (UINT32 i=0; i < size; i++) {
209  int count = DataTSize;
210  stream->Read(&count, &m_channel[c][i]);
211  if (count != DataTSize) ReturnWithError(MissingData);
212  }
213  }
214  }
215 }
virtual void Read(int *count, void *buffer)=0
UINT64 m_userDataPos
stream position of user data
Definition: PGFimage.h:531
bool m_useOMPinDecoder
use Open MP in decoder
Definition: PGFimage.h:538
UINT8 mode
image mode according to Adobe's image modes
Definition: PGFtypes.h:159
UINT32 width
image width in pixels
Definition: PGFtypes.h:153
INT32 DataT
Definition: PGFtypes.h:269
#define ImageModeRGBA
Definition: PGFplatform.h:115
CDecoder * m_decoder
PGF decoder.
Definition: PGFimage.h:523
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
bool CompleteHeader()
Definition: PGFimage.cpp:218
BYTE m_quant
quantization parameter
Definition: PGFimage.h:534
#define DataTSize
Definition: PGFtypes.h:283
#define ImageModeLabColor
Definition: PGFplatform.h:107
DataT * m_channel[MaxChannels]
untransformed channels in YUV format
Definition: PGFimage.h:522
PGFPreHeader m_preHeader
PGF pre-header.
Definition: PGFimage.h:528
UINT8 nLevels
number of FWT transforms
Definition: PGFtypes.h:155
#define ImageModeLab48
Definition: PGFplatform.h:110
#define ImageModeCMYKColor
Definition: PGFplatform.h:102
#define MaxLevel
maximum number of transform levels
Definition: PGFtypes.h:62
CWaveletTransform * m_wtChannel[MaxChannels]
wavelet transformed color channels
Definition: PGFimage.h:521
PGFPostHeader m_postHeader
PGF post-header.
Definition: PGFimage.h:530
bool m_downsample
chrominance channels are downsampled
Definition: PGFimage.h:535
PGF decoder.
Definition: Decoder.h:46
#define DownsampleThreshold
if quality is larger than this threshold than downsampling is used
Definition: PGFtypes.h:65
friend class CWaveletTransform
Definition: Subband.h:43
UINT32 * m_levelLength
length of each level in bytes; first level starts immediately after this array
Definition: PGFimage.h:525
UINT32 m_width[MaxChannels]
width of each channel at current level
Definition: PGFimage.h:526
#define ImageModeRGBColor
Definition: PGFplatform.h:101
UINT32 m_userDataPolicy
user data (metadata) policy during open
Definition: PGFimage.h:533
double m_percent
progress [0..1]
Definition: PGFimage.h:547
UINT8 channels
number of channels
Definition: PGFtypes.h:158
#define ImageModeCMYK64
Definition: PGFplatform.h:111
int m_currentLevel
transform level of current image
Definition: PGFimage.h:532
UINT8 quality
quantization parameter: 0=lossless, 4=standard, 6=poor quality
Definition: PGFtypes.h:156
UINT32 height
image height in pixels
Definition: PGFtypes.h:154
#define ImageModeRGB48
Definition: PGFplatform.h:109
UINT32 m_height[MaxChannels]
height of each channel at current level
Definition: PGFimage.h:527

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

442 { return m_header.quality; }
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
UINT8 quality
quantization parameter: 0=lossless, 4=standard, 6=poor quality
Definition: PGFtypes.h:156

◆ Read() [1/2]

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

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

402  {
403  ASSERT((level >= 0 && level < m_header.nLevels) || m_header.nLevels == 0); // m_header.nLevels == 0: image didn't use wavelet transform
404  ASSERT(m_decoder);
405 
406 #ifdef __PGFROISUPPORT__
407  if (ROIisSupported() && m_header.nLevels > 0) {
408  // new encoding scheme supporting ROI
409  PGFRect rect(0, 0, m_header.width, m_header.height);
410  Read(rect, level, cb, data);
411  return;
412  }
413 #endif
414 
415  if (m_header.nLevels == 0) {
416  if (level == 0) {
417  // the data has already been read during open
418  // now update progress
419  if (cb) {
420  if ((*cb)(1.0, true, data)) ReturnWithError(EscapePressed);
421  }
422  }
423  } else {
424  const int levelDiff = m_currentLevel - level;
425  double percent = (m_progressMode == PM_Relative) ? pow(0.25, levelDiff) : m_percent;
426 
427  // encoding scheme without ROI
428  while (m_currentLevel > level) {
429  for (int i=0; i < m_header.channels; i++) {
430  CWaveletTransform* wtChannel = m_wtChannel[i];
431  ASSERT(wtChannel);
432 
433  // decode file and write stream to m_wtChannel
434  if (m_currentLevel == m_header.nLevels) {
435  // last level also has LL band
437  }
438  if (m_preHeader.version & Version5) {
439  // since version 5
442  } else {
443  // until version 4
445  }
447  }
448 
449  volatile OSError error = NoError; // volatile prevents optimizations
450 #ifdef LIBPGF_USE_OPENMP
451  #pragma omp parallel for default(shared)
452 #endif
453  for (int i=0; i < m_header.channels; i++) {
454  // inverse transform from m_wtChannel to m_channel
455  if (error == NoError) {
456  OSError err = m_wtChannel[i]->InverseTransform(m_currentLevel, &m_width[i], &m_height[i], &m_channel[i]);
457  if (err != NoError) error = err;
458  }
459  ASSERT(m_channel[i]);
460  }
461  if (error != NoError) ReturnWithError(error);
462 
463  // set new level: must be done before refresh callback
464  m_currentLevel--;
465 
466  // now we have to refresh the display
467  if (m_cb) m_cb(m_cbArg);
468 
469  // now update progress
470  if (cb) {
471  percent *= 4;
472  if (m_progressMode == PM_Absolute) m_percent = percent;
473  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
474  }
475  }
476  }
477 }
OSError InverseTransform(int level, UINT32 *width, UINT32 *height, DataT **data)
void Read(int level=0, CallbackPtr cb=nullptr, void *data=nullptr)
Definition: PGFimage.cpp:402
UINT8 version
PGF version.
Definition: PGFtypes.h:115
Definition: PGFtypes.h:99
UINT32 width
image width in pixels
Definition: PGFtypes.h:153
CDecoder * m_decoder
PGF decoder.
Definition: PGFimage.h:523
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
void DecodeInterleaved(CWaveletTransform *wtChannel, int level, int quantParam)
Definition: Decoder.cpp:333
BYTE m_quant
quantization parameter
Definition: PGFimage.h:534
void * m_cbArg
refresh callback argument
Definition: PGFimage.h:546
DataT * m_channel[MaxChannels]
untransformed channels in YUV format
Definition: PGFimage.h:522
PGFPreHeader m_preHeader
PGF pre-header.
Definition: PGFimage.h:528
UINT8 nLevels
number of FWT transforms
Definition: PGFtypes.h:155
PGF wavelet transform.
ProgressMode m_progressMode
progress mode used in Read and Write; PM_Relative is default mode
Definition: PGFimage.h:548
CWaveletTransform * m_wtChannel[MaxChannels]
wavelet transformed color channels
Definition: PGFimage.h:521
void PlaceTile(CDecoder &decoder, int quantParam, bool tile=false, UINT32 tileX=0, UINT32 tileY=0)
Definition: Subband.cpp:203
Definition: PGFtypes.h:99
UINT32 m_width[MaxChannels]
width of each channel at current level
Definition: PGFimage.h:526
Definition: PGFtypes.h:99
CSubband * GetSubband(int level, Orientation orientation)
bool ROIisSupported() const
Definition: PGFimage.h:466
Definition: PGFtypes.h:99
double m_percent
progress [0..1]
Definition: PGFimage.h:547
UINT8 channels
number of channels
Definition: PGFtypes.h:158
Rectangle.
Definition: PGFtypes.h:225
RefreshCB m_cb
pointer to refresh callback procedure
Definition: PGFimage.h:545
int m_currentLevel
transform level of current image
Definition: PGFimage.h:532
UINT32 height
image height in pixels
Definition: PGFtypes.h:154
#define Version5
new coding scheme since major version 5
Definition: PGFtypes.h:71
UINT32 m_height[MaxChannels]
height of each channel at current level
Definition: PGFimage.h:527

◆ Read() [2/2]

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

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) at level 0. 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 707 of file PGFimage.cpp.

707  {
708  ASSERT(level >= 0 && level < m_header.nLevels);
709  ASSERT(target);
710  ASSERT(targetLen > 0);
711  ASSERT(m_decoder);
712 
713  // reset stream position
715 
716  // position stream
717  UINT64 offset = 0;
718 
719  for (int i=m_header.nLevels - 1; i > level; i--) {
720  offset += m_levelLength[m_header.nLevels - 1 - i];
721  }
722  m_decoder->Skip(offset);
723 
724  // compute number of bytes to read
725  UINT32 len = __min(targetLen, GetEncodedLevelLength(level));
726 
727  // read data
728  len = m_decoder->ReadEncodedData(target, len);
729  ASSERT(len >= 0 && len <= targetLen);
730 
731  return len;
732 }
CDecoder * m_decoder
PGF decoder.
Definition: PGFimage.h:523
UINT32 GetEncodedLevelLength(int level) const
Definition: PGFimage.h:367
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
void SetStreamPosToData()
Resets stream position to beginning of data block.
Definition: Decoder.h:144
UINT8 nLevels
number of FWT transforms
Definition: PGFtypes.h:155
UINT32 * m_levelLength
length of each level in bytes; first level starts immediately after this array
Definition: PGFimage.h:525
#define __min(x, y)
Definition: PGFplatform.h:91
void Skip(UINT64 offset)
Definition: Decoder.cpp:449
UINT32 ReadEncodedData(UINT8 *target, UINT32 len) const
Definition: Decoder.cpp:246

◆ ReadEncodedHeader()

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

Reads the encoded PGF header 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 660 of file PGFimage.cpp.

660  {
661  ASSERT(target);
662  ASSERT(targetLen > 0);
663  ASSERT(m_decoder);
664 
665  // reset stream position
667 
668  // compute number of bytes to read
669  UINT32 len = __min(targetLen, GetEncodedHeaderLength());
670 
671  // read data
672  len = m_decoder->ReadEncodedData(target, len);
673  ASSERT(len >= 0 && len <= targetLen);
674 
675  return len;
676 }
CDecoder * m_decoder
PGF decoder.
Definition: PGFimage.h:523
#define __min(x, y)
Definition: PGFplatform.h:91
UINT32 ReadEncodedData(UINT8 *target, UINT32 len) const
Definition: Decoder.cpp:246
UINT32 GetEncodedHeaderLength() const
Definition: PGFimage.cpp:648
void SetStreamPosToStart()
Resets stream position to beginning of PGF pre-header.
Definition: Decoder.h:140

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

111 { Read(Levels() - 1); }
void Read(int level=0, CallbackPtr cb=nullptr, void *data=nullptr)
Definition: PGFimage.cpp:402
BYTE Levels() const
Definition: PGFimage.h:432

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

348  {
349  if (m_header.nLevels == 0) {
350  // image didn't use wavelet transform
351  if (level == 0) {
352  for (int i=0; i < m_header.channels; i++) {
353  ASSERT(m_wtChannel[i]);
354  m_channel[i] = m_wtChannel[i]->GetSubband(0, LL)->GetBuffer();
355  }
356  }
357  } else {
358  int currentLevel = m_header.nLevels;
359 
360  #ifdef __PGFROISUPPORT__
361  if (ROIisSupported()) {
362  // enable ROI reading
364  }
365  #endif
366 
367  while (currentLevel > level) {
368  for (int i=0; i < m_header.channels; i++) {
369  ASSERT(m_wtChannel[i]);
370  // dequantize subbands
371  if (currentLevel == m_header.nLevels) {
372  // last level also has LL band
373  m_wtChannel[i]->GetSubband(currentLevel, LL)->Dequantize(m_quant);
374  }
375  m_wtChannel[i]->GetSubband(currentLevel, HL)->Dequantize(m_quant);
376  m_wtChannel[i]->GetSubband(currentLevel, LH)->Dequantize(m_quant);
377  m_wtChannel[i]->GetSubband(currentLevel, HH)->Dequantize(m_quant);
378 
379  // inverse transform from m_wtChannel to m_channel
380  OSError err = m_wtChannel[i]->InverseTransform(currentLevel, &m_width[i], &m_height[i], &m_channel[i]);
381  if (err != NoError) ReturnWithError(err);
382  ASSERT(m_channel[i]);
383  }
384 
385  currentLevel--;
386  }
387  }
388 }
OSError InverseTransform(int level, UINT32 *width, UINT32 *height, DataT **data)
Definition: PGFtypes.h:99
void Dequantize(int quantParam)
Definition: Subband.cpp:154
DataT * GetBuffer()
Definition: Subband.h:107
UINT32 width
image width in pixels
Definition: PGFtypes.h:153
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
BYTE m_quant
quantization parameter
Definition: PGFimage.h:534
DataT * m_channel[MaxChannels]
untransformed channels in YUV format
Definition: PGFimage.h:522
UINT8 nLevels
number of FWT transforms
Definition: PGFtypes.h:155
void SetROI(PGFRect rect)
CWaveletTransform * m_wtChannel[MaxChannels]
wavelet transformed color channels
Definition: PGFimage.h:521
Definition: PGFtypes.h:99
UINT32 m_width[MaxChannels]
width of each channel at current level
Definition: PGFimage.h:526
Definition: PGFtypes.h:99
CSubband * GetSubband(int level, Orientation orientation)
bool ROIisSupported() const
Definition: PGFimage.h:466
Definition: PGFtypes.h:99
UINT8 channels
number of channels
Definition: PGFtypes.h:158
Rectangle.
Definition: PGFtypes.h:225
UINT32 height
image height in pixels
Definition: PGFtypes.h:154
UINT32 m_height[MaxChannels]
height of each channel at current level
Definition: PGFimage.h:527

◆ ResetStreamPos()

void CPGFImage::ResetStreamPos ( bool  startOfData)

Reset stream position to start of PGF pre-header or start of data. Must not be called before Open() or before Write(). Use this method after Read() if you want to read the same image several times, e.g. reading different ROIs.

Parameters
startOfDatatrue: you want to read the same image several times. false: resets stream position to the initial position

Definition at line 682 of file PGFimage.cpp.

682  {
683  m_currentLevel = 0;
684  if (startOfData) {
685  ASSERT(m_decoder);
687  } else {
688  if (m_decoder) {
690  } else if (m_encoder) {
692  } else {
693  ASSERT(false);
694  }
695  }
696 }
CDecoder * m_decoder
PGF decoder.
Definition: PGFimage.h:523
void SetStreamPosToData()
Resets stream position to beginning of data block.
Definition: Decoder.h:144
void SetStreamPosToStart()
Resets stream position to beginning of PGF pre-header.
Definition: Encoder.h:188
CEncoder * m_encoder
PGF encoder.
Definition: PGFimage.h:524
void SetStreamPosToStart()
Resets stream position to beginning of PGF pre-header.
Definition: Decoder.h:140
int m_currentLevel
transform level of current image
Definition: PGFimage.h:532

◆ RgbToYuv()

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

Definition at line 1389 of file PGFimage.cpp.

1389  {
1390  ASSERT(buff);
1391  UINT32 yPos = 0, cnt = 0;
1392  double percent = 0;
1393  const double dP = 1.0/m_header.height;
1394  int defMap[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; ASSERT(sizeof(defMap)/sizeof(defMap[0]) == MaxChannels);
1395 
1396  if (channelMap == nullptr) channelMap = defMap;
1397 
1398  switch(m_header.mode) {
1399  case ImageModeBitmap:
1400  {
1401  ASSERT(m_header.channels == 1);
1402  ASSERT(m_header.bpp == 1);
1403  ASSERT(bpp == 1);
1404 
1405  const UINT32 w = m_header.width;
1406  const UINT32 w2 = (m_header.width + 7)/8;
1407  DataT* y = m_channel[0]; ASSERT(y);
1408 
1409  // new unpacked version since version 7
1410  for (UINT32 h = 0; h < m_header.height; h++) {
1411  if (cb) {
1412  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1413  percent += dP;
1414  }
1415  cnt = 0;
1416  for (UINT32 j = 0; j < w2; j++) {
1417  UINT8 byte = buff[j];
1418  for (int k = 0; k < 8; k++) {
1419  UINT8 bit = (byte & 0x80) >> 7;
1420  if (cnt < w) y[yPos++] = bit;
1421  byte <<= 1;
1422  cnt++;
1423  }
1424  }
1425  buff += pitch;
1426  }
1427  /* old version: packed values: 8 pixels in 1 byte
1428  for (UINT32 h = 0; h < m_header.height; h++) {
1429  if (cb) {
1430  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1431  percent += dP;
1432  }
1433 
1434  for (UINT32 j = 0; j < w2; j++) {
1435  y[yPos++] = buff[j] - YUVoffset8;
1436  }
1437  // version 5 and 6
1438  // for (UINT32 j = w2; j < w; j++) {
1439  // y[yPos++] = YUVoffset8;
1440  //}
1441  buff += pitch;
1442  }
1443  */
1444  }
1445  break;
1446  case ImageModeIndexedColor:
1447  case ImageModeGrayScale:
1448  case ImageModeHSLColor:
1449  case ImageModeHSBColor:
1450  case ImageModeLabColor:
1451  {
1452  ASSERT(m_header.channels >= 1);
1453  ASSERT(m_header.bpp == m_header.channels*8);
1454  ASSERT(bpp%8 == 0);
1455  const int channels = bpp/8; ASSERT(channels >= m_header.channels);
1456 
1457  for (UINT32 h=0; h < m_header.height; h++) {
1458  if (cb) {
1459  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1460  percent += dP;
1461  }
1462 
1463  cnt = 0;
1464  for (UINT32 w=0; w < m_header.width; w++) {
1465  for (int c=0; c < m_header.channels; c++) {
1466  m_channel[c][yPos] = buff[cnt + channelMap[c]] - YUVoffset8;
1467  }
1468  cnt += channels;
1469  yPos++;
1470  }
1471  buff += pitch;
1472  }
1473  }
1474  break;
1475  case ImageModeGray16:
1476  case ImageModeLab48:
1477  {
1478  ASSERT(m_header.channels >= 1);
1479  ASSERT(m_header.bpp == m_header.channels*16);
1480  ASSERT(bpp%16 == 0);
1481 
1482  UINT16 *buff16 = (UINT16 *)buff;
1483  const int pitch16 = pitch/2;
1484  const int channels = bpp/16; ASSERT(channels >= m_header.channels);
1485  const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
1486  const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
1487 
1488  for (UINT32 h=0; h < m_header.height; h++) {
1489  if (cb) {
1490  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1491  percent += dP;
1492  }
1493 
1494  cnt = 0;
1495  for (UINT32 w=0; w < m_header.width; w++) {
1496  for (int c=0; c < m_header.channels; c++) {
1497  m_channel[c][yPos] = (buff16[cnt + channelMap[c]] >> shift) - yuvOffset16;
1498  }
1499  cnt += channels;
1500  yPos++;
1501  }
1502  buff16 += pitch16;
1503  }
1504  }
1505  break;
1506  case ImageModeRGBColor:
1507  {
1508  ASSERT(m_header.channels == 3);
1509  ASSERT(m_header.bpp == m_header.channels*8);
1510  ASSERT(bpp%8 == 0);
1511 
1512  DataT* y = m_channel[0]; ASSERT(y);
1513  DataT* u = m_channel[1]; ASSERT(u);
1514  DataT* v = m_channel[2]; ASSERT(v);
1515  const int channels = bpp/8; ASSERT(channels >= m_header.channels);
1516  UINT8 b, g, r;
1517 
1518  for (UINT32 h=0; h < m_header.height; h++) {
1519  if (cb) {
1520  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1521  percent += dP;
1522  }
1523 
1524  cnt = 0;
1525  for (UINT32 w=0; w < m_header.width; w++) {
1526  b = buff[cnt + channelMap[0]];
1527  g = buff[cnt + channelMap[1]];
1528  r = buff[cnt + channelMap[2]];
1529  // Yuv
1530  y[yPos] = ((b + (g << 1) + r) >> 2) - YUVoffset8;
1531  u[yPos] = r - g;
1532  v[yPos] = b - g;
1533  yPos++;
1534  cnt += channels;
1535  }
1536  buff += pitch;
1537  }
1538  }
1539  break;
1540  case ImageModeRGB48:
1541  {
1542  ASSERT(m_header.channels == 3);
1543  ASSERT(m_header.bpp == m_header.channels*16);
1544  ASSERT(bpp%16 == 0);
1545 
1546  UINT16 *buff16 = (UINT16 *)buff;
1547  const int pitch16 = pitch/2;
1548  const int channels = bpp/16; ASSERT(channels >= m_header.channels);
1549  const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
1550  const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
1551 
1552  DataT* y = m_channel[0]; ASSERT(y);
1553  DataT* u = m_channel[1]; ASSERT(u);
1554  DataT* v = m_channel[2]; ASSERT(v);
1555  UINT16 b, g, r;
1556 
1557  for (UINT32 h=0; h < m_header.height; h++) {
1558  if (cb) {
1559  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1560  percent += dP;
1561  }
1562 
1563  cnt = 0;
1564  for (UINT32 w=0; w < m_header.width; w++) {
1565  b = buff16[cnt + channelMap[0]] >> shift;
1566  g = buff16[cnt + channelMap[1]] >> shift;
1567  r = buff16[cnt + channelMap[2]] >> shift;
1568  // Yuv
1569  y[yPos] = ((b + (g << 1) + r) >> 2) - yuvOffset16;
1570  u[yPos] = r - g;
1571  v[yPos] = b - g;
1572  yPos++;
1573  cnt += channels;
1574  }
1575  buff16 += pitch16;
1576  }
1577  }
1578  break;
1579  case ImageModeRGBA:
1580  case ImageModeCMYKColor:
1581  {
1582  ASSERT(m_header.channels == 4);
1583  ASSERT(m_header.bpp == m_header.channels*8);
1584  ASSERT(bpp%8 == 0);
1585  const int channels = bpp/8; ASSERT(channels >= m_header.channels);
1586 
1587  DataT* y = m_channel[0]; ASSERT(y);
1588  DataT* u = m_channel[1]; ASSERT(u);
1589  DataT* v = m_channel[2]; ASSERT(v);
1590  DataT* a = m_channel[3]; ASSERT(a);
1591  UINT8 b, g, r;
1592 
1593  for (UINT32 h=0; h < m_header.height; h++) {
1594  if (cb) {
1595  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1596  percent += dP;
1597  }
1598 
1599  cnt = 0;
1600  for (UINT32 w=0; w < m_header.width; w++) {
1601  b = buff[cnt + channelMap[0]];
1602  g = buff[cnt + channelMap[1]];
1603  r = buff[cnt + channelMap[2]];
1604  // Yuv
1605  y[yPos] = ((b + (g << 1) + r) >> 2) - YUVoffset8;
1606  u[yPos] = r - g;
1607  v[yPos] = b - g;
1608  a[yPos++] = buff[cnt + channelMap[3]] - YUVoffset8;
1609  cnt += channels;
1610  }
1611  buff += pitch;
1612  }
1613  }
1614  break;
1615  case ImageModeCMYK64:
1616  {
1617  ASSERT(m_header.channels == 4);
1618  ASSERT(m_header.bpp == m_header.channels*16);
1619  ASSERT(bpp%16 == 0);
1620 
1621  UINT16 *buff16 = (UINT16 *)buff;
1622  const int pitch16 = pitch/2;
1623  const int channels = bpp/16; ASSERT(channels >= m_header.channels);
1624  const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
1625  const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
1626 
1627  DataT* y = m_channel[0]; ASSERT(y);
1628  DataT* u = m_channel[1]; ASSERT(u);
1629  DataT* v = m_channel[2]; ASSERT(v);
1630  DataT* a = m_channel[3]; ASSERT(a);
1631  UINT16 b, g, r;
1632 
1633  for (UINT32 h=0; h < m_header.height; h++) {
1634  if (cb) {
1635  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1636  percent += dP;
1637  }
1638 
1639  cnt = 0;
1640  for (UINT32 w=0; w < m_header.width; w++) {
1641  b = buff16[cnt + channelMap[0]] >> shift;
1642  g = buff16[cnt + channelMap[1]] >> shift;
1643  r = buff16[cnt + channelMap[2]] >> shift;
1644  // Yuv
1645  y[yPos] = ((b + (g << 1) + r) >> 2) - yuvOffset16;
1646  u[yPos] = r - g;
1647  v[yPos] = b - g;
1648  a[yPos++] = (buff16[cnt + channelMap[3]] >> shift) - yuvOffset16;
1649  cnt += channels;
1650  }
1651  buff16 += pitch16;
1652  }
1653  }
1654  break;
1655 #ifdef __PGF32SUPPORT__
1656  case ImageModeGray32:
1657  {
1658  ASSERT(m_header.channels == 1);
1659  ASSERT(m_header.bpp == 32);
1660  ASSERT(bpp == 32);
1661  ASSERT(DataTSize == sizeof(UINT32));
1662 
1663  DataT* y = m_channel[0]; ASSERT(y);
1664 
1665  UINT32 *buff32 = (UINT32 *)buff;
1666  const int pitch32 = pitch/4;
1667  const int shift = 31 - UsedBitsPerChannel(); ASSERT(shift >= 0);
1668  const DataT yuvOffset31 = 1 << (UsedBitsPerChannel() - 1);
1669 
1670  for (UINT32 h=0; h < m_header.height; h++) {
1671  if (cb) {
1672  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1673  percent += dP;
1674  }
1675 
1676  for (UINT32 w=0; w < m_header.width; w++) {
1677  y[yPos++] = (buff32[w] >> shift) - yuvOffset31;
1678  }
1679  buff32 += pitch32;
1680  }
1681  }
1682  break;
1683 #endif
1684  case ImageModeRGB12:
1685  {
1686  ASSERT(m_header.channels == 3);
1687  ASSERT(m_header.bpp == m_header.channels*4);
1688  ASSERT(bpp == m_header.channels*4);
1689 
1690  DataT* y = m_channel[0]; ASSERT(y);
1691  DataT* u = m_channel[1]; ASSERT(u);
1692  DataT* v = m_channel[2]; ASSERT(v);
1693 
1694  UINT8 rgb = 0, b, g, r;
1695 
1696  for (UINT32 h=0; h < m_header.height; h++) {
1697  if (cb) {
1698  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1699  percent += dP;
1700  }
1701 
1702  cnt = 0;
1703  for (UINT32 w=0; w < m_header.width; w++) {
1704  if (w%2 == 0) {
1705  // even pixel position
1706  rgb = buff[cnt];
1707  b = rgb & 0x0F;
1708  g = (rgb & 0xF0) >> 4;
1709  cnt++;
1710  rgb = buff[cnt];
1711  r = rgb & 0x0F;
1712  } else {
1713  // odd pixel position
1714  b = (rgb & 0xF0) >> 4;
1715  cnt++;
1716  rgb = buff[cnt];
1717  g = rgb & 0x0F;
1718  r = (rgb & 0xF0) >> 4;
1719  cnt++;
1720  }
1721 
1722  // Yuv
1723  y[yPos] = ((b + (g << 1) + r) >> 2) - YUVoffset4;
1724  u[yPos] = r - g;
1725  v[yPos] = b - g;
1726  yPos++;
1727  }
1728  buff += pitch;
1729  }
1730  }
1731  break;
1732  case ImageModeRGB16:
1733  {
1734  ASSERT(m_header.channels == 3);
1735  ASSERT(m_header.bpp == 16);
1736  ASSERT(bpp == 16);
1737 
1738  DataT* y = m_channel[0]; ASSERT(y);
1739  DataT* u = m_channel[1]; ASSERT(u);
1740  DataT* v = m_channel[2]; ASSERT(v);
1741 
1742  UINT16 *buff16 = (UINT16 *)buff;
1743  UINT16 rgb, b, g, r;
1744  const int pitch16 = pitch/2;
1745 
1746  for (UINT32 h=0; h < m_header.height; h++) {
1747  if (cb) {
1748  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1749  percent += dP;
1750  }
1751  for (UINT32 w=0; w < m_header.width; w++) {
1752  rgb = buff16[w];
1753  r = (rgb & 0xF800) >> 10; // highest 5 bits
1754  g = (rgb & 0x07E0) >> 5; // middle 6 bits
1755  b = (rgb & 0x001F) << 1; // lowest 5 bits
1756  // Yuv
1757  y[yPos] = ((b + (g << 1) + r) >> 2) - YUVoffset6;
1758  u[yPos] = r - g;
1759  v[yPos] = b - g;
1760  yPos++;
1761  }
1762 
1763  buff16 += pitch16;
1764  }
1765  }
1766  break;
1767  default:
1768  ASSERT(false);
1769  }
1770 }
#define ImageModeIndexedColor
Definition: PGFplatform.h:100
#define ImageModeRGB12
Definition: PGFplatform.h:117
UINT8 mode
image mode according to Adobe's image modes
Definition: PGFtypes.h:159
#define ImageModeHSBColor
Definition: PGFplatform.h:104
#define MaxChannels
maximum number of (color) channels
Definition: PGFtypes.h:64
BYTE UsedBitsPerChannel() const
Definition: PGFimage.cpp:756
UINT32 width
image width in pixels
Definition: PGFtypes.h:153
INT32 DataT
Definition: PGFtypes.h:269
#define ImageModeRGBA
Definition: PGFplatform.h:115
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
#define DataTSize
Definition: PGFtypes.h:283
#define ImageModeLabColor
Definition: PGFplatform.h:107
DataT * m_channel[MaxChannels]
untransformed channels in YUV format
Definition: PGFimage.h:522
#define ImageModeGray16
Definition: PGFplatform.h:108
#define ImageModeLab48
Definition: PGFplatform.h:110
#define ImageModeCMYKColor
Definition: PGFplatform.h:102
#define ImageModeGrayScale
Definition: PGFplatform.h:99
UINT8 bpp
bits per pixel
Definition: PGFtypes.h:157
#define YUVoffset6
Definition: PGFimage.cpp:37
#define ImageModeGray32
Definition: PGFplatform.h:116
#define ImageModeRGBColor
Definition: PGFplatform.h:101
#define ImageModeHSLColor
Definition: PGFplatform.h:103
#define ImageModeBitmap
Definition: PGFplatform.h:98
UINT8 channels
number of channels
Definition: PGFtypes.h:158
#define ImageModeCMYK64
Definition: PGFplatform.h:111
#define YUVoffset4
Definition: PGFimage.cpp:36
#define ImageModeRGB16
Definition: PGFplatform.h:118
#define YUVoffset8
Definition: PGFimage.cpp:38
UINT32 height
image height in pixels
Definition: PGFtypes.h:154
#define ImageModeRGB48
Definition: PGFplatform.h:109

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

466 { return (m_preHeader.version & PGFROI) == PGFROI; }
UINT8 version
PGF version.
Definition: PGFtypes.h:115
PGFPreHeader m_preHeader
PGF pre-header.
Definition: PGFimage.h:528
#define PGFROI
supports Regions Of Interest
Definition: PGFtypes.h:70

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

272 { ASSERT(c >= 0 && c < MaxChannels); m_channel[c] = channel; }
#define MaxChannels
maximum number of (color) channels
Definition: PGFtypes.h:64
DataT * m_channel[MaxChannels]
untransformed channels in YUV format
Definition: PGFimage.h:522

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

1364  {
1365  if (iFirstColor + nColors > ColorTableLen) ReturnWithError(ColorTableError);
1366 
1367  for (UINT32 i=iFirstColor, j=0; j < nColors; i++, j++) {
1368  m_postHeader.clut[i] = prgbColors[j];
1369  }
1370 }
#define ColorTableLen
size of color lookup table (clut)
Definition: PGFtypes.h:66
PGFPostHeader m_postHeader
PGF post-header.
Definition: PGFimage.h:530
RGBQUAD clut[ColorTableLen]
color table for indexed color images (optional part of file header)
Definition: PGFtypes.h:170

◆ SetHeader()

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

Set PGF header and user data. Precondition: The PGF image has been 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 894 of file PGFimage.cpp.

894  {
895  ASSERT(!m_decoder); // current image must be closed
896  ASSERT(header.quality <= MaxQuality);
897  ASSERT(userDataLength <= MaxUserDataSize);
898 
899  // init state
900 #ifdef __PGFROISUPPORT__
901  m_streamReinitialized = false;
902 #endif
903 
904  // init preHeader
905  memcpy(m_preHeader.magic, PGFMagic, 3);
906  m_preHeader.version = PGFVersion | flags;
908 
909  // copy header
910  memcpy(&m_header, &header, HeaderSize);
911 
912  // check quality
914 
915  // complete header
916  CompleteHeader();
917 
918  // check and set number of levels
919  ComputeLevels();
920 
921  // check for downsample
929  m_downsample = true;
930  m_quant = m_header.quality - 1;
931  } else {
932  m_downsample = false;
934  }
935 
936  // update header size and copy user data
938  // update header size
940  }
941  if (userDataLength && userData) {
942  if (userDataLength > MaxUserDataSize) userDataLength = MaxUserDataSize;
943  m_postHeader.userData = new(std::nothrow) UINT8[userDataLength];
944  if (!m_postHeader.userData) ReturnWithError(InsufficientMemory);
946  memcpy(m_postHeader.userData, userData, userDataLength);
947  // update header size
948  m_preHeader.hSize += userDataLength;
949  }
950 
951  // allocate channels
952  for (int i=0; i < m_header.channels; i++) {
953  // set current width and height
954  m_width[i] = m_header.width;
955  m_height[i] = m_header.height;
956 
957  // allocate channels
958  ASSERT(!m_channel[i]);
959  m_channel[i] = new(std::nothrow) DataT[m_header.width*m_header.height];
960  if (!m_channel[i]) {
961  if (i) i--;
962  while(i) {
963  delete[] m_channel[i]; m_channel[i] = 0;
964  i--;
965  }
966  ReturnWithError(InsufficientMemory);
967  }
968  }
969 }
#define ImageModeIndexedColor
Definition: PGFplatform.h:100
UINT8 version
PGF version.
Definition: PGFtypes.h:115
UINT8 mode
image mode according to Adobe's image modes
Definition: PGFtypes.h:159
#define PGFVersion
current standard version
Definition: PGFtypes.h:76
UINT32 width
image width in pixels
Definition: PGFtypes.h:153
#define ColorTableSize
Definition: PGFtypes.h:282
INT32 DataT
Definition: PGFtypes.h:269
UINT32 userDataLen
user data size in bytes (not part of file header)
Definition: PGFtypes.h:172
#define ImageModeRGBA
Definition: PGFplatform.h:115
CDecoder * m_decoder
PGF decoder.
Definition: PGFimage.h:523
UINT8 * userData
user data of size userDataLen (optional part of file header)
Definition: PGFtypes.h:171
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
bool m_streamReinitialized
stream has been reinitialized
Definition: PGFimage.h:540
bool CompleteHeader()
Definition: PGFimage.cpp:218
BYTE m_quant
quantization parameter
Definition: PGFimage.h:534
#define HeaderSize
Definition: PGFtypes.h:281
#define ImageModeLabColor
Definition: PGFplatform.h:107
DataT * m_channel[MaxChannels]
untransformed channels in YUV format
Definition: PGFimage.h:522
PGFPreHeader m_preHeader
PGF pre-header.
Definition: PGFimage.h:528
#define PGFMagic
PGF identification.
Definition: PGFtypes.h:61
#define ImageModeLab48
Definition: PGFplatform.h:110
UINT32 cachedUserDataLen
cached user data size in bytes (not part of file header)
Definition: PGFtypes.h:173
#define ImageModeCMYKColor
Definition: PGFplatform.h:102
char magic[3]
PGF identification = "PGF".
Definition: PGFtypes.h:114
PGFPostHeader m_postHeader
PGF post-header.
Definition: PGFimage.h:530
void ComputeLevels()
Definition: PGFimage.cpp:854
bool m_downsample
chrominance channels are downsampled
Definition: PGFimage.h:535
#define DownsampleThreshold
if quality is larger than this threshold than downsampling is used
Definition: PGFtypes.h:65
UINT32 hSize
total size of PGFHeader, [ColorTable], and [UserData] in bytes (since Version 6: 4 Bytes)
Definition: PGFtypes.h:124
UINT32 m_width[MaxChannels]
width of each channel at current level
Definition: PGFimage.h:526
#define MaxQuality
maximum quality
Definition: PGFtypes.h:94
#define ImageModeRGBColor
Definition: PGFplatform.h:101
UINT8 channels
number of channels
Definition: PGFtypes.h:158
#define MaxUserDataSize
Definition: PGFtypes.h:284
#define ImageModeCMYK64
Definition: PGFplatform.h:111
UINT8 quality
quantization parameter: 0=lossless, 4=standard, 6=poor quality
Definition: PGFtypes.h:156
UINT32 height
image height in pixels
Definition: PGFtypes.h:154
#define ImageModeRGB48
Definition: PGFplatform.h:109
UINT32 m_height[MaxChannels]
height of each channel at current level
Definition: PGFimage.h:527

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

738  {
739  const BYTE bpc = m_header.bpp/m_header.channels;
740  BYTE pot = 0;
741 
742  while(maxValue > 0) {
743  pot++;
744  maxValue >>= 1;
745  }
746  // store bits per channel
747  if (pot > bpc) pot = bpc;
748  if (pot > 31) pot = 31;
750 }
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
UINT8 usedBitsPerChannel
number of used bits per channel in 16- and 32-bit per channel modes
Definition: PGFtypes.h:160
UINT8 bpp
bits per pixel
Definition: PGFtypes.h:157
UINT8 channels
number of channels
Definition: PGFtypes.h:158

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

296 { m_progressMode = pm; }
ProgressMode m_progressMode
progress mode used in Read and Write; PM_Relative is default mode
Definition: PGFimage.h:548

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

303 { m_cb = callback; m_cbArg = arg; }
void * m_cbArg
refresh callback argument
Definition: PGFimage.h:546
RefreshCB m_cb
pointer to refresh callback procedure
Definition: PGFimage.h:545

◆ SetROI()

void CPGFImage::SetROI ( PGFRect  rect)
private

◆ UpdatePostHeaderSize()

UINT32 CPGFImage::UpdatePostHeaderSize ( )
private

Definition at line 1124 of file PGFimage.cpp.

1124  {
1125  ASSERT(m_encoder);
1126 
1127  INT64 offset = m_encoder->ComputeOffset(); ASSERT(offset >= 0);
1128 
1129  if (offset > 0) {
1130  // update post-header size and rewrite pre-header
1131  m_preHeader.hSize += (UINT32)offset;
1133  }
1134 
1135  // write dummy levelLength into stream
1137 }
PGFPreHeader m_preHeader
PGF pre-header.
Definition: PGFimage.h:528
UINT32 WriteLevelLength(UINT32 *&levelLength)
Definition: Encoder.cpp:177
void UpdatePostHeaderSize(PGFPreHeader preHeader)
Definition: Encoder.cpp:160
UINT32 * m_levelLength
length of each level in bytes; first level starts immediately after this array
Definition: PGFimage.h:525
UINT32 hSize
total size of PGFHeader, [ColorTable], and [UserData] in bytes (since Version 6: 4 Bytes)
Definition: PGFtypes.h:124
CEncoder * m_encoder
PGF encoder.
Definition: PGFimage.h:524
INT64 ComputeOffset() const
Definition: Encoder.h:184

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

756  {
757  const BYTE bpc = m_header.bpp/m_header.channels;
758 
759  if (bpc > 8) {
761  } else {
762  return bpc;
763  }
764 }
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
UINT8 usedBitsPerChannel
number of used bits per channel in 16- and 32-bit per channel modes
Definition: PGFtypes.h:160
UINT8 bpp
bits per pixel
Definition: PGFtypes.h:157
UINT8 channels
number of channels
Definition: PGFtypes.h:158

◆ Version()

BYTE CPGFImage::Version ( ) const
inline

Returns the used codec major version of a pgf image

Returns
PGF codec major version of this image

Definition at line 484 of file PGFimage.h.

484 { BYTE ver = CodecMajorVersion(m_preHeader.version); return (ver <= 7) ? ver : (BYTE)m_header.version.major; }
UINT8 version
PGF version.
Definition: PGFtypes.h:115
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
PGFPreHeader m_preHeader
PGF pre-header.
Definition: PGFimage.h:528
static BYTE CodecMajorVersion(BYTE version=PGFVersion)
Return major version.
Definition: PGFimage.cpp:768
UINT16 major
major version number
Definition: PGFtypes.h:140
PGFVersionNumber version
codec version number: (since Version 7)
Definition: PGFtypes.h:161

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

413 { ASSERT(level >= 0); return LevelSizeL(m_header.width, level); }
UINT32 width
image width in pixels
Definition: PGFtypes.h:153
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
static UINT32 LevelSizeL(UINT32 size, int level)
Definition: PGFimage.h:499

◆ Write() [1/2]

void CPGFImage::Write ( CPGFStream stream,
UINT32 *  nWrittenBytes = nullptr,
CallbackPtr  cb = nullptr,
void *  data = nullptr 
)

Encode and write an 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 1221 of file PGFimage.cpp.

1221  {
1222  ASSERT(stream);
1223  ASSERT(m_preHeader.hSize);
1224 
1225  // create wavelet transform channels and encoder
1226  UINT32 nBytes = WriteHeader(stream);
1227 
1228  // write image
1229  nBytes += WriteImage(stream, cb, data);
1230 
1231  // return written bytes
1232  if (nWrittenBytes) *nWrittenBytes += nBytes;
1233 }
PGFPreHeader m_preHeader
PGF pre-header.
Definition: PGFimage.h:528
UINT32 WriteImage(CPGFStream *stream, CallbackPtr cb=nullptr, void *data=nullptr)
Definition: PGFimage.cpp:1150
UINT32 WriteHeader(CPGFStream *stream)
Definition: PGFimage.cpp:979
UINT32 hSize
total size of PGFHeader, [ColorTable], and [UserData] in bytes (since Version 6: 4 Bytes)
Definition: PGFtypes.h:124

◆ Write() [2/2]

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

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.

Create wavelet transform channels and encoder. Write header at current stream position. Performs forward FWT. 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 979 of file PGFimage.cpp.

979  {
980  ASSERT(m_header.nLevels <= MaxLevel);
981  ASSERT(m_header.quality <= MaxQuality); // quality is already initialized
982 
983  if (m_header.nLevels > 0) {
984  volatile OSError error = NoError; // volatile prevents optimizations
985  // create new wt channels
986 #ifdef LIBPGF_USE_OPENMP
987  #pragma omp parallel for default(shared)
988 #endif
989  for (int i=0; i < m_header.channels; i++) {
990  DataT *temp = nullptr;
991  if (error == NoError) {
992  if (m_wtChannel[i]) {
993  ASSERT(m_channel[i]);
994  // copy m_channel to temp
995  int size = m_height[i]*m_width[i];
996  temp = new(std::nothrow) DataT[size];
997  if (temp) {
998  memcpy(temp, m_channel[i], size*DataTSize);
999  delete m_wtChannel[i]; // also deletes m_channel
1000  m_channel[i] = nullptr;
1001  } else {
1002  error = InsufficientMemory;
1003  }
1004  }
1005  if (error == NoError) {
1006  if (temp) {
1007  ASSERT(!m_channel[i]);
1008  m_channel[i] = temp;
1009  }
1011  if (m_wtChannel[i]) {
1012  #ifdef __PGFROISUPPORT__
1013  m_wtChannel[i]->SetROI(PGFRect(0, 0, m_width[i], m_height[i]));
1014  #endif
1015 
1016  // wavelet subband decomposition
1017  for (int l=0; error == NoError && l < m_header.nLevels; l++) {
1018  OSError err = m_wtChannel[i]->ForwardTransform(l, m_quant);
1019  if (err != NoError) error = err;
1020  }
1021  } else {
1022  delete[] m_channel[i];
1023  error = InsufficientMemory;
1024  }
1025  }
1026  }
1027  }
1028  if (error != NoError) {
1029  // free already allocated memory
1030  for (int i=0; i < m_header.channels; i++) {
1031  delete m_wtChannel[i];
1032  }
1033  ReturnWithError(error);
1034  }
1035 
1037 
1038  // create encoder, write headers and user data, but not level-length area
1041 
1042  #ifdef __PGFROISUPPORT__
1043  if (ROIisSupported()) {
1044  // new encoding scheme supporting ROI
1045  m_encoder->SetROI();
1046  }
1047  #endif
1048 
1049  } else {
1050  // very small image: we don't use DWT and encoding
1051 
1052  // create encoder, write headers and user data, but not level-length area
1054  }
1055 
1056  INT64 nBytes = m_encoder->ComputeHeaderLength();
1057  return (nBytes > 0) ? (UINT32)nBytes : 0;
1058 }
bool m_favorSpeedOverSize
favor encoding speed over compression ratio
Definition: PGFimage.h:536
UINT64 m_userDataPos
stream position of user data
Definition: PGFimage.h:531
INT32 DataT
Definition: PGFtypes.h:269
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
BYTE m_quant
quantization parameter
Definition: PGFimage.h:534
#define DataTSize
Definition: PGFtypes.h:283
DataT * m_channel[MaxChannels]
untransformed channels in YUV format
Definition: PGFimage.h:522
PGFPreHeader m_preHeader
PGF pre-header.
Definition: PGFimage.h:528
UINT8 nLevels
number of FWT transforms
Definition: PGFtypes.h:155
OSError ForwardTransform(int level, int quant)
#define MaxLevel
maximum number of transform levels
Definition: PGFtypes.h:62
CWaveletTransform * m_wtChannel[MaxChannels]
wavelet transformed color channels
Definition: PGFimage.h:521
PGFPostHeader m_postHeader
PGF post-header.
Definition: PGFimage.h:530
friend class CWaveletTransform
Definition: Subband.h:43
UINT32 m_width[MaxChannels]
width of each channel at current level
Definition: PGFimage.h:526
bool ROIisSupported() const
Definition: PGFimage.h:466
#define MaxQuality
maximum quality
Definition: PGFtypes.h:94
bool m_useOMPinEncoder
use Open MP in encoder
Definition: PGFimage.h:537
INT64 ComputeHeaderLength() const
Definition: Encoder.h:174
void FavorSpeedOverSize()
Encoder favors speed over compression size.
Definition: Encoder.h:121
UINT8 channels
number of channels
Definition: PGFtypes.h:158
Rectangle.
Definition: PGFtypes.h:225
CEncoder * m_encoder
PGF encoder.
Definition: PGFimage.h:524
int m_currentLevel
transform level of current image
Definition: PGFimage.h:532
UINT8 quality
quantization parameter: 0=lossless, 4=standard, 6=poor quality
Definition: PGFtypes.h:156
UINT32 m_height[MaxChannels]
height of each channel at current level
Definition: PGFimage.h:527
PGF encoder.
Definition: Encoder.h:46

◆ WriteImage()

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

Encode and write an 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 1150 of file PGFimage.cpp.

1150  {
1151  ASSERT(stream);
1152  ASSERT(m_preHeader.hSize);
1153 
1154  int levels = m_header.nLevels;
1155  double percent = pow(0.25, levels);
1156 
1157  // update post-header size, rewrite pre-header, and write dummy levelLength
1158  UINT32 nWrittenBytes = UpdatePostHeaderSize();
1159 
1160  if (levels == 0) {
1161  // for very small images: write channels uncoded
1162  for (int c=0; c < m_header.channels; c++) {
1163  const UINT32 size = m_width[c]*m_height[c];
1164 
1165  // write channel data into stream
1166  for (UINT32 i=0; i < size; i++) {
1167  int count = DataTSize;
1168  stream->Write(&count, &m_channel[c][i]);
1169  }
1170  }
1171 
1172  // now update progress
1173  if (cb) {
1174  if ((*cb)(1, true, data)) ReturnWithError(EscapePressed);
1175  }
1176 
1177  } else {
1178  // encode quantized wavelet coefficients and write to PGF file
1179  // encode subbands, higher levels first
1180  // color channels are interleaved
1181 
1182  // encode all levels
1183  for (m_currentLevel = levels; m_currentLevel > 0; ) {
1184  WriteLevel(); // decrements m_currentLevel
1185 
1186  // now update progress
1187  if (cb) {
1188  percent *= 4;
1189  if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1190  }
1191  }
1192 
1193  // flush encoder and write level lengths
1194  m_encoder->Flush();
1195  }
1196 
1197  // update level lengths
1198  nWrittenBytes += m_encoder->UpdateLevelLength(); // return written image bytes
1199 
1200  // delete encoder
1201  delete m_encoder; m_encoder = nullptr;
1202 
1203  ASSERT(!m_encoder);
1204 
1205  return nWrittenBytes;
1206 }
virtual void Write(int *count, void *buffer)=0
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
void WriteLevel()
Definition: PGFimage.cpp:1068
#define DataTSize
Definition: PGFtypes.h:283
DataT * m_channel[MaxChannels]
untransformed channels in YUV format
Definition: PGFimage.h:522
PGFPreHeader m_preHeader
PGF pre-header.
Definition: PGFimage.h:528
UINT8 nLevels
number of FWT transforms
Definition: PGFtypes.h:155
UINT32 hSize
total size of PGFHeader, [ColorTable], and [UserData] in bytes (since Version 6: 4 Bytes)
Definition: PGFtypes.h:124
UINT32 m_width[MaxChannels]
width of each channel at current level
Definition: PGFimage.h:526
void Flush()
Definition: Encoder.cpp:310
UINT32 UpdateLevelLength()
Definition: Encoder.cpp:202
UINT8 channels
number of channels
Definition: PGFtypes.h:158
CEncoder * m_encoder
PGF encoder.
Definition: PGFimage.h:524
int m_currentLevel
transform level of current image
Definition: PGFimage.h:532
UINT32 m_height[MaxChannels]
height of each channel at current level
Definition: PGFimage.h:527
UINT32 UpdatePostHeaderSize()
Definition: PGFimage.cpp:1124

◆ WriteLevel()

void CPGFImage::WriteLevel ( )
private

Definition at line 1068 of file PGFimage.cpp.

1068  {
1069  ASSERT(m_encoder);
1070  ASSERT(m_currentLevel > 0);
1071  ASSERT(m_header.nLevels > 0);
1072 
1073 #ifdef __PGFROISUPPORT__
1074  if (ROIisSupported()) {
1075  const int lastChannel = m_header.channels - 1;
1076 
1077  for (int i=0; i < m_header.channels; i++) {
1078  // get number of tiles and tile indices
1079  const UINT32 nTiles = m_wtChannel[i]->GetNofTiles(m_currentLevel);
1080  const UINT32 lastTile = nTiles - 1;
1081 
1082  if (m_currentLevel == m_header.nLevels) {
1083  // last level also has LL band
1084  ASSERT(nTiles == 1);
1086  m_encoder->EncodeTileBuffer(); // encode macro block with tile-end = true
1087  }
1088  for (UINT32 tileY=0; tileY < nTiles; tileY++) {
1089  for (UINT32 tileX=0; tileX < nTiles; tileX++) {
1090  // extract tile to macro block and encode already filled macro blocks with tile-end = false
1091  m_wtChannel[i]->GetSubband(m_currentLevel, HL)->ExtractTile(*m_encoder, true, tileX, tileY);
1092  m_wtChannel[i]->GetSubband(m_currentLevel, LH)->ExtractTile(*m_encoder, true, tileX, tileY);
1093  m_wtChannel[i]->GetSubband(m_currentLevel, HH)->ExtractTile(*m_encoder, true, tileX, tileY);
1094  if (i == lastChannel && tileY == lastTile && tileX == lastTile) {
1095  // all necessary data are buffered. next call of EncodeTileBuffer will write the last piece of data of the current level.
1097  }
1098  m_encoder->EncodeTileBuffer(); // encode last macro block with tile-end = true
1099  }
1100  }
1101  }
1102  } else
1103 #endif
1104  {
1105  for (int i=0; i < m_header.channels; i++) {
1106  ASSERT(m_wtChannel[i]);
1107  if (m_currentLevel == m_header.nLevels) {
1108  // last level also has LL band
1110  }
1111  //encoder.EncodeInterleaved(m_wtChannel[i], m_currentLevel, m_quant); // until version 4
1112  m_wtChannel[i]->GetSubband(m_currentLevel, HL)->ExtractTile(*m_encoder); // since version 5
1113  m_wtChannel[i]->GetSubband(m_currentLevel, LH)->ExtractTile(*m_encoder); // since version 5
1115  }
1116 
1117  // all necessary data are buffered. next call of EncodeBuffer will write the last piece of data of the current level.
1119  }
1120 }
Definition: PGFtypes.h:99
void ExtractTile(CEncoder &encoder, bool tile=false, UINT32 tileX=0, UINT32 tileY=0)
Definition: Subband.cpp:177
PGFHeader m_header
PGF file header.
Definition: PGFimage.h:529
UINT8 nLevels
number of FWT transforms
Definition: PGFtypes.h:155
CWaveletTransform * m_wtChannel[MaxChannels]
wavelet transformed color channels
Definition: PGFimage.h:521
Definition: PGFtypes.h:99
Definition: PGFtypes.h:99
CSubband * GetSubband(int level, Orientation orientation)
bool ROIisSupported() const
Definition: PGFimage.h:466
Definition: PGFtypes.h:99
UINT8 channels
number of channels
Definition: PGFtypes.h:158
CEncoder * m_encoder
PGF encoder.
Definition: PGFimage.h:524
int m_currentLevel
transform level of current image
Definition: PGFimage.h:532
void SetEncodedLevel(int currentLevel)
Definition: Encoder.h:162

Member Data Documentation

◆ m_cb

RefreshCB CPGFImage::m_cb
private

pointer to refresh callback procedure

Definition at line 545 of file PGFimage.h.

◆ m_cbArg

void* CPGFImage::m_cbArg
private

refresh callback argument

Definition at line 546 of file PGFimage.h.

◆ m_channel

DataT* CPGFImage::m_channel[MaxChannels]
protected

untransformed channels in YUV format

Definition at line 522 of file PGFimage.h.

◆ m_currentLevel

int CPGFImage::m_currentLevel
protected

transform level of current image

Definition at line 532 of file PGFimage.h.

◆ m_decoder

CDecoder* CPGFImage::m_decoder
protected

PGF decoder.

Definition at line 523 of file PGFimage.h.

◆ m_downsample

bool CPGFImage::m_downsample
protected

chrominance channels are downsampled

Definition at line 535 of file PGFimage.h.

◆ m_encoder

CEncoder* CPGFImage::m_encoder
protected

PGF encoder.

Definition at line 524 of file PGFimage.h.

◆ m_favorSpeedOverSize

bool CPGFImage::m_favorSpeedOverSize
protected

favor encoding speed over compression ratio

Definition at line 536 of file PGFimage.h.

◆ m_header

PGFHeader CPGFImage::m_header
protected

PGF file header.

Definition at line 529 of file PGFimage.h.

◆ m_height

UINT32 CPGFImage::m_height[MaxChannels]
protected

height of each channel at current level

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

◆ m_percent

double CPGFImage::m_percent
private

progress [0..1]

Definition at line 547 of file PGFimage.h.

◆ m_postHeader

PGFPostHeader CPGFImage::m_postHeader
protected

PGF post-header.

Definition at line 530 of file PGFimage.h.

◆ m_preHeader

PGFPreHeader CPGFImage::m_preHeader
protected

PGF pre-header.

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

◆ m_quant

BYTE CPGFImage::m_quant
protected

quantization parameter

Definition at line 534 of file PGFimage.h.

◆ m_roi

PGFRect CPGFImage::m_roi
protected

region of interest

Definition at line 541 of file PGFimage.h.

◆ m_streamReinitialized

bool CPGFImage::m_streamReinitialized
protected

stream has been reinitialized

Definition at line 540 of file PGFimage.h.

◆ m_useOMPinDecoder

bool CPGFImage::m_useOMPinDecoder
protected

use Open MP in decoder

Definition at line 538 of file PGFimage.h.

◆ m_useOMPinEncoder

bool CPGFImage::m_useOMPinEncoder
protected

use Open MP in encoder

Definition at line 537 of file PGFimage.h.

◆ m_userDataPolicy

UINT32 CPGFImage::m_userDataPolicy
protected

user data (metadata) policy during open

Definition at line 533 of file PGFimage.h.

◆ m_userDataPos

UINT64 CPGFImage::m_userDataPos
protected

stream position of user data

Definition at line 531 of file PGFimage.h.

◆ m_width

UINT32 CPGFImage::m_width[MaxChannels]
protected

width of each channel at current level

Definition at line 526 of file PGFimage.h.

◆ m_wtChannel

CWaveletTransform* CPGFImage::m_wtChannel[MaxChannels]
protected

wavelet transformed color channels

Definition at line 521 of file PGFimage.h.


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