libpgf: CPGFImage Class Reference

| libpgf 7.21.2 PGF - Progressive Graphics File

Loading...
Searching...
No Matches
CPGFImage Class Reference

PGF main class. More...

`#include <PGFimage.h>`

## Public Member Functions
| CPGFImage ()
| Standard constructor.
virtual | ~CPGFImage ()
| Destructor.
void | Destroy ()
void | Open (CPGFStream *stream)
bool | IsOpen () const
| Returns true if the PGF has been opened for reading.
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)
DataT * | GetChannel (int c=0)
void | GetColorTable (UINT32 iFirstColor, UINT32 nColors, RGBQUAD *prgbColors) const
const RGBQUAD * | GetColorTable () const
const PGFHeader * | GetHeader () 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.
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.
static BYTE | MaxChannelDepth (BYTE version=PGFVersion)

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

## 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
void * | m_cbArg
| refresh callback argument
double | m_percent
| progress [0..1]
ProgressMode | m_progressMode
| progress mode used in Read and Write; PM_Relative is default mode

## Detailed Description

PGF main class.

PGF image class is the main class. You always need a PGF object for encoding or decoding image data. Decoding: 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}
CPGFImage::Init
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}
CPGFImage::m_currentLevel
int m_currentLevel
transform level of current image
Definition PGFimage.h:532
CPGFImage::Destroy
void Destroy()
Definition PGFimage.cpp:124

## 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; }
CPGFImage::m_header
PGFHeader m_header
PGF file header.
Definition PGFimage.h:529

## ◆ 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.

406{ return MaxChannelDepth(m_preHeader.version); }
CPGFImage::MaxChannelDepth
static BYTE MaxChannelDepth(BYTE version=PGFVersion)
Definition PGFimage.h:518
CPGFImage::m_preHeader
PGFPreHeader m_preHeader
PGF pre-header.
Definition PGFimage.h:528

## ◆ 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

  c | A 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]; }
MaxChannels
#define MaxChannels
maximum number of (color) channels
Definition PGFtypes.h:64
CPGFImage::m_height
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; }

## ◆ 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

  c | A 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]; }
CPGFImage::m_width
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

  version | pgf 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}
Version7
#define Version7
Codec major and minor version number stored in PGFHeader.
Definition PGFtypes.h:73
Version5
#define Version5
new coding scheme since major version 5
Definition PGFtypes.h:71
Version2
#define Version2
data structure PGFHeader of major version 2
Definition PGFtypes.h:68
Version6
#define Version6
hSize in PGFPreHeader uses 32 bits instead of 16 bits
Definition PGFtypes.h:72

## ◆ CompleteHeader()

bool CPGFImage::CompleteHeader | ( |  | ) |
| private

Definition at line 218 of file PGFimage.cpp.

218 {
219 // set current codec version
220 m_header.version = PGFVersionNumber(PGFMajorNumber, PGFYear, PGFWeek);
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;
241 case ImageModeIndexedColor:
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
275 m_header.mode = ImageModeRGBA;
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:
296 case ImageModeIndexedColor:
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;
323 if (!m_header.usedBitsPerChannel || m_header.usedBitsPerChannel > bpc) {
324 m_header.usedBitsPerChannel = bpc;
325 }
326
327 return true;
328}
ImageModeRGBColor
#define ImageModeRGBColor
Definition PGFplatform.h:101
ImageModeRGB12
#define ImageModeRGB12
Definition PGFplatform.h:117
ImageModeGray32
#define ImageModeGray32
Definition PGFplatform.h:116
ImageModeUnknown
#define ImageModeUnknown
Definition PGFplatform.h:119
ImageModeBitmap
#define ImageModeBitmap
Definition PGFplatform.h:98
ImageModeLabColor
#define ImageModeLabColor
Definition PGFplatform.h:107
ImageModeRGB16
#define ImageModeRGB16
Definition PGFplatform.h:118
ImageModeRGBA
#define ImageModeRGBA
Definition PGFplatform.h:115
ImageModeRGB48
#define ImageModeRGB48
Definition PGFplatform.h:109
ImageModeCMYK64
#define ImageModeCMYK64
Definition PGFplatform.h:111
ImageModeGrayScale
#define ImageModeGrayScale
Definition PGFplatform.h:99
ImageModeLab48
#define ImageModeLab48
Definition PGFplatform.h:110
ImageModeGray16
#define ImageModeGray16
Definition PGFplatform.h:108
ImageModeIndexedColor
#define ImageModeIndexedColor
Definition PGFplatform.h:100
ImageModeCMYKColor
#define ImageModeCMYKColor
Definition PGFplatform.h:102
PGFWeek
#define PGFWeek
Definition PGFtypes.h:46
PGFYear
#define PGFYear
Definition PGFtypes.h:45
PGFMajorNumber
#define PGFMajorNumber
Definition PGFtypes.h:44

## ◆ 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

Definition at line 583 of file PGFimage.cpp.

583 {
584 if (m_currentLevel == 0) {
585 return m_roi;
586 } else {
587 const UINT32 rLeft = LevelSizeL(m_roi.left, m_currentLevel);
588 const UINT32 rRight = LevelSizeL(m_roi.right, m_currentLevel);
589 const UINT32 rTop = LevelSizeL(m_roi.top, m_currentLevel);
590 const UINT32 rBottom = LevelSizeL(m_roi.bottom, m_currentLevel);
591 return PGFRect(rLeft, rTop, rRight - rLeft, rBottom - rTop);
592 }
593}
CPGFImage::m_roi
PGFRect m_roi
region of interest
Definition PGFimage.h:541
CPGFImage::LevelSizeL
static UINT32 LevelSizeL(UINT32 size, int level)
Definition PGFimage.h:499

## ◆ 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}
__min
#define __min(x, y)
Definition PGFplatform.h:91
MaxLevel
#define MaxLevel
maximum number of transform levels
Definition PGFtypes.h:62
FilterSize
const UINT32 FilterSize
Definition WaveletTransform.h:39
CPGFImage::m_percent
double m_percent
progress [0..1]
Definition PGFimage.h:547

## ◆ ConfigureDecoder()

void CPGFImage::ConfigureDecoder | ( | bool | useOMP = true,
|  | UserdataPolicy | policy = UP_CacheAll,
|  | UINT32 | prefixSize = 0 )
| inline

Configures the decoder.

Parameters

  useOMP | Use parallel threading with Open MP during decoding. Default value: true. Influences the decoding only if the codec has been compiled with OpenMP support.
  policy | The 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.
  prefixSize | Is 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; }
UP_CachePrefix
@ UP_CachePrefix
Definition PGFtypes.h:101
MaxUserDataSize
#define MaxUserDataSize
Definition PGFtypes.h:284
CPGFImage::m_useOMPinDecoder
bool m_useOMPinDecoder
use Open MP in decoder
Definition PGFimage.h:538
CPGFImage::m_userDataPolicy
UINT32 m_userDataPolicy
user data (metadata) policy during open
Definition PGFimage.h:533

## ◆ ConfigureEncoder()

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

Configures the encoder.

Parameters

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

Definition at line 250 of file PGFimage.h.

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

## ◆ 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}
CPGFImage::m_decoder
CDecoder * m_decoder
PGF decoder.
Definition PGFimage.h:523
CPGFImage::m_levelLength
UINT32 * m_levelLength
length of each level in bytes; first level starts immediately after this array
Definition PGFimage.h:525
CPGFImage::m_encoder
CEncoder * m_encoder
PGF encoder.
Definition PGFimage.h:524
CPGFImage::m_postHeader
PGFPostHeader m_postHeader
PGF post-header.
Definition PGFimage.h:530
CPGFImage::m_wtChannel
CWaveletTransform * m_wtChannel[MaxChannels]
wavelet transformed color channels
Definition PGFimage.h:521

## ◆ 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}
DataT
INT32 DataT
Definition PGFtypes.h:269
CPGFImage::m_channel
DataT * m_channel[MaxChannels]
untransformed channels in YUV format
Definition PGFimage.h:522

## ◆ GetAlignedROI()

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

Returns aligned ROI in pixels of current level of channel c

Parameters

  c | A channel index

Definition at line 598 of file PGFimage.cpp.

598 {
599 PGFRect roi(0, 0, m_width[c], m_height[c]);
600
601 if (ROIisSupported()) {
602 ASSERT(m_wtChannel[c]);
603
604 roi = m_wtChannel[c]->GetAlignedROI(m_currentLevel);
605 }
606 ASSERT(roi.Width() == m_width[c]);
607 ASSERT(roi.Height() == m_height[c]);
608 return roi;
609}
CPGFImage::ROIisSupported
bool ROIisSupported() const
Definition PGFimage.h:466

## ◆ 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

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

Definition at line 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}
YUVoffset8
#define YUVoffset8
Definition PGFimage.cpp:38
YUVoffset4
#define YUVoffset4
Definition PGFimage.cpp:36
YUVoffset6
#define YUVoffset6
Definition PGFimage.cpp:37
ImageModeHSLColor
#define ImageModeHSLColor
Definition PGFplatform.h:103
ImageModeHSBColor
#define ImageModeHSBColor
Definition PGFplatform.h:104
__max
#define __max(x, y)
Definition PGFplatform.h:92
CPGFImage::Clamp31
UINT32 Clamp31(DataT v) const
Definition PGFimage.h:576
CPGFImage::Clamp6
UINT16 Clamp6(DataT v) const
Definition PGFimage.h:566
CPGFImage::GetAlignedROI
PGFRect GetAlignedROI(int c=0) const
Definition PGFimage.cpp:598
CPGFImage::Clamp16
UINT16 Clamp16(DataT v) const
Definition PGFimage.h:573
CPGFImage::UsedBitsPerChannel
BYTE UsedBitsPerChannel() const
Definition PGFimage.cpp:756
CPGFImage::ComputeLevelROI
PGFRect ComputeLevelROI() const
Definition PGFimage.cpp:583
CPGFImage::Clamp8
UINT8 Clamp8(DataT v) const
Definition PGFimage.h:569
CPGFImage::m_downsample
bool m_downsample
chrominance channels are downsampled
Definition PGFimage.h:535
CPGFImage::Clamp4
UINT8 Clamp4(DataT v) const
Definition PGFimage.h:563
PGFRect::Height
UINT32 Height() const
Definition PGFtypes.h:259
PGFRect::Width
UINT32 Width() const
Definition PGFtypes.h:256
PGFRect::top
UINT32 top
Definition PGFtypes.h:226
PGFRect::bottom
UINT32 bottom
Definition PGFtypes.h:226
PGFRect::right
UINT32 right
Definition PGFtypes.h:226
PGFRect::left
UINT32 left
Definition PGFtypes.h:226

## ◆ GetChannel()

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

Return an internal YUV image channel.

Parameters

  c | A channel index

Returns
  An internal YUV image channel

Definition at line 317 of file PGFimage.h.

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

## ◆ GetColorTable() [1/2]

const RGBQUAD * CPGFImage::GetColorTable | ( |  | ) | const
| inline

Returns
  Address of color table

Definition at line 330 of file PGFimage.h.

330{ return m_postHeader.clut; }

## ◆ GetColorTable() [2/2]

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

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

Parameters

  iFirstColor | The color table index of the first entry to retrieve.
  nColors | The number of color table entries to retrieve.
  prgbColors | A pointer to the array of RGBQUAD structures to retrieve the color table entries.

Definition at line 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}
ColorTableLen
#define ColorTableLen
size of color lookup table (clut)
Definition PGFtypes.h:66

## ◆ 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);
650 return m_decoder->GetEncodedHeaderLength();
651}

## ◆ 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

  level | The 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]; }

## ◆ 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; }

## ◆ 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; }

## ◆ 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}

## ◆ 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; }
CPGFImage::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

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

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

Parameters

  pitch | The number of bytes of a row of the image buffer.
  buff | An image buffer.
  bpp | The number of bits per pixel used in image buffer.
  channelMap | A integer array containing the mapping of PGF channel ordering to expected channel ordering.
  cb | A pointer to a callback procedure. The procedure is called after each copied buffer row. If cb returns true, then it stops proceeding.

Definition at line 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}
YUVoffset16
#define YUVoffset16
Definition PGFimage.cpp:39
DataTSize
#define DataTSize
Definition PGFtypes.h:283

## ◆ 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

  level | A 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); }

## ◆ 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

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

Definition at line 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}
CPGFImage::Downsample
void Downsample(int nChannel)
Definition PGFimage.cpp:810
CPGFImage::RgbToYuv
void RgbToYuv(int pitch, UINT8 *rgbBuff, BYTE bpp, int channelMap[], CallbackPtr cb, void *data)
Definition PGFimage.cpp:1389

## ◆ ImportIsSupported()

bool CPGFImage::ImportIsSupported | ( | BYTE | mode | ) |
| static

Check for valid import image mode.

Parameters

  mode | Image mode

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

Definition at line 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}

## ◆ 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

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

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

Parameters

  pitch | The number of bytes of a row of the image buffer.
  buff | An image buffer.
  bpp | The number of bits per pixel used in image buffer.
  channelMap | A integer array containing the mapping of input channel ordering to expected channel ordering.
  cb | A pointer to a callback procedure. The procedure is called after each imported buffer row. If cb returns true, then it stops proceeding.

Definition at line 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}

## ◆ 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;
88 m_progressMode = PM_Relative;
89 m_percent = 0;
90 m_userDataPolicy = UP_CacheAll;
91
92 // init preHeader
93 memcpy(m_preHeader.magic, PGFMagic, 3);
94 m_preHeader.version = PGFVersion;
95 m_preHeader.hSize = 0;
96
97 // init postHeader
98 m_postHeader.userData = nullptr;
99 m_postHeader.userDataLen = 0;
100 m_postHeader.cachedUserDataLen = 0;
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}
PM_Relative
@ PM_Relative
Definition PGFtypes.h:100
UP_CacheAll
@ UP_CacheAll
Definition PGFtypes.h:101
PGFMagic
#define PGFMagic
PGF identification.
Definition PGFtypes.h:61
PGFVersion
#define PGFVersion
current standard version
Definition PGFtypes.h:76
CPGFImage::m_cbArg
void * m_cbArg
refresh callback argument
Definition PGFimage.h:546
CPGFImage::m_quant
BYTE m_quant
quantization parameter
Definition PGFimage.h:534
CPGFImage::m_progressMode
ProgressMode m_progressMode
progress mode used in Read and Write; PM_Relative is default mode
Definition PGFimage.h:548
CPGFImage::m_cb
RefreshCB m_cb
pointer to refresh callback procedure
Definition PGFimage.h:545
CPGFImage::m_streamReinitialized
bool m_streamReinitialized
stream has been reinitialized
Definition PGFimage.h:540

## ◆ 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; }

## ◆ 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; }

## ◆ 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; }

## ◆ 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; }

## ◆ LevelSizeH()

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

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

Parameters

  size | Original image size (e.g. width or height at level 0)
  level | An 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()

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

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

Parameters

  size | Original image size (e.g. width or height at level 0)
  level | An 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()

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

Return maximum channel depth.

Parameters

  version | pgf 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; }
PGF32
#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; }

## ◆ 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

  stream | A PGF stream

Definition at line 141 of file PGFimage.cpp.

141 {
142 ASSERT(stream);
143
144 // create decoder and read PGFPreHeader PGFHeader PGFPostHeader LevelLengths
145 m_decoder = new CDecoder(stream, m_preHeader, m_header, m_postHeader, m_levelLength,
146 m_userDataPos, m_useOMPinDecoder, m_userDataPolicy);
147
148 if (m_header.nLevels > MaxLevel) ReturnWithError(FormatCannotRead);
149
150 // set current level
151 m_currentLevel = m_header.nLevels;
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
161 if (m_header.quality > DownsampleThreshold &&
162 (m_header.mode == ImageModeRGBColor ||
163 m_header.mode == ImageModeRGBA ||
164 m_header.mode == ImageModeRGB48 ||
165 m_header.mode == ImageModeCMYKColor ||
166 m_header.mode == ImageModeCMYK64 ||
167 m_header.mode == ImageModeLabColor ||
168 m_header.mode == ImageModeLab48)) {
169 m_downsample = true;
170 m_quant = m_header.quality - 1;
171 } else {
172 m_downsample = false;
173 m_quant = m_header.quality;
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++) {
192 m_wtChannel[i] = new CWaveletTransform(m_width[i], m_height[i], m_header.nLevels);
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}
DownsampleThreshold
#define DownsampleThreshold
if quality is larger than this threshold than downsampling is used
Definition PGFtypes.h:65
CPGFImage::CompleteHeader
bool CompleteHeader()
Definition PGFimage.cpp:218
CPGFStream::Read
virtual void Read(int *count, void *buffer)=0

## ◆ 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; }

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

Definition at line 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
436 wtChannel->GetSubband(m_currentLevel, LL)->PlaceTile(*m_decoder, m_quant);
437 }
438 if (m_preHeader.version & Version5) {
439 // since version 5
440 wtChannel->GetSubband(m_currentLevel, HL)->PlaceTile(*m_decoder, m_quant);
441 wtChannel->GetSubband(m_currentLevel, LH)->PlaceTile(*m_decoder, m_quant);
442 } else {
443 // until version 4
444 m_decoder->DecodeInterleaved(wtChannel, m_currentLevel, m_quant);
445 }
446 wtChannel->GetSubband(m_currentLevel, HH)->PlaceTile(*m_decoder, m_quant);
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}
PM_Absolute
@ PM_Absolute
Definition PGFtypes.h:100
LL
@ LL
Definition PGFtypes.h:99
HL
@ HL
Definition PGFtypes.h:99
LH
@ LH
Definition PGFtypes.h:99
HH
@ HH
Definition PGFtypes.h:99
CPGFImage::Read
void Read(int level=0, CallbackPtr cb=nullptr, void *data=nullptr)
Definition PGFimage.cpp:402
CSubband::PlaceTile
void PlaceTile(CDecoder &decoder, int quantParam, bool tile=false, UINT32 tileX=0, UINT32 tileY=0)
Definition Subband.cpp:203
CWaveletTransform::GetSubband
CSubband * GetSubband(int level, Orientation orientation)
Definition WaveletTransform.h:93

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

Read and decode rectangular region of interest (ROI) 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 | The image level of the resulting image in the internal image buffer.
  cb | A pointer to a callback procedure. The procedure is called after reading a single level. If cb returns true, then it stops proceeding.
  data | Data Pointer to C++ class container to host callback procedure.

Definition at line 489 of file PGFimage.cpp.

489 {
490 ASSERT((level >= 0 && level < m_header.nLevels) || m_header.nLevels == 0); // m_header.nLevels == 0: image didn't use wavelet transform
491 ASSERT(m_decoder);
492
493 if (m_header.nLevels == 0 || !ROIisSupported()) {
494 rect.left = rect.top = 0;
495 rect.right = m_header.width; rect.bottom = m_header.height;
496 Read(level, cb, data);
497 } else {
498 ASSERT(ROIisSupported());
499 // new encoding scheme supporting ROI
500 ASSERT(rect.left < m_header.width && rect.top < m_header.height);
501
502 // check rectangle
503 if (rect.right == 0 || rect.right > m_header.width) rect.right = m_header.width;
504 if (rect.bottom == 0 || rect.bottom > m_header.height) rect.bottom = m_header.height;
505
506 const int levelDiff = m_currentLevel - level;
507 double percent = (m_progressMode == PM_Relative) ? pow(0.25, levelDiff) : m_percent;
508
509 // check level difference
510 if (levelDiff <= 0) {
511 // it is a new read call, probably with a new ROI
512 m_currentLevel = m_header.nLevels;
513 m_decoder->SetStreamPosToData();
514 }
515
516 // enable ROI decoding and reading
517 SetROI(rect);
518
519 while (m_currentLevel > level) {
520 for (int i=0; i < m_header.channels; i++) {
521 CWaveletTransform* wtChannel = m_wtChannel[i];
522 ASSERT(wtChannel);
523
524 // get number of tiles and tile indices
525 const UINT32 nTiles = wtChannel->GetNofTiles(m_currentLevel); // independent of ROI
526
527 // decode file and write stream to m_wtChannel
528 if (m_currentLevel == m_header.nLevels) { // last level also has LL band
529 ASSERT(nTiles == 1);
530 m_decoder->GetNextMacroBlock();
531 wtChannel->GetSubband(m_currentLevel, LL)->PlaceTile(*m_decoder, m_quant);
532 }
533 for (UINT32 tileY=0; tileY < nTiles; tileY++) {
534 for (UINT32 tileX=0; tileX < nTiles; tileX++) {
535 // check relevance of tile
536 if (wtChannel->TileIsRelevant(m_currentLevel, tileX, tileY)) {
537 m_decoder->GetNextMacroBlock();
538 wtChannel->GetSubband(m_currentLevel, HL)->PlaceTile(*m_decoder, m_quant, true, tileX, tileY);
539 wtChannel->GetSubband(m_currentLevel, LH)->PlaceTile(*m_decoder, m_quant, true, tileX, tileY);
540 wtChannel->GetSubband(m_currentLevel, HH)->PlaceTile(*m_decoder, m_quant, true, tileX, tileY);
541 } else {
542 // skip tile
543 m_decoder->SkipTileBuffer();
544 }
545 }
546 }
547 }
548
549 volatile OSError error = NoError; // volatile prevents optimizations
550#ifdef LIBPGF_USE_OPENMP
551 #pragma omp parallel for default(shared)
552#endif
553 for (int i=0; i < m_header.channels; i++) {
554 // inverse transform from m_wtChannel to m_channel
555 if (error == NoError) {
556 OSError err = m_wtChannel[i]->InverseTransform(m_currentLevel, &m_width[i], &m_height[i], &m_channel[i]);
557 if (err != NoError) error = err;
558 }
559 ASSERT(m_channel[i]);
560 }
561 if (error != NoError) ReturnWithError(error);
562
563 // set new level: must be done before refresh callback
564 m_currentLevel--;
565
566 // now we have to refresh the display
567 if (m_cb) m_cb(m_cbArg);
568
569 // now update progress
570 if (cb) {
571 percent *= 4;
572 if (m_progressMode == PM_Absolute) m_percent = percent;
573 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
574 }
575 }
576 }
577}
CPGFImage::SetROI
void SetROI(PGFRect rect)
Definition PGFimage.cpp:615

## ◆ 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

  level | The image level
  target | The target buffer
  targetLen | The length of the target buffer in bytes

Returns
  The number of bytes copied to the target buffer

Definition at line 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
714 m_decoder->SetStreamPosToData();
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}
CPGFImage::GetEncodedLevelLength
UINT32 GetEncodedLevelLength(int level) const
Definition PGFimage.h:367

## ◆ 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

  target | The target buffer
  targetLen | The length of the target buffer in bytes

Returns
  The number of bytes copied to the target buffer

Definition at line 660 of file PGFimage.cpp.

660 {
661 ASSERT(target);
662 ASSERT(targetLen > 0);
663 ASSERT(m_decoder);
664
665 // reset stream position
666 m_decoder->SetStreamPosToStart();
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}
CPGFImage::GetEncodedHeaderLength
UINT32 GetEncodedHeaderLength() const
Definition PGFimage.cpp:648

## ◆ 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); }
CPGFImage::Levels
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

  level | The 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
363 SetROI(PGFRect(0, 0, m_header.width, m_header.height));
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}

## ◆ 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

  startOfData | true: 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);
686 m_decoder->SetStreamPosToData();
687 } else {
688 if (m_decoder) {
689 m_decoder->SetStreamPosToStart();
690 } else if (m_encoder) {
691 m_encoder->SetStreamPosToStart();
692 } else {
693 ASSERT(false);
694 }
695 }
696}

## ◆ 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}

## ◆ 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; }
PGFROI
#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

  channel | A YUV data channel
  c | A channel index

Definition at line 272 of file PGFimage.h.

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

## ◆ SetColorTable()

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

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

Parameters

  iFirstColor | The color table index of the first entry to set.
  nColors | The number of color table entries to set.
  prgbColors | A pointer to the array of RGBQUAD structures to set the color table entries.

Definition at line 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}

## ◆ 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

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

Definition at line 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;
907 m_preHeader.hSize = HeaderSize;
908
909 // copy header
910 memcpy(&m_header, &header, HeaderSize);
911
912 // check quality
913 if (m_header.quality > MaxQuality) m_header.quality = MaxQuality;
914
915 // complete header
916 CompleteHeader();
917
918 // check and set number of levels
919 ComputeLevels();
920
921 // check for downsample
922 if (m_header.quality > DownsampleThreshold && (m_header.mode == ImageModeRGBColor ||
923 m_header.mode == ImageModeRGBA ||
924 m_header.mode == ImageModeRGB48 ||
925 m_header.mode == ImageModeCMYKColor ||
926 m_header.mode == ImageModeCMYK64 ||
927 m_header.mode == ImageModeLabColor ||
928 m_header.mode == ImageModeLab48)) {
929 m_downsample = true;
930 m_quant = m_header.quality - 1;
931 } else {
932 m_downsample = false;
933 m_quant = m_header.quality;
934 }
935
936 // update header size and copy user data
937 if (m_header.mode == ImageModeIndexedColor) {
938 // update header size
939 m_preHeader.hSize += ColorTableSize;
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);
945 m_postHeader.userDataLen = m_postHeader.cachedUserDataLen = userDataLength;
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}
HeaderSize
#define HeaderSize
Definition PGFtypes.h:281
ColorTableSize
#define ColorTableSize
Definition PGFtypes.h:282
MaxQuality
#define MaxQuality
maximum quality
Definition PGFtypes.h:94
CPGFImage::ComputeLevels
void ComputeLevels()
Definition PGFimage.cpp:854
PGFHeader::quality
UINT8 quality
quantization parameter: 0=lossless, 4=standard, 6=poor quality
Definition PGFtypes.h:156

## ◆ 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

  maxValue | The 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;
749 m_header.usedBitsPerChannel = pot;
750}

## ◆ 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; }

## ◆ 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

  callback | A refresh callback procedure
  arg | A parameter of the refresh callback procedure

Definition at line 303 of file PGFimage.h.

303{ m_cb = callback; m_cbArg = arg; }

## ◆ SetROI()

void CPGFImage::SetROI | ( | PGFRect | rect | ) |
| private

Compute ROIs for each channel and each level <= current level Called inside of Read(rect, ...).

Parameters

  rect | rectangular region of interest (ROI) at level 0

Definition at line 615 of file PGFimage.cpp.

615 {
616 ASSERT(m_decoder);
617 ASSERT(ROIisSupported());
618 ASSERT(m_wtChannel[0]);
619
620 // store ROI for a later call of GetBitmap
621 m_roi = rect;
622
623 // enable ROI decoding
624 m_decoder->SetROI();
625
626 // prepare wavelet channels for using ROI
627 m_wtChannel[0]->SetROI(rect);
628
629 if (m_downsample && m_header.channels > 1) {
630 // all further channels are downsampled, therefore downsample ROI
631 rect.left >>= 1;
632 rect.top >>= 1;
633 rect.right = (rect.right + 1) >> 1;
634 rect.bottom = (rect.bottom + 1) >> 1;
635 }
636 for (int i=1; i < m_header.channels; i++) {
637 ASSERT(m_wtChannel[i]);
638 m_wtChannel[i]->SetROI(rect);
639 }
640}

## ◆ 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;
1132 m_encoder->UpdatePostHeaderSize(m_preHeader);
1133 }
1134
1135 // write dummy levelLength into stream
1136 return m_encoder->WriteLevelLength(m_levelLength);
1137}

## ◆ 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) {
760 return m_header.usedBitsPerChannel;
761 } else {
762 return bpc;
763 }
764}

## ◆ 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; }
CPGFImage::CodecMajorVersion
static BYTE CodecMajorVersion(BYTE version=PGFVersion)
Return major version.
Definition PGFimage.cpp:768

## ◆ 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

  level | A 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); }

## ◆ 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

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

Definition at line 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}
CPGFImage::WriteImage
UINT32 WriteImage(CPGFStream *stream, CallbackPtr cb=nullptr, void *data=nullptr)
Definition PGFimage.cpp:1150
CPGFImage::WriteHeader
UINT32 WriteHeader(CPGFStream *stream)
Definition PGFimage.cpp:979

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

Returns
  The number of bytes written into stream.

Definition at line 1250 of file PGFimage.cpp.

1250 {
1251 ASSERT(m_header.nLevels > 0);
1252 ASSERT(0 <= level && level < m_header.nLevels);
1253 ASSERT(m_encoder);
1254 ASSERT(ROIisSupported());
1255
1256 const int levelDiff = m_currentLevel - level;
1257 double percent = (m_progressMode == PM_Relative) ? pow(0.25, levelDiff) : m_percent;
1258 UINT32 nWrittenBytes = 0;
1259
1260 if (m_currentLevel == m_header.nLevels) {
1261 // update post-header size, rewrite pre-header, and write dummy levelLength
1262 nWrittenBytes = UpdatePostHeaderSize();
1263 } else {
1264 // prepare for next level: save current file position, because the stream might have been reinitialized
1265 if (m_encoder->ComputeBufferLength()) {
1266 m_streamReinitialized = true;
1267 }
1268 }
1269
1270 // encoding scheme with ROI
1271 while (m_currentLevel > level) {
1272 WriteLevel(); // decrements m_currentLevel
1273
1274 if (m_levelLength) {
1275 nWrittenBytes += m_levelLength[m_header.nLevels - m_currentLevel - 1];
1276 }
1277
1278 // now update progress
1279 if (cb) {
1280 percent *= 4;
1281 if (m_progressMode == PM_Absolute) m_percent = percent;
1282 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1283 }
1284 }
1285
1286 // automatically closing
1287 if (m_currentLevel == 0) {
1288 if (!m_streamReinitialized) {
1289 // don't write level lengths, if the stream position changed inbetween two Write operations
1290 m_encoder->UpdateLevelLength();
1291 }
1292 // delete encoder
1293 delete m_encoder; m_encoder = nullptr;
1294 }
1295
1296 return nWrittenBytes;
1297}
CPGFImage::WriteLevel
void WriteLevel()
Definition PGFimage.cpp:1068
CPGFImage::UpdatePostHeaderSize
UINT32 UpdatePostHeaderSize()
Definition PGFimage.cpp:1124

## ◆ 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

  stream | A 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

  stream | A 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 }
1010 m_wtChannel[i] = new CWaveletTransform(m_width[i], m_height[i], m_header.nLevels, m_channel[i]);
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
1036 m_currentLevel = m_header.nLevels;
1037
1038 // create encoder, write headers and user data, but not level-length area
1039 m_encoder = new CEncoder(stream, m_preHeader, m_header, m_postHeader, m_userDataPos, m_useOMPinEncoder);
1040 if (m_favorSpeedOverSize) m_encoder->FavorSpeedOverSize();
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
1053 m_encoder = new CEncoder(stream, m_preHeader, m_header, m_postHeader, m_userDataPos, m_useOMPinEncoder);
1054 }
1055
1056 INT64 nBytes = m_encoder->ComputeHeaderLength();
1057 return (nBytes > 0) ? (UINT32)nBytes : 0;
1058}

## ◆ 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

  stream | A PGF stream
  cb | A pointer to a callback procedure. The procedure is called after writing a single level. If cb returns true, then it stops proceeding.
  data | Data Pointer to C++ class container to host callback procedure.

Returns
  The number of bytes written into stream.

Definition at line 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}
CPGFStream::Write
virtual void Write(int *count, void *buffer)=0

## ◆ 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);
1085 m_wtChannel[i]->GetSubband(m_currentLevel, LL)->ExtractTile(*m_encoder);
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.
1096 m_encoder->SetEncodedLevel(--m_currentLevel);
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
1109 m_wtChannel[i]->GetSubband(m_currentLevel, LL)->ExtractTile(*m_encoder);
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
1114 m_wtChannel[i]->GetSubband(m_currentLevel, HH)->ExtractTile(*m_encoder);
1115 }
1116
1117 // all necessary data are buffered. next call of EncodeBuffer will write the last piece of data of the current level.
1118 m_encoder->SetEncodedLevel(--m_currentLevel);
1119 }
1120}

## 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:

- PGFimage.h
- PGFimage.cpp