libpgf 6.14.12
PGF - Progressive Graphics File
Loading...
Searching...
No Matches
CPGFImage Class Reference

PGF main class. More...

#include <PGFimage.h>

Public Member Functions

 CPGFImage ()
 Standard constructor: It is used to create a PGF instance for opening and reading.
 
virtual ~CPGFImage ()
 Destructor: Destroy internal data structures.
 
virtual void Close ()
 
virtual void Destroy ()
 
void Open (CPGFStream *stream) THROW_
 
bool IsOpen () const
 Returns true if the PGF has been opened and not closed.
 
void Read (int level=0, CallbackPtr cb=NULL, void *data=NULL) THROW_
 
void Read (PGFRect &rect, int level=0, CallbackPtr cb=NULL, void *data=NULL) THROW_
 
void ReadPreview () THROW_
 
void Reconstruct (int level=0) THROW_
 
void GetBitmap (int pitch, UINT8 *buff, BYTE bpp, int channelMap[]=NULL, CallbackPtr cb=NULL, void *data=NULL) const THROW_
 
void GetYUV (int pitch, DataT *buff, BYTE bpp, int channelMap[]=NULL, CallbackPtr cb=NULL, void *data=NULL) const THROW_
 
void ImportBitmap (int pitch, UINT8 *buff, BYTE bpp, int channelMap[]=NULL, CallbackPtr cb=NULL, void *data=NULL) THROW_
 
void ImportYUV (int pitch, DataT *buff, BYTE bpp, int channelMap[]=NULL, CallbackPtr cb=NULL, void *data=NULL) THROW_
 
void Write (CPGFStream *stream, UINT32 *nWrittenBytes=NULL, CallbackPtr cb=NULL, void *data=NULL) THROW_
 
UINT32 WriteHeader (CPGFStream *stream) THROW_
 
UINT32 WriteImage (CPGFStream *stream, CallbackPtr cb=NULL, void *data=NULL) THROW_
 
UINT32 Write (int level, CallbackPtr cb=NULL, void *data=NULL) THROW_
 
void ConfigureEncoder (bool useOMP=true, bool favorSpeedOverSize=false)
 
void ConfigureDecoder (bool useOMP=true, bool skipUserData=false)
 
void ResetStreamPos () THROW_
 Reset stream position to start of PGF pre-header.
 
void SetChannel (DataT *channel, int c=0)
 
void SetHeader (const PGFHeader &header, BYTE flags=0, UINT8 *userData=0, UINT32 userDataLength=0) THROW_
 
void SetMaxValue (UINT32 maxValue)
 
void SetProgressMode (ProgressMode pm)
 
void SetRefreshCallback (RefreshCB callback, void *arg)
 
void SetColorTable (UINT32 iFirstColor, UINT32 nColors, const RGBQUAD *prgbColors) THROW_
 
DataTGetChannel (int c=0)
 
void GetColorTable (UINT32 iFirstColor, UINT32 nColors, RGBQUAD *prgbColors) const THROW_
 
const RGBQUAD * GetColorTable () const
 
const PGFHeaderGetHeader () const
 
UINT32 GetMaxValue () const
 
UINT64 GetUserDataPos () const
 
const UINT8 * GetUserData (UINT32 &size) const
 
UINT32 GetEncodedHeaderLength () const
 
UINT32 GetEncodedLevelLength (int level) const
 
UINT32 ReadEncodedHeader (UINT8 *target, UINT32 targetLen) const THROW_
 
UINT32 ReadEncodedData (int level, UINT8 *target, UINT32 targetLen) const THROW_
 
UINT32 ChannelWidth (int c=0) const
 
UINT32 ChannelHeight (int c=0) const
 
BYTE ChannelDepth () const
 
UINT32 Width (int level=0) const
 
UINT32 Height (int level=0) const
 
BYTE Level () const
 
BYTE Levels () const
 
BYTE Quality () const
 
BYTE Channels () const
 
BYTE Mode () const
 
BYTE BPP () const
 
bool ROIisSupported () const
 
BYTE UsedBitsPerChannel () const
 
BYTE Version () const
 

Static Public Member Functions

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

Protected Attributes

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

Private Member Functions

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

Private Attributes

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

Detailed Description

PGF main class.

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

Author
C. Stamm, R. Spuler

Definition at line 57 of file PGFimage.h.

Constructor & Destructor Documentation

◆ CPGFImage()

CPGFImage::CPGFImage ( )

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

Definition at line 55 of file PGFimage.cpp.

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

◆ ~CPGFImage()

CPGFImage::~CPGFImage ( )
virtual

Destructor: Destroy internal data structures.

Definition at line 98 of file PGFimage.cpp.

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

Member Function Documentation

◆ BPP()

BYTE CPGFImage::BPP ( ) const
inline

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

Returns
Number of bits per pixel.

Definition at line 460 of file PGFimage.h.

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

◆ ChannelDepth()

BYTE CPGFImage::ChannelDepth ( ) const
inline

Return bits per channel of the image's encoder.

Returns
Bits per channel

Definition at line 409 of file PGFimage.h.

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

◆ ChannelHeight()

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

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

Parameters
cA channel index
Returns
Channel height in pixels

Definition at line 404 of file PGFimage.h.

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

◆ Channels()

BYTE CPGFImage::Channels ( ) const
inline

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

Returns
Number of image channels

Definition at line 447 of file PGFimage.h.

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

◆ ChannelWidth()

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

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

Parameters
cA channel index
Returns
Channel width in pixels

Definition at line 397 of file PGFimage.h.

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

◆ Clamp16()

UINT16 CPGFImage::Clamp16 ( DataT v) const
inlineprivate

Definition at line 561 of file PGFimage.h.

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

◆ Clamp31()

UINT32 CPGFImage::Clamp31 ( DataT v) const
inlineprivate

Definition at line 564 of file PGFimage.h.

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

◆ Clamp4()

UINT8 CPGFImage::Clamp4 ( DataT v) const
inlineprivate

Definition at line 551 of file PGFimage.h.

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

◆ Clamp6()

UINT16 CPGFImage::Clamp6 ( DataT v) const
inlineprivate

Definition at line 554 of file PGFimage.h.

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

◆ Clamp8()

UINT8 CPGFImage::Clamp8 ( DataT v) const
inlineprivate

Definition at line 557 of file PGFimage.h.

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

◆ Close()

void CPGFImage::Close ( )
virtual

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

Definition at line 122 of file PGFimage.cpp.

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

◆ CompleteHeader()

void CPGFImage::CompleteHeader ( )
private

Definition at line 208 of file PGFimage.cpp.

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

◆ ComputeLevels()

void CPGFImage::ComputeLevels ( )
private

Definition at line 803 of file PGFimage.cpp.

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

◆ ConfigureDecoder()

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

Configures the decoder.

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

Definition at line 266 of file PGFimage.h.

266{ m_useOMPinDecoder = useOMP; m_skipUserData = skipUserData; }

◆ ConfigureEncoder()

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

Configures the encoder.

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

Definition at line 260 of file PGFimage.h.

260{ m_useOMPinEncoder = useOMP; m_favorSpeedOverSize = favorSpeedOverSize; }

◆ CurrentChannelDepth()

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

Compute and return codec version.

Returns
current PGF codec version

Definition at line 508 of file PGFimage.h.

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

◆ CurrentVersion()

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

Return version.

Compute and return codec version.

Returns
current PGF codec version

Definition at line 719 of file PGFimage.cpp.

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

◆ Destroy()

void CPGFImage::Destroy ( )
virtual

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

Definition at line 105 of file PGFimage.cpp.

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

◆ Downsample()

void CPGFImage::Downsample ( int nChannel)
private

Definition at line 759 of file PGFimage.cpp.

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

◆ GetBitmap()

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

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

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

Definition at line 1719 of file PGFimage.cpp.

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

◆ GetChannel()

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

Return an internal YUV image channel.

Parameters
cA channel index
Returns
An internal YUV image channel

Definition at line 321 of file PGFimage.h.

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

◆ GetColorTable() [1/2]

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

Definition at line 334 of file PGFimage.h.

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

◆ GetColorTable() [2/2]

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

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

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

Definition at line 1291 of file PGFimage.cpp.

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

◆ GetEncodedHeaderLength()

UINT32 CPGFImage::GetEncodedHeaderLength ( ) const

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

Returns
The length of all encoded headers in bytes

Definition at line 612 of file PGFimage.cpp.

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

◆ GetEncodedLevelLength()

UINT32 CPGFImage::GetEncodedLevelLength ( int level) const
inline

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

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

Definition at line 370 of file PGFimage.h.

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

◆ GetHeader()

const PGFHeader * CPGFImage::GetHeader ( ) const
inline

Return the PGF header structure.

Returns
A PGF header structure

Definition at line 339 of file PGFimage.h.

339{ return &m_header; }

◆ GetMaxValue()

UINT32 CPGFImage::GetMaxValue ( ) const
inline

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

Returns
The maximum intensity value.

Definition at line 345 of file PGFimage.h.

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

◆ GetUserData()

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

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

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

Definition at line 321 of file PGFimage.cpp.

321 {
323 return m_postHeader.userData;
324}

◆ GetUserDataPos()

UINT64 CPGFImage::GetUserDataPos ( ) const
inline

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

Definition at line 350 of file PGFimage.h.

350{ return m_userDataPos; }

◆ GetYUV()

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

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

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

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

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

Definition at line 2477 of file PGFimage.cpp.

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

◆ Height()

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

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

Parameters
levelA level
Returns
Image level height in pixels

Definition at line 423 of file PGFimage.h.

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

◆ ImportBitmap()

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

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

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

Definition at line 742 of file PGFimage.cpp.

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

◆ ImportIsSupported()

bool CPGFImage::ImportIsSupported ( BYTE mode)
static

Check for valid import image mode.

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

Definition at line 1246 of file PGFimage.cpp.

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

◆ ImportYUV()

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

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

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

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

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

Definition at line 2588 of file PGFimage.cpp.

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

◆ IsOpen()

bool CPGFImage::IsOpen ( ) const
inline

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

Definition at line 87 of file PGFimage.h.

87{ return m_decoder != NULL; }

◆ Level()

BYTE CPGFImage::Level ( ) const
inline

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

Returns
Current image level

Definition at line 430 of file PGFimage.h.

430{ return (BYTE)m_currentLevel; }

◆ LevelHeight()

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

Compute and return image height at given level.

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

Definition at line 498 of file PGFimage.h.

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

◆ Levels()

BYTE CPGFImage::Levels ( ) const
inline

Return the number of image levels.

Returns
Number of image levels

Definition at line 435 of file PGFimage.h.

435{ return m_header.nLevels; }

◆ LevelWidth()

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

Compute and return image width at given level.

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

Definition at line 491 of file PGFimage.h.

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

◆ Mode()

BYTE CPGFImage::Mode ( ) const
inline

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

Returns
Image mode

Definition at line 454 of file PGFimage.h.

454{ return m_header.mode; }

◆ Open()

void CPGFImage::Open ( CPGFStream * stream)

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

Parameters
streamA PGF stream

Definition at line 131 of file PGFimage.cpp.

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

◆ Quality()

BYTE CPGFImage::Quality ( ) const
inline

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

Returns
PGF quality

Definition at line 441 of file PGFimage.h.

441{ return m_header.quality; }

◆ Read() [1/2]

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

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

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

Definition at line 383 of file PGFimage.cpp.

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

◆ Read() [2/2]

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

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

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

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

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

Definition at line 471 of file PGFimage.cpp.

471 {
472 ASSERT((level >= 0 && level < m_header.nLevels) || m_header.nLevels == 0); // m_header.nLevels == 0: image didn't use wavelet transform
473 ASSERT(m_decoder);
474
475 if (m_header.nLevels == 0 || !ROIisSupported()) {
476 rect.left = rect.top = 0;
477 rect.right = m_header.width; rect.bottom = m_header.height;
478 Read(level, cb, data);
479 } else {
480 ASSERT(ROIisSupported());
481 // new encoding scheme supporting ROI
482 ASSERT(rect.left < m_header.width && rect.top < m_header.height);
483
484 const int levelDiff = m_currentLevel - level;
485 double percent = (m_progressMode == PM_Relative) ? pow(0.25, levelDiff) : m_percent;
486
487 // check level difference
488 if (levelDiff <= 0) {
489 // it is a new read call, probably with a new ROI
492 }
493
494 // check rectangle
495 if (rect.right == 0 || rect.right > m_header.width) rect.right = m_header.width;
496 if (rect.bottom == 0 || rect.bottom > m_header.height) rect.bottom = m_header.height;
497
498 // enable ROI decoding and reading
499 SetROI(rect);
500
501 while (m_currentLevel > level) {
502 for (int i=0; i < m_header.channels; i++) {
503 ASSERT(m_wtChannel[i]);
504
505 // get number of tiles and tile indices
506 const UINT32 nTiles = m_wtChannel[i]->GetNofTiles(m_currentLevel);
507 const PGFRect& tileIndices = m_wtChannel[i]->GetTileIndices(m_currentLevel);
508
509 // decode file and write stream to m_wtChannel
510 if (m_currentLevel == m_header.nLevels) { // last level also has LL band
511 ASSERT(nTiles == 1);
512 m_decoder->DecodeTileBuffer();
514 }
515 for (UINT32 tileY=0; tileY < nTiles; tileY++) {
516 for (UINT32 tileX=0; tileX < nTiles; tileX++) {
517 // check relevance of tile
518 if (tileIndices.IsInside(tileX, tileY)) {
519 m_decoder->DecodeTileBuffer();
520 m_wtChannel[i]->GetSubband(m_currentLevel, HL)->PlaceTile(*m_decoder, m_quant, true, tileX, tileY);
521 m_wtChannel[i]->GetSubband(m_currentLevel, LH)->PlaceTile(*m_decoder, m_quant, true, tileX, tileY);
522 m_wtChannel[i]->GetSubband(m_currentLevel, HH)->PlaceTile(*m_decoder, m_quant, true, tileX, tileY);
523 } else {
524 // skip tile
525 m_decoder->SkipTileBuffer();
526 }
527 }
528 }
529 }
530
531 volatile OSError error = NoError; // volatile prevents optimizations
532#ifdef LIBPGF_USE_OPENMP
533 #pragma omp parallel for default(shared)
534#endif
535 for (int i=0; i < m_header.channels; i++) {
536 // inverse transform from m_wtChannel to m_channel
537 if (error == NoError) {
538 OSError err = m_wtChannel[i]->InverseTransform(m_currentLevel, &m_width[i], &m_height[i], &m_channel[i]);
539 if (err != NoError) error = err;
540 }
541 ASSERT(m_channel[i]);
542 }
543 if (error != NoError) ReturnWithError(error);
544
545 // set new level: must be done before refresh callback
547
548 // now we have to refresh the display
549 if (m_cb) m_cb(m_cbArg);
550
551 // now update progress
552 if (cb) {
553 percent *= 4;
554 if (m_progressMode == PM_Absolute) m_percent = percent;
555 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
556 }
557 }
558 }
559
560 // automatically closing
561 if (m_currentLevel == 0) Close();
562}
void SetStreamPosToData() THROW_
Reset stream position to beginning of data block.
Definition Decoder.h:145
void SetROI(PGFRect rect)
Definition PGFimage.cpp:567
bool IsInside(UINT32 x, UINT32 y) const
Definition PGFtypes.h:213

◆ ReadEncodedData()

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

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

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

Definition at line 658 of file PGFimage.cpp.

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

◆ ReadEncodedHeader()

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

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

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

Definition at line 624 of file PGFimage.cpp.

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

◆ ReadPreview()

void CPGFImage::ReadPreview ( )
inline

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

Definition at line 121 of file PGFimage.h.

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

◆ Reconstruct()

void CPGFImage::Reconstruct ( int level = 0)

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

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

Definition at line 331 of file PGFimage.cpp.

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

◆ ResetStreamPos()

void CPGFImage::ResetStreamPos ( )

Reset stream position to start of PGF pre-header.

Definition at line 644 of file PGFimage.cpp.

644 {
645 ASSERT(m_decoder);
647}

◆ RgbToYuv()

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

Definition at line 1330 of file PGFimage.cpp.

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

◆ ROIisSupported()

bool CPGFImage::ROIisSupported ( ) const
inline

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

Returns
true if the pgf image supports ROI.

Definition at line 465 of file PGFimage.h.

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

◆ SetChannel()

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

Set internal PGF image buffer channel.

Parameters
channelA YUV data channel
cA channel index

Definition at line 276 of file PGFimage.h.

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

◆ SetColorTable()

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

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

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

Definition at line 1305 of file PGFimage.cpp.

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

◆ SetHeader()

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

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

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

Definition at line 843 of file PGFimage.cpp.

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

◆ SetMaxValue()

void CPGFImage::SetMaxValue ( UINT32 maxValue)

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

Parameters
maxValueThe maximum intensity value.

Definition at line 689 of file PGFimage.cpp.

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

◆ SetProgressMode()

void CPGFImage::SetProgressMode ( ProgressMode pm)
inline

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

Definition at line 300 of file PGFimage.h.

300{ m_progressMode = pm; }

◆ SetRefreshCallback()

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

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

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

Definition at line 307 of file PGFimage.h.

307{ m_cb = callback; m_cbArg = arg; }

◆ SetROI()

void CPGFImage::SetROI ( PGFRect rect)
private

Compute ROIs for each channel and each level

Parameters
rectrectangular region of interest (ROI)

Definition at line 567 of file PGFimage.cpp.

567 {
568 ASSERT(m_decoder);
569 ASSERT(ROIisSupported());
570
571 // store ROI for a later call of GetBitmap
572 m_roi = rect;
573
574 // enable ROI decoding
575 m_decoder->SetROI();
576
577 // enlarge ROI because of border artefacts
578 const UINT32 dx = FilterWidth/2*(1 << m_currentLevel);
579 const UINT32 dy = FilterHeight/2*(1 << m_currentLevel);
580
581 if (rect.left < dx) rect.left = 0;
582 else rect.left -= dx;
583 if (rect.top < dy) rect.top = 0;
584 else rect.top -= dy;
585 rect.right += dx;
586 if (rect.right > m_header.width) rect.right = m_header.width;
587 rect.bottom += dy;
588 if (rect.bottom > m_header.height) rect.bottom = m_header.height;
589
590 // prepare wavelet channels for using ROI
591 ASSERT(m_wtChannel[0]);
592 m_wtChannel[0]->SetROI(rect);
593 if (m_downsample && m_header.channels > 1) {
594 // all further channels are downsampled, therefore downsample ROI
595 rect.left >>= 1;
596 rect.top >>= 1;
597 rect.right >>= 1;
598 rect.bottom >>= 1;
599 }
600 for (int i=1; i < m_header.channels; i++) {
601 ASSERT(m_wtChannel[i]);
602 m_wtChannel[i]->SetROI(rect);
603 }
604}
#define FilterHeight
number of coefficients of the column wavelet filter

◆ UpdatePostHeaderSize()

UINT32 CPGFImage::UpdatePostHeaderSize ( )
private

Definition at line 1066 of file PGFimage.cpp.

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

◆ UsedBitsPerChannel()

BYTE CPGFImage::UsedBitsPerChannel ( ) const

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

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

Definition at line 707 of file PGFimage.cpp.

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

◆ Version()

BYTE CPGFImage::Version ( ) const
inline

Returns images' PGF version

Returns
PGF codec version of the image

Definition at line 476 of file PGFimage.h.

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

◆ Width()

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

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

Parameters
levelA level
Returns
Image level width in pixels

Definition at line 416 of file PGFimage.h.

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

◆ Write() [1/2]

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

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

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

Definition at line 1162 of file PGFimage.cpp.

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

◆ Write() [2/2]

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

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

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

Definition at line 1191 of file PGFimage.cpp.

1191 {
1192 ASSERT(m_header.nLevels > 0);
1193 ASSERT(0 <= level && level < m_header.nLevels);
1194 ASSERT(m_encoder);
1195 ASSERT(ROIisSupported());
1196
1197 const int levelDiff = m_currentLevel - level;
1198 double percent = (m_progressMode == PM_Relative) ? pow(0.25, levelDiff) : m_percent;
1199 UINT32 nWrittenBytes = 0;
1200
1202 // update post-header size, rewrite pre-header, and write dummy levelLength
1203 nWrittenBytes = UpdatePostHeaderSize();
1204 } else {
1205 // prepare for next level: save current file position, because the stream might have been reinitialized
1207 m_streamReinitialized = true;
1208 }
1209 }
1210
1211 // encoding scheme with ROI
1212 while (m_currentLevel > level) {
1213 WriteLevel(); // decrements m_currentLevel
1214
1215 if (m_levelLength) {
1216 nWrittenBytes += m_levelLength[m_header.nLevels - m_currentLevel - 1];
1217 }
1218
1219 // now update progress
1220 if (cb) {
1221 percent *= 4;
1222 if (m_progressMode == PM_Absolute) m_percent = percent;
1223 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
1224 }
1225 }
1226
1227 // automatically closing
1228 if (m_currentLevel == 0) {
1229 if (!m_streamReinitialized) {
1230 // don't write level lengths, if the stream position changed inbetween two Write operations
1232 }
1233 // delete encoder
1234 delete m_encoder; m_encoder = NULL;
1235 }
1236
1237 return nWrittenBytes;
1238}
INT64 ComputeBufferLength() const
Definition Encoder.h:179
UINT32 UpdateLevelLength() THROW_
Definition Encoder.cpp:202
UINT32 UpdatePostHeaderSize() THROW_
void WriteLevel() THROW_

◆ WriteHeader()

UINT32 CPGFImage::WriteHeader ( CPGFStream * stream)

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

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

Definition at line 922 of file PGFimage.cpp.

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

◆ WriteImage()

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

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

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

Definition at line 1091 of file PGFimage.cpp.

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

◆ WriteLevel()

void CPGFImage::WriteLevel ( )
private

Definition at line 1011 of file PGFimage.cpp.

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

Member Data Documentation

◆ m_cb

RefreshCB CPGFImage::m_cb
private

pointer to refresh callback procedure

Definition at line 535 of file PGFimage.h.

◆ m_cbArg

void* CPGFImage::m_cbArg
private

refresh callback argument

Definition at line 536 of file PGFimage.h.

◆ m_channel

DataT* CPGFImage::m_channel[MaxChannels]
protected

untransformed channels in YUV format

Definition at line 512 of file PGFimage.h.

◆ m_currentLevel

int CPGFImage::m_currentLevel
protected

transform level of current image

Definition at line 522 of file PGFimage.h.

◆ m_decoder

CDecoder* CPGFImage::m_decoder
protected

PGF decoder.

Definition at line 513 of file PGFimage.h.

◆ m_downsample

bool CPGFImage::m_downsample
protected

chrominance channels are downsampled

Definition at line 524 of file PGFimage.h.

◆ m_encoder

CEncoder* CPGFImage::m_encoder
protected

PGF encoder.

Definition at line 514 of file PGFimage.h.

◆ m_favorSpeedOverSize

bool CPGFImage::m_favorSpeedOverSize
protected

favor encoding speed over compression ratio

Definition at line 525 of file PGFimage.h.

◆ m_header

PGFHeader CPGFImage::m_header
protected

PGF file header.

Definition at line 519 of file PGFimage.h.

◆ m_height

UINT32 CPGFImage::m_height[MaxChannels]
protected

height of each channel at current level

Definition at line 517 of file PGFimage.h.

◆ m_levelLength

UINT32* CPGFImage::m_levelLength
protected

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

Definition at line 515 of file PGFimage.h.

◆ m_percent

double CPGFImage::m_percent
private

progress [0..1]

Definition at line 537 of file PGFimage.h.

◆ m_postHeader

PGFPostHeader CPGFImage::m_postHeader
protected

PGF post-header.

Definition at line 520 of file PGFimage.h.

◆ m_preHeader

PGFPreHeader CPGFImage::m_preHeader
protected

PGF pre-header.

Definition at line 518 of file PGFimage.h.

◆ m_progressMode

ProgressMode CPGFImage::m_progressMode
private

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

Definition at line 538 of file PGFimage.h.

◆ m_quant

BYTE CPGFImage::m_quant
protected

quantization parameter

Definition at line 523 of file PGFimage.h.

◆ m_roi

PGFRect CPGFImage::m_roi
protected

region of interest

Definition at line 531 of file PGFimage.h.

◆ m_skipUserData

bool CPGFImage::m_skipUserData
protected

skip user data (metadata) during open

Definition at line 528 of file PGFimage.h.

◆ m_streamReinitialized

bool CPGFImage::m_streamReinitialized
protected

stream has been reinitialized

Definition at line 530 of file PGFimage.h.

◆ m_useOMPinDecoder

bool CPGFImage::m_useOMPinDecoder
protected

use Open MP in decoder

Definition at line 527 of file PGFimage.h.

◆ m_useOMPinEncoder

bool CPGFImage::m_useOMPinEncoder
protected

use Open MP in encoder

Definition at line 526 of file PGFimage.h.

◆ m_userDataPos

UINT64 CPGFImage::m_userDataPos
protected

stream position of user data

Definition at line 521 of file PGFimage.h.

◆ m_width

UINT32 CPGFImage::m_width[MaxChannels]
protected

width of each channel at current level

Definition at line 516 of file PGFimage.h.

◆ m_wtChannel

CWaveletTransform* CPGFImage::m_wtChannel[MaxChannels]
protected

wavelet transformed color channels

Definition at line 511 of file PGFimage.h.


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