r16771 by fschmid - Update pgf library to latest version used by DigiKam

scribus-commit scribus-commit at lists.scribus.net
Mon Aug 8 18:19:06 UTC 2011


Author: fschmid
Date: Mon Aug  8 18:19:05 2011
New Revision: 16771

URL: http://scribus.net/websvn/listing.php?repname=Scribus&sc=1&rev=16771
Log:
Update pgf library to latest version used by DigiKam

Modified:
    trunk/Scribus/scribus/third_party/pgf/BitStream.h
    trunk/Scribus/scribus/third_party/pgf/CMakeLists.txt
    trunk/Scribus/scribus/third_party/pgf/Decoder.cpp
    trunk/Scribus/scribus/third_party/pgf/Decoder.h
    trunk/Scribus/scribus/third_party/pgf/Encoder.cpp
    trunk/Scribus/scribus/third_party/pgf/Encoder.h
    trunk/Scribus/scribus/third_party/pgf/PGFimage.cpp
    trunk/Scribus/scribus/third_party/pgf/PGFimage.h
    trunk/Scribus/scribus/third_party/pgf/PGFplatform.h
    trunk/Scribus/scribus/third_party/pgf/PGFtypes.h
    trunk/Scribus/scribus/third_party/pgf/Subband.cpp
    trunk/Scribus/scribus/third_party/pgf/Subband.h
    trunk/Scribus/scribus/third_party/pgf/WaveletTransform.cpp
    trunk/Scribus/scribus/third_party/pgf/WaveletTransform.h

Modified: trunk/Scribus/scribus/third_party/pgf/BitStream.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16771&path=/trunk/Scribus/scribus/third_party/pgf/BitStream.h
==============================================================================
--- trunk/Scribus/scribus/third_party/pgf/BitStream.h (original)
+++ trunk/Scribus/scribus/third_party/pgf/BitStream.h Mon Aug  8 18:19:05 2011
@@ -1,26 +1,31 @@
 /*
  * The Progressive Graphics File; http://www.libpgf.org
- * 
+ *
  * $Date: 2006-06-04 22:05:59 +0200 (So, 04 Jun 2006) $
  * $Revision: 229 $
- * 
+ *
  * This file Copyright (C) 2006 xeraina GmbH, Switzerland
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
  * as published by the Free Software Foundation; either version 2.1
  * of the License, or (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+//////////////////////////////////////////////////////////////////////
+/// @file Bitstream.h
+/// @brief PGF bit-stream operations
+/// @author C. Stamm
+
 #ifndef PGF_BITSTREAM_H
 #define PGF_BITSTREAM_H
 
@@ -31,13 +36,14 @@
 //static const WordWidthLog = 5;
 static const UINT32 Filled = 0xFFFFFFFF;
 
-#define MAKEU64(a, b) ((UINT64) (((UINT32) (a)) | ((UINT64) ((UINT32) (b))) << 32)) 
- 
+/// @brief Make 64 bit unsigned integer from two 32 bit unsigned integers
+#define MAKEU64(a, b) ((UINT64) (((UINT32) (a)) | ((UINT64) ((UINT32) (b))) << 32))
+
 // these procedures have to be inlined because of performance reasons
 
 //////////////////////////////////////////////////////////////////////
 /// Set one bit of a bit stream to 1
-/// @param stream A bit stream composed of unsigned integer arrays
+/// @param stream A bit stream stored in array of unsigned integers
 /// @param pos A valid zero-based position in the bit stream
 inline void SetBit(UINT32* stream, UINT32 pos) {
 	stream[pos >> WordWidthLog] |= (1 << (pos%WordWidth));
@@ -45,15 +51,15 @@
 
 //////////////////////////////////////////////////////////////////////
 /// Set one bit of a bit stream to 0
-/// @param stream A bit stream composed of unsigned integer arrays
+/// @param stream A bit stream stored in array of unsigned integers
 /// @param pos A valid zero-based position in the bit stream
 inline void ClearBit(UINT32* stream, UINT32 pos) {
-	stream[pos >> WordWidthLog] &= ~(1 << (pos%WordWidth)); 
+	stream[pos >> WordWidthLog] &= ~(1 << (pos%WordWidth));
 }
 
 //////////////////////////////////////////////////////////////////////
 /// Return one bit of a bit stream
-/// @param stream A bit stream composed of unsigned integer arrays
+/// @param stream A bit stream stored in array of unsigned integers
 /// @param pos A valid zero-based position in the bit stream
 /// @return bit at position pos of bit stream stream
 inline bool GetBit(UINT32* stream, UINT32 pos)  {
@@ -62,10 +68,11 @@
 }
 
 //////////////////////////////////////////////////////////////////////
-/// Compare k-bit binary representation of stream at postition pos with val
-/// @param stream A bit stream composed of unsigned integer arrays
+/// Compare k-bit binary representation of stream at position pos with val
+/// @param stream A bit stream stored in array of unsigned integers
 /// @param pos A valid zero-based position in the bit stream
 /// @param k Number of bits to compare
+/// @param val Value to compare with
 /// @return true if equal
 inline bool CompareBitBlock(UINT32* stream, UINT32 pos, UINT32 k, UINT32 val) {
 	const UINT32 iLoInt = pos >> WordWidthLog;
@@ -87,33 +94,35 @@
 }
 
 //////////////////////////////////////////////////////////////////////
-/// Store k-bit binary representation of val in stream at postition pos
-/// @param stream A bit stream composed of unsigned integer arrays
-/// @param pos A valid zero-based position in the bit stream
+/// Store k-bit binary representation of val in stream at position pos
+/// @param stream A bit stream stored in array of unsigned integers
+/// @param pos A valid zero-based position in the bit stream
+/// @param val Value to store in stream at position pos
 /// @param k Number of bits of integer representation of val
 inline void SetValueBlock(UINT32* stream, UINT32 pos, UINT32 val, UINT32 k) {
+	const UINT32 offset = pos%WordWidth;
 	const UINT32 iLoInt = pos >> WordWidthLog;
 	const UINT32 iHiInt = (pos + k - 1) >> WordWidthLog;
 	ASSERT(iLoInt <= iHiInt);
-	const UINT32 loMask = Filled << (pos%WordWidth);
+	const UINT32 loMask = Filled << offset;
 	const UINT32 hiMask = Filled >> (WordWidth - 1 - ((pos + k - 1)%WordWidth));
 
 	if (iLoInt == iHiInt) {
 		// fits into one integer
-		stream[iLoInt] &= ~(loMask & hiMask);
-		stream[iLoInt] |= val << (pos%WordWidth);
+		stream[iLoInt] &= ~(loMask & hiMask); // clear bits
+		stream[iLoInt] |= val << offset; // write value
 	} else {
 		// must be splitted over integer boundary
-		stream[iLoInt] &= ~loMask;
-		stream[iLoInt] |= val << (pos%WordWidth);
-		stream[iHiInt] &= ~hiMask;
-		stream[iHiInt] |= val >> (WordWidth - (pos%WordWidth));
+		stream[iLoInt] &= ~loMask; // clear bits
+		stream[iLoInt] |= val << offset; // write lower part of value
+		stream[iHiInt] &= ~hiMask; // clear bits
+		stream[iHiInt] |= val >> (WordWidth - offset); // write higher part of value
 	}
 }
 
 //////////////////////////////////////////////////////////////////////
 /// Read k-bit number from stream at position pos
-/// @param stream A bit stream composed of unsigned integer arrays
+/// @param stream A bit stream stored in array of unsigned integers
 /// @param pos A valid zero-based position in the bit stream
 /// @param k Number of bits to read: 1 <= k <= 32
 inline UINT32 GetValueBlock(UINT32* stream, UINT32 pos, UINT32 k) {
@@ -122,7 +131,7 @@
 	const UINT32 iHiInt = (pos + k - 1) >> WordWidthLog;		// integer of last bit
 	const UINT32 loMask = Filled << (pos%WordWidth);
 	const UINT32 hiMask = Filled >> (WordWidth - 1 - ((pos + k - 1)%WordWidth));
-	
+
 	if (iLoInt == iHiInt) {
 		// inside integer boundary
 		count = stream[iLoInt] & (loMask & hiMask);
@@ -140,7 +149,7 @@
 
 //////////////////////////////////////////////////////////////////////
 /// Clear block of size at least len at position pos in stream
-/// @param stream A bit stream composed of unsigned integer arrays
+/// @param stream A bit stream stored in array of unsigned integers
 /// @param pos A valid zero-based position in the bit stream
 /// @param len Number of bits set to 0
 inline void ClearBitBlock(UINT32* stream, UINT32 pos, UINT32 len) {
@@ -164,7 +173,7 @@
 
 //////////////////////////////////////////////////////////////////////
 /// Set block of size at least len at position pos in stream
-/// @param stream A bit stream composed of unsigned integer arrays
+/// @param stream A bit stream stored in array of unsigned integers
 /// @param pos A valid zero-based position in the bit stream
 /// @param len Number of bits set to 1
 inline void SetBitBlock(UINT32* stream, UINT32 pos, UINT32 len) {
@@ -190,25 +199,24 @@
 //////////////////////////////////////////////////////////////////////
 /// Returns the distance to the next 1 in stream at position pos.
 /// If no 1 is found within len bits, then len is returned.
-/// @param stream A bit stream composed of unsigned integer arrays
+/// @param stream A bit stream stored in array of unsigned integers
 /// @param pos A valid zero-based position in the bit stream
 /// @param len size of search area (in bits)
 /// return The distance to the next 1 in stream at position pos
 inline UINT32 SeekBitRange(UINT32* stream, UINT32 pos, UINT32 len) {
 	UINT32 count = 0;
-	UINT32 wordPos = pos >> WordWidthLog;
 	UINT32 testMask = 1 << (pos%WordWidth);
-	UINT32* word = stream + wordPos;
+	UINT32* word = stream + (pos >> WordWidthLog);
 
 	while (((*word & testMask) == 0) && (count < len)) {
-		count++; 
+		count++;
 		testMask <<= 1;
 		if (!testMask) {
 			word++; testMask = 1;
 
 			// fast steps if all bits in a word are zero
 			while ((count + WordWidth <= len) && (*word == 0)) {
-				word++; 
+				word++;
 				count += WordWidth;
 			}
 		}
@@ -220,28 +228,24 @@
 //////////////////////////////////////////////////////////////////////
 /// Returns the distance to the next 0 in stream at position pos.
 /// If no 0 is found within len bits, then len is returned.
-/// @param stream A bit stream composed of unsigned integer arrays
+/// @param stream A bit stream stored in array of unsigned integers
 /// @param pos A valid zero-based position in the bit stream
 /// @param len size of search area (in bits)
 /// return The distance to the next 0 in stream at position pos
 inline UINT32 SeekBit1Range(UINT32* stream, UINT32 pos, UINT32 len) {
 	UINT32 count = 0;
-	UINT32  wordPos = pos >> WordWidthLog;
-	UINT32  bitPos  = pos%WordWidth;
-	UINT32 testMask = 1 << bitPos;
-
-	while (((stream[wordPos] & testMask) != 0) && (count < len)) {
-		ASSERT(bitPos < WordWidth);
-		count++; 
-		bitPos++;
-		if (bitPos < WordWidth) {
-			testMask <<= 1;
-		} else {
-			wordPos++; bitPos = 0; testMask = 1;
-
-			// fast steps if all bits in a word are zero
-			while ((count + WordWidth <= len) && (stream[wordPos] == Filled)) {
-				wordPos++; 
+	UINT32 testMask = 1 << (pos%WordWidth);
+	UINT32* word = stream + (pos >> WordWidthLog);
+
+	while (((*word & testMask) != 0) && (count < len)) {
+		count++;
+		testMask <<= 1;
+		if (!testMask) {
+			word++; testMask = 1;
+
+			// fast steps if all bits in a word are one
+			while ((count + WordWidth <= len) && (*word == Filled)) {
+				word++;
 				count += WordWidth;
 			}
 		}
@@ -250,13 +254,12 @@
 }
 
 //////////////////////////////////////////////////////////////////////
-/// Compute position to beginning of the next 32-bit word
-/// @param pos Current bit stream position
-/// @return Position of next 32-bit word
+/// Compute bit position of the next 32-bit word
+/// @param pos current bit stream position
+/// @return bit position of next 32-bit word
 inline UINT32 AlignWordPos(UINT32 pos) {
-//	return (pos%WordWidth) ? pos + (WordWidth - pos%WordWidth) : pos;
-//	return pos + (WordWidth - pos%WordWidth)%WordWidth;
-	return ((pos + WordWidth - 1) >> WordWidthLog) << WordWidthLog;
+//	return ((pos + WordWidth - 1) >> WordWidthLog) << WordWidthLog;
+	return (pos + WordWidth - 1) & WordMask;
 }
 
 //////////////////////////////////////////////////////////////////////

Modified: trunk/Scribus/scribus/third_party/pgf/CMakeLists.txt
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16771&path=/trunk/Scribus/scribus/third_party/pgf/CMakeLists.txt
==============================================================================
--- trunk/Scribus/scribus/third_party/pgf/CMakeLists.txt (original)
+++ trunk/Scribus/scribus/third_party/pgf/CMakeLists.txt Mon Aug  8 18:19:05 2011
@@ -7,7 +7,7 @@
         Decoder.cpp
         Encoder.cpp
         PGFimage.cpp
-        Stream.cpp
+        PGFstream.cpp
         Subband.cpp
         WaveletTransform.cpp
        )

Modified: trunk/Scribus/scribus/third_party/pgf/Decoder.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16771&path=/trunk/Scribus/scribus/third_party/pgf/Decoder.cpp
==============================================================================
--- trunk/Scribus/scribus/third_party/pgf/Decoder.cpp (original)
+++ trunk/Scribus/scribus/third_party/pgf/Decoder.cpp Mon Aug  8 18:19:05 2011
@@ -1,27 +1,33 @@
 /*
  * The Progressive Graphics File; http://www.libpgf.org
- * 
+ *
  * $Date: 2006-06-04 22:05:59 +0200 (So, 04 Jun 2006) $
  * $Revision: 229 $
- * 
+ *
  * This file Copyright (C) 2006 xeraina GmbH, Switzerland
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
  * as published by the Free Software Foundation; either version 2.1
  * of the License, or (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+//////////////////////////////////////////////////////////////////////
+/// @file Decoder.cpp
+/// @brief PGF decoder class implementation
+/// @author C. Stamm, R. Spuler
+
 #include "Decoder.h"
+
 #ifdef TRACE
 	#include <stdio.h>
 #endif
@@ -47,50 +53,67 @@
 //                   m_value	[BufferSize]
 //                      |
 //                   subband
-//  
+//
 
 // Constants
 #define CodeBufferBitLen		(BufferSize*WordWidth)	// max number of bits in m_codeBuffer
-
-/////////////////////////////////////////////////////////////////////
-// Default Constructor
-CDecoder::CDecoder(CPGFStream* stream /*= NULL */) 
-: m_stream(stream), m_startPos(0), m_encodedHeaderLength(0), m_valuePos(0), m_bufferIsAvailable(false)
-#ifdef __PGFROISUPPORT__
-, m_roi(false)
-#endif
-{
-}
 
 /////////////////////////////////////////////////////////////////////
 // Constructor
 // Read pre-header, header, and levelLength
-// throws IOException
-CDecoder::CDecoder(CPGFStream* stream, PGFPreHeader& preHeader, PGFHeader& header, PGFPostHeader& postHeader, UINT32*& levelLength) THROW_
-: m_stream(stream), m_startPos(0), m_encodedHeaderLength(0), m_valuePos(0), m_bufferIsAvailable(false)
+// It might throw an IOException.
+CDecoder::CDecoder(CPGFStream* stream, PGFPreHeader& preHeader, PGFHeader& header, PGFPostHeader& postHeader, UINT32*& levelLength, bool useOMP /*= true*/) THROW_
+: m_stream(stream)
+, m_startPos(0)
+, m_streamSizeEstimation(0)
+, m_encodedHeaderLength(0)
+, m_currentBlockIndex(0)
+, m_macroBlocksAvailable(0)
 #ifdef __PGFROISUPPORT__
 , m_roi(false)
 #endif
 {
 	ASSERT(m_stream);
 
-	int count;
+	int count, expected;
+
+	// set number of threads
+#ifdef LIBPGF_USE_OPENMP
+	m_macroBlockLen = omp_get_num_procs();
+#else
+	m_macroBlockLen = 1;
+#endif
+
+	if (useOMP && m_macroBlockLen > 1) {
+#ifdef LIBPGF_USE_OPENMP
+		omp_set_num_threads(m_macroBlockLen);
+#endif
+
+		// create macro block array
+		m_macroBlocks = new CMacroBlock*[m_macroBlockLen];
+		for (int i=0; i < m_macroBlockLen; i++) m_macroBlocks[i] = new CMacroBlock(this);
+	} else {
+		m_macroBlocks = 0;
+		m_currentBlock = new CMacroBlock(this);
+	}
 
 	// store current stream position
 	m_startPos = m_stream->GetPos();
 
 	// read magic and version
-	count = MagicVersionSize;
+	count = expected = MagicVersionSize;
 	m_stream->Read(&count, &preHeader);
+	if (count != expected) ReturnWithError(MissingData);
 
 	// read header size
 	if (preHeader.version & Version6) {
 		// 32 bit header size since version 6
-		count = 4;
+		count = expected = 4;
 	} else {
-		count = 2;
+		count = expected = 2;
 	}
 	m_stream->Read(&count, ((UINT8*)&preHeader) + MagicVersionSize);
+	if (count != expected) ReturnWithError(MissingData);
 
 	// make sure the values are correct read
 	preHeader.hSize = __VAL(preHeader.hSize);
@@ -102,8 +125,10 @@
 	}
 
 	// read file header
-	count = (preHeader.hSize < HeaderSize) ? preHeader.hSize : HeaderSize;
+	count = expected = (preHeader.hSize < HeaderSize) ? preHeader.hSize : HeaderSize;
 	m_stream->Read(&count, &header);
+	if (count != expected) ReturnWithError(MissingData);
+
 	// make sure the values are correct read
 	header.height = __VAL(UINT32(header.height));
 	header.width = __VAL(UINT32(header.width));
@@ -122,9 +147,9 @@
 			if (header.mode == ImageModeIndexedColor) {
 				ASSERT(size >= ColorTableSize);
 				// read color table
-				count = ColorTableSize;
+				count = expected = ColorTableSize;
 				m_stream->Read(&count, postHeader.clut);
-				ASSERT(count == ColorTableSize);
+				if (count != expected) ReturnWithError(MissingData);
 				size -= count;
 			}
 
@@ -134,9 +159,9 @@
 				postHeader.userData = new UINT8[postHeader.userDataLen];
 
 				// read user data
-				count = postHeader.userDataLen;
+				count = expected = postHeader.userDataLen;
 				m_stream->Read(&count, postHeader.userData);
-				ASSERT(count == size);
+				if (count != expected) ReturnWithError(MissingData);
 			}
 		}
 
@@ -145,16 +170,22 @@
 		if (!levelLength) ReturnWithError(InsufficientMemory);
 
 		// read levelLength
-		count = header.nLevels*WordBytes;
+		count = expected = header.nLevels*WordBytes;
 		m_stream->Read(&count, levelLength);
-
-#ifdef PGF_USE_BIG_ENDIAN 
+		if (count != expected) ReturnWithError(MissingData);
+
+#ifdef PGF_USE_BIG_ENDIAN
 		// make sure the values are correct read
-		count /= WordBytes;
-		for (int i=0; i < count; i++) {
+		for (int i=0; i < header.nLevels; i++) {
 			levelLength[i] = __VAL(levelLength[i]);
 		}
 #endif
+
+		// compute the total size in bytes; keep attention: level length information is optional
+		for (int i=0; i < header.nLevels; i++) {
+			m_streamSizeEstimation += levelLength[i];
+		}
+
 	}
 
 	// store current stream position
@@ -164,6 +195,12 @@
 /////////////////////////////////////////////////////////////////////
 // Destructor
 CDecoder::~CDecoder() {
+	if (m_macroBlocks) {
+		for (int i=0; i < m_macroBlockLen; i++) delete m_macroBlocks[i];
+		delete[] m_macroBlocks;
+	} else {
+		delete m_currentBlock;
+	}
 }
 
 //////////////////////////////////////////////////////////////////////
@@ -199,17 +236,16 @@
 	const div_t hh = div(height, LinBlockSize);
 	const int ws = pitch - LinBlockSize;
 	const int wr = pitch - ww.rem;
-	int x, y, i, j;
 	int pos, base = startPos, base2;
 
 	// main height
-	for (i=0; i < hh.quot; i++) {
+	for (int i=0; i < hh.quot; i++) {
 		// main width
 		base2 = base;
-		for (j=0; j < ww.quot; j++) {
+		for (int j=0; j < ww.quot; j++) {
 			pos = base2;
-			for (y=0; y < LinBlockSize; y++) {
-				for (x=0; x < LinBlockSize; x++) {
+			for (int y=0; y < LinBlockSize; y++) {
+				for (int x=0; x < LinBlockSize; x++) {
 					DequantizeValue(band, pos, quantParam);
 					pos++;
 				}
@@ -219,8 +255,8 @@
 		}
 		// rest of width
 		pos = base2;
-		for (y=0; y < LinBlockSize; y++) {
-			for (x=0; x < ww.rem; x++) {
+		for (int y=0; y < LinBlockSize; y++) {
+			for (int x=0; x < ww.rem; x++) {
 				DequantizeValue(band, pos, quantParam);
 				pos++;
 			}
@@ -228,13 +264,13 @@
 			base += pitch;
 		}
 	}
-	// main width 
+	// main width
 	base2 = base;
-	for (j=0; j < ww.quot; j++) {
+	for (int j=0; j < ww.quot; j++) {
 		// rest of height
 		pos = base2;
-		for (y=0; y < hh.rem; y++) {
-			for (x=0; x < LinBlockSize; x++) {
+		for (int y=0; y < hh.rem; y++) {
+			for (int x=0; x < LinBlockSize; x++) {
 				DequantizeValue(band, pos, quantParam);
 				pos++;
 			}
@@ -244,9 +280,9 @@
 	}
 	// rest of height
 	pos = base2;
-	for (y=0; y < hh.rem; y++) {
+	for (int y=0; y < hh.rem; y++) {
 		// rest of width
-		for (x=0; x < ww.rem; x++) {
+		for (int x=0; x < ww.rem; x++) {
 			DequantizeValue(band, pos, quantParam);
 			pos++;
 		}
@@ -259,7 +295,7 @@
 // LH and HH are interleaved in the codestream and must be split
 // Deccoding and dequantization of HL and LH Band (interleaved) using partitioning scheme
 // partitions the plane in squares of side length InterBlockSize
-// throws IOException
+// It might throw an IOException.
 void CDecoder::DecodeInterleaved(CWaveletTransform* wtChannel, int level, int quantParam) THROW_ {
 	CSubband* hlBand = wtChannel->GetSubband(level, HL);
 	CSubband* lhBand = wtChannel->GetSubband(level, LH);
@@ -269,7 +305,6 @@
 	const int hlwr = hlBand->GetWidth() - hlW.rem;
 	const int lhws = lhBand->GetWidth() - InterBlockSize;
 	const int lhwr = lhBand->GetWidth() - hlW.rem;
-	int x, y, i, j;
 	int hlPos, lhPos;
 	int hlBase = 0, lhBase = 0, hlBase2, lhBase2;
 
@@ -284,15 +319,15 @@
 	if (quantParam < 0) quantParam = 0;
 
 	// main height
-	for (i=0; i < lhH.quot; i++) {
+	for (int i=0; i < lhH.quot; i++) {
 		// main width
 		hlBase2 = hlBase;
 		lhBase2 = lhBase;
-		for (j=0; j < hlW.quot; j++) {
+		for (int j=0; j < hlW.quot; j++) {
 			hlPos = hlBase2;
 			lhPos = lhBase2;
-			for (y=0; y < InterBlockSize; y++) {
-				for (x=0; x < InterBlockSize; x++) {
+			for (int y=0; y < InterBlockSize; y++) {
+				for (int x=0; x < InterBlockSize; x++) {
 					DequantizeValue(hlBand, hlPos, quantParam);
 					DequantizeValue(lhBand, lhPos, quantParam);
 					hlPos++;
@@ -307,8 +342,8 @@
 		// rest of width
 		hlPos = hlBase2;
 		lhPos = lhBase2;
-		for (y=0; y < InterBlockSize; y++) {
-			for (x=0; x < hlW.rem; x++) {
+		for (int y=0; y < InterBlockSize; y++) {
+			for (int x=0; x < hlW.rem; x++) {
 				DequantizeValue(hlBand, hlPos, quantParam);
 				DequantizeValue(lhBand, lhPos, quantParam);
 				hlPos++;
@@ -324,15 +359,15 @@
 			lhBase += lhBand->GetWidth();
 		}
 	}
-	// main width 
+	// main width
 	hlBase2 = hlBase;
 	lhBase2 = lhBase;
-	for (j=0; j < hlW.quot; j++) {
+	for (int j=0; j < hlW.quot; j++) {
 		// rest of height
 		hlPos = hlBase2;
 		lhPos = lhBase2;
-		for (y=0; y < lhH.rem; y++) {
-			for (x=0; x < InterBlockSize; x++) {
+		for (int y=0; y < lhH.rem; y++) {
+			for (int x=0; x < InterBlockSize; x++) {
 				DequantizeValue(hlBand, hlPos, quantParam);
 				DequantizeValue(lhBand, lhPos, quantParam);
 				hlPos++;
@@ -347,9 +382,9 @@
 	// rest of height
 	hlPos = hlBase2;
 	lhPos = lhBase2;
-	for (y=0; y < lhH.rem; y++) {
+	for (int y=0; y < lhH.rem; y++) {
 		// rest of width
-		for (x=0; x < hlW.rem; x++) {
+		for (int x=0; x < hlW.rem; x++) {
 			DequantizeValue(hlBand, hlPos, quantParam);
 			DequantizeValue(lhBand, lhPos, quantParam);
 			hlPos++;
@@ -367,7 +402,7 @@
 	if (hlBand->GetHeight() > lhBand->GetHeight()) {
 		// total width
 		hlPos = hlBase;
-		for (j=0; j < hlBand->GetWidth(); j++) {
+		for (int j=0; j < hlBand->GetWidth(); j++) {
 			DequantizeValue(hlBand, hlPos, quantParam);
 			hlPos++;
 		}
@@ -383,137 +418,208 @@
 
 //////////////////////////////////////////////////////////////////////
 /// Dequantization of a single value at given position in subband.
-/// If encoded data is available, then stores dequantized band value into 
+/// If encoded data is available, then stores dequantized band value into
 /// buffer m_value at position m_valuePos.
 /// Otherwise reads encoded data buffer and decodes it.
 /// @param band A subband
 /// @param bandPos A valid position in subband band
 /// @param quantParam The quantization parameter
 void CDecoder::DequantizeValue(CSubband* band, UINT32 bandPos, int quantParam) {
-	if (!m_bufferIsAvailable) {
+	if (!m_macroBlocksAvailable) {
 		DecodeBuffer();
-	}
-	band->SetData(bandPos, m_value[m_valuePos] << quantParam);
-	m_valuePos++;
-	if (m_valuePos == BufferSize) {
-		m_bufferIsAvailable = false;
-	}
-}
-
-///////////////////////////////////////////////////////
-// Read next block from stream and decode into buffer
-// Decoding scheme: <wordLen>(16 bits) [ ROI ] data
-//		ROI	  ::= <bufferSize>(15 bits) <eofTile>(1 bit)
-// throws IOException
-void CDecoder::DecodeBuffer() THROW_ {
+		ASSERT(m_currentBlock);
+		ASSERT(m_currentBlock->m_valuePos == 0);
+		ASSERT(m_macroBlocksAvailable);
+	}
+	band->SetData(bandPos, m_currentBlock->m_value[m_currentBlock->m_valuePos] << quantParam);
+	m_currentBlock->m_valuePos++;
+	if (m_currentBlock->m_valuePos == BufferSize) {
+		// current block has been read
+		m_macroBlocksAvailable--;
+		if (m_macroBlocksAvailable)
+			m_currentBlock = m_macroBlocks[++m_currentBlockIndex];
+	}
+}
+
+//////////////////////////////////////////////////////////////////////
+// Read next block from stream and store it in the given block
+// It might throw an IOException.
+void CDecoder::ReadMacroBlock(CMacroBlock* block) THROW_ {
+	ASSERT(block);
+
 	UINT16 wordLen;
 	ROIBlockHeader h(BufferSize);
-	int count;
+	int count, expected;
 
 #ifdef TRACE
-	UINT32 filePos = (UINT32)m_stream->GetPos();
-	printf("%d\n", filePos);
+	//UINT32 filePos = (UINT32)m_stream->GetPos();
+	//printf("DecodeBuffer: %d\n", filePos);
 #endif
 
 	// read wordLen
-	count = sizeof(UINT16);
-	m_stream->Read(&count, &wordLen); ASSERT(count == sizeof(UINT16));
+	count = expected = sizeof(UINT16);
+	m_stream->Read(&count, &wordLen);
+	if (count != expected) ReturnWithError(MissingData);
 	wordLen = __VAL(wordLen);
-	ASSERT(wordLen <= BufferSize);
+	if (wordLen > BufferSize)
+		ReturnWithError(FormatCannotRead);
 
 #ifdef __PGFROISUPPORT__
 	// read ROIBlockHeader
 	if (m_roi) {
-		m_stream->Read(&count, &h.val); ASSERT(count == sizeof(UINT16));
-		
+		m_stream->Read(&count, &h.val);
+		if (count != expected) ReturnWithError(MissingData);
+
 		// convert ROIBlockHeader
 		h.val = __VAL(h.val);
 	}
 #endif
+	// save header
+	block->m_header = h;
 
 	// read data
-	count = wordLen*WordBytes;
-	m_stream->Read(&count, m_codeBuffer);
-
-#ifdef PGF_USE_BIG_ENDIAN 
+	count = expected = wordLen*WordBytes;
+	m_stream->Read(&count, block->m_codeBuffer);
+	if (count != expected) ReturnWithError(MissingData);
+
+#ifdef PGF_USE_BIG_ENDIAN
 	// convert data
 	count /= WordBytes;
 	for (int i=0; i < count; i++) {
-		m_codeBuffer[i] = __VAL(m_codeBuffer[i]);
+		block->m_codeBuffer[i] = __VAL(block->m_codeBuffer[i]);
 	}
 #endif
 
 #ifdef __PGFROISUPPORT__
-	ASSERT(m_roi && h.bufferSize <= BufferSize || h.bufferSize == BufferSize);
+	ASSERT(m_roi && h.rbh.bufferSize <= BufferSize || h.rbh.bufferSize == BufferSize);
 #else
-	ASSERT(h.bufferSize == BufferSize);
-#endif
-	BitplaneDecode(h.bufferSize);
-
-	// data is available
-	m_bufferIsAvailable = true;
-	m_valuePos = 0;
-}
-
-///////////////////////////////////////////////////////
-// Read next block from stream but don't decode into buffer
+	ASSERT(h.rbh.bufferSize == BufferSize);
+#endif
+}
+
+//////////////////////////////////////////////////////////////////////
+// Read next block from stream but don't decode into macro block
 // Encoding scheme: <wordLen>(16 bits) [ ROI ] data
 //		ROI	  ::= <bufferSize>(15 bits) <eofTile>(1 bit)
-// throws IOException
-void CDecoder::SkipBuffer() THROW_ {
+// It might throw an IOException.
+void CDecoder::SkipTileBuffer() THROW_ {
+	// check if pre-decoded data is available
+	if (m_macroBlocksAvailable) {
+		// current block is not used
+		m_macroBlocksAvailable--;
+		if (m_macroBlocksAvailable)
+			m_currentBlock = m_macroBlocks[++m_currentBlockIndex];
+		return;
+	}
+
 	UINT16 wordLen;
-	int count;
+	int count, expected;
 
 	// read wordLen
-	count = sizeof(UINT16);
-	m_stream->Read(&count, &wordLen); ASSERT(count == sizeof(UINT16));
+	count = expected = sizeof(wordLen);
+	m_stream->Read(&count, &wordLen);
+	if (count != expected) ReturnWithError(MissingData);
 	wordLen = __VAL(wordLen);
 	ASSERT(wordLen <= BufferSize);
 
 #ifdef __PGFROISUPPORT__
 	if (m_roi) {
 		// skip ROIBlockHeader
-		m_stream->SetPos(FSFromCurrent, count);
+		m_stream->SetPos(FSFromCurrent, sizeof(ROIBlockHeader));
 	}
 #endif
 
 	// skip data
 	m_stream->SetPos(FSFromCurrent, wordLen*WordBytes);
+}
+
+//////////////////////////////////////////////////////////////////////
+// Read next block from stream and decode into macro block
+// It might throw an IOException.
+void CDecoder::DecodeTileBuffer() THROW_ {
+	if (m_macroBlocksAvailable) {
+		// current block has been read
+		m_macroBlocksAvailable--;
+		if (m_macroBlocksAvailable)
+			m_currentBlock = m_macroBlocks[++m_currentBlockIndex];
+	} else {
+		DecodeBuffer();
+		ASSERT(m_currentBlock);
+		ASSERT(m_currentBlock->m_valuePos == 0);
+		ASSERT(m_macroBlocksAvailable);
+	}
+}
+
+//////////////////////////////////////////////////////////////////////
+// Read next block from stream and decode into macro block
+// Decoding scheme: <wordLen>(16 bits) [ ROI ] data
+//		ROI	  ::= <bufferSize>(15 bits) <eofTile>(1 bit)
+// It might throw an IOException.
+void CDecoder::DecodeBuffer() THROW_ {
+	ASSERT(m_macroBlocksAvailable == 0);
+
+	// macro block management
+	if (m_macroBlockLen == 1) {
+		ASSERT(m_currentBlock);
+		ReadMacroBlock(m_currentBlock);
+		m_currentBlock->BitplaneDecode();
+		m_macroBlocksAvailable = 1;
+	} else {
+		for (int i=0; i < m_macroBlockLen; i++) {
+			// read sequentially several blocks
+			try {
+				ReadMacroBlock(m_macroBlocks[i]);
+				m_macroBlocksAvailable++;
+			} catch(const IOException &ex) {
+				if (ex.error == MissingData) {
+					break; // no further levels available
+				} else {
+					throw;
+				}
+			}
+		}
+
+		// decode in parallel
+		#pragma omp parallel for default(shared) //no declared exceptions in next block
+		for (int i=0; i < m_macroBlocksAvailable; i++) {
+			m_macroBlocks[i]->BitplaneDecode();
+		}
+
+		m_currentBlockIndex = 0;
+		m_currentBlock = m_macroBlocks[m_currentBlockIndex];
+	}
 }
 
 //////////////////////////////////////////////////////////////////////
 // Decode block into buffer of given size using bit plane coding.
 // A buffer contains bufferLen UINT32 values, thus, bufferSize bits per bit plane.
-// Following coding scheme is used: 
-//		Buffer		::= <nPlanes>(5 bits) foreach(plane i): Plane[i]  
+// Following coding scheme is used:
+//		Buffer		::= <nPlanes>(5 bits) foreach(plane i): Plane[i]
 //		Plane[i]	::= [ Sig1 | Sig2 ] [DWORD alignment] refBits
-//		Sig1		::= 1 <codeLen>(15 bits) codedSigAndSignBits 
-//		Sig2		::= 0 <sigLen>(15 bits) [Sign1 | Sign2 ] sigBits 
+//		Sig1		::= 1 <codeLen>(15 bits) codedSigAndSignBits
+//		Sig2		::= 0 <sigLen>(15 bits) [Sign1 | Sign2 ] sigBits
 //		Sign1		::= 1 <codeLen>(15 bits) [DWORD alignment] codedSignBits
 //		Sign2		::= 0 <signLen>(15 bits) [DWORD alignment] signBits
-void CDecoder::BitplaneDecode(UINT32 bufferSize) {
-	ASSERT(bufferSize <= BufferSize);
-	const UINT32 bufferLen = AlignWordPos(bufferSize)/WordWidth;
-
-	UINT32 nPlanes, k;
-	UINT32 codePos = 0, codeLen, sigLen, sigPos, signLen, wordPos;
-	int    plane;
-	UINT32 sigBits[BufferLen];
-	UINT32 signBits[BufferLen];
-	UINT32 planeMask;
+void CDecoder::CMacroBlock::BitplaneDecode() {
+	UINT32 bufferSize = m_header.rbh.bufferSize; ASSERT(bufferSize <= BufferSize);
+
+	UINT32 nPlanes;
+	UINT32 codePos = 0, codeLen, sigLen, sigPos, signLen, signPos;
+	DataT planeMask;
 
 	// clear significance vector
-	for (k=0; k < bufferLen; k++) {
-		m_sigFlagVector[k] = 0;
-	}
-
-	// clear buffer
-	for (k=0; k < bufferSize; k++) {
+	for (UINT32 k=0; k < bufferSize; k++) {
+		m_sigFlagVector[k] = false;
+	}
+	m_sigFlagVector[bufferSize] = true; // sentinel
+
+	// clear output buffer
+	for (UINT32 k=0; k < BufferSize; k++) {
 		m_value[k] = 0;
 	}
 
 	// read number of bit planes
-	nPlanes = GetValueBlock(m_codeBuffer, 0, MaxBitPlanesLog); 
+	nPlanes = GetValueBlock(m_codeBuffer, 0, MaxBitPlanesLog);
 	codePos += MaxBitPlanesLog;
 
 	// loop through all bit planes
@@ -521,31 +627,25 @@
 	ASSERT(0 < nPlanes && nPlanes <= MaxBitPlanes + 1);
 	planeMask = 1 << (nPlanes - 1);
 
-	for (plane = nPlanes - 1; plane >= 0; plane--) {
+	for (int plane = nPlanes - 1; plane >= 0; plane--) {
 		// read RL code
 		if (GetBit(m_codeBuffer, codePos)) {
 			// RL coding of sigBits is used
 			codePos++;
 
 			// read codeLen
-			codeLen = GetValueBlock(m_codeBuffer, codePos, RLblockSizeLen);
-
-			// run-length decode significant bits and signs from m_codeBuffer and store them to sigBits
-			ASSERT(codeLen < (1 << RLblockSizeLen)); 
-			m_codePos = codePos + RLblockSizeLen;
-			sigLen = RLDSigsAndSigns(bufferSize, codeLen, sigBits, signBits); ASSERT(sigLen <= bufferSize);
-			//printf("%d\n", sigLen);
-
-			// adjust code buffer position
-			codePos += RLblockSizeLen + codeLen;
-			codePos = AlignWordPos(codePos); ASSERT(codePos < CodeBufferBitLen);
-
+			codeLen = GetValueBlock(m_codeBuffer, codePos, RLblockSizeLen); ASSERT(codeLen < (1 << RLblockSizeLen));
+
+			// position of encoded sigBits and signBits
+			sigPos = codePos + RLblockSizeLen; ASSERT(sigPos < CodeBufferBitLen);
+
+			// refinement bits
+			codePos = AlignWordPos(sigPos + codeLen); ASSERT(codePos < CodeBufferBitLen);
+
+			// run-length decode significant bits and signs from m_codeBuffer and
 			// read refinement bits from m_codeBuffer and compose bit plane
-			sigLen = ComposeBitplane(bufferSize, planeMask, sigBits, &m_codeBuffer[codePos >> WordWidthLog], signBits);
-
-			// adjust code buffer position
-			codePos += bufferSize - sigLen;
-			codePos = AlignWordPos(codePos); ASSERT(codePos < CodeBufferBitLen);
+			sigLen = ComposeBitplaneRLD(bufferSize, planeMask, sigPos, &m_codeBuffer[codePos >> WordWidthLog]);
+
 		} else {
 			// no RL coding is used
 			codePos++;
@@ -561,76 +661,73 @@
 
 				// read codeLen
 				codeLen = GetValueBlock(m_codeBuffer, codePos, RLblockSizeLen);
-				codePos += RLblockSizeLen;
-
-				// RL decode signBits
-				m_codePos = codePos;
-				signLen = RLDSigns(bufferSize, codeLen, signBits);
-
-				// adjust code buffer position
-				codePos += codeLen;
-				codePos = AlignWordPos(codePos); ASSERT(codePos < CodeBufferBitLen);
+
+				// sign bits
+				signPos = codePos + RLblockSizeLen; ASSERT(signPos < CodeBufferBitLen);
+
+				// significant bits
+				sigPos = AlignWordPos(signPos + codeLen); ASSERT(sigPos < CodeBufferBitLen);
+
+				// refinement bits
+				codePos = AlignWordPos(sigPos + sigLen); ASSERT(codePos < CodeBufferBitLen);
+
+				// read significant and refinement bitset from m_codeBuffer
+				sigLen = ComposeBitplaneRLD(bufferSize, planeMask, &m_codeBuffer[sigPos >> WordWidthLog], &m_codeBuffer[codePos >> WordWidthLog], &m_codeBuffer[signPos >> WordWidthLog]);
+
 			} else {
 				// RL coding of signBits was not efficient and therefore not used
 				codePos++;
 
 				// read signLen
-				signLen = GetValueBlock(m_codeBuffer, codePos, RLblockSizeLen); ASSERT(signLen <= bufferSize);
-				
-				// adjust code buffer position
-				codePos += RLblockSizeLen; 
-				codePos = AlignWordPos(codePos); ASSERT(codePos < CodeBufferBitLen);
-
-				// read signBits
-				wordPos = codePos >> WordWidthLog; ASSERT(0 <= wordPos && wordPos < BufferSize);
-				signLen = AlignWordPos(signLen) >> WordWidthLog;
-				for (k=0; k < signLen; k++) {
-					signBits[k] = m_codeBuffer[wordPos];
-					wordPos++;
-				}
-
-				// adjust code buffer position
-				codePos = wordPos << WordWidthLog; ASSERT(codePos < CodeBufferBitLen);
-			}
-
-			sigPos = codePos; // position of sigBits
-			codePos += sigLen;
-
-			codePos = AlignWordPos(codePos);
-			ASSERT(codePos < CodeBufferBitLen);
-
-			// read significant and refinement bitset from m_codeBuffer
-			sigLen = ComposeBitplane(bufferSize, planeMask, &m_codeBuffer[sigPos >> WordWidthLog], &m_codeBuffer[codePos >> WordWidthLog], signBits);
-			
-			// adjust code buffer position
-			codePos += bufferSize - sigLen;
-			codePos = AlignWordPos(codePos);
-		}
+				signLen = AlignWordPos(GetValueBlock(m_codeBuffer, codePos, RLblockSizeLen)); ASSERT(signLen <= bufferSize);
+
+				// sign bits
+				signPos = AlignWordPos(codePos + RLblockSizeLen); ASSERT(signPos < CodeBufferBitLen);
+
+				// significant bits
+				sigPos = signPos + signLen; ASSERT(sigPos < CodeBufferBitLen);
+
+				// refinement bits
+				codePos = AlignWordPos(sigPos + sigLen); ASSERT(codePos < CodeBufferBitLen);
+
+				// read significant and refinement bitset from m_codeBuffer
+				sigLen = ComposeBitplane(bufferSize, planeMask, &m_codeBuffer[sigPos >> WordWidthLog], &m_codeBuffer[codePos >> WordWidthLog], &m_codeBuffer[signPos >> WordWidthLog]);
+			}
+		}
+
+		// start of next chunk
+		codePos = AlignWordPos(codePos + bufferSize - sigLen); ASSERT(codePos < CodeBufferBitLen);
+
+		// next plane
 		planeMask >>= 1;
 	}
+
+	m_valuePos = 0;
 }
 
 ////////////////////////////////////////////////////////////////////
 // Reconstruct bitplane from significant bitset and refinement bitset
 // returns length [bits] of sigBits
-// input:  sigBits, refBits
+// input:  sigBits, refBits, signBits
 // output: m_value
-UINT32 CDecoder::ComposeBitplane(UINT32 bufferSize, UINT32 planeMask, UINT32* sigBits, UINT32* refBits, UINT32* signBits) {
+UINT32 CDecoder::CMacroBlock::ComposeBitplane(UINT32 bufferSize, DataT planeMask, UINT32* sigBits, UINT32* refBits, UINT32* signBits) {
 	ASSERT(sigBits);
 	ASSERT(refBits);
 	ASSERT(signBits);
 
 	UINT32 valPos = 0, signPos = 0, refPos = 0;
-	UINT32 sigPos = 0, sigEnd, sigRunLen;
+	UINT32 sigPos = 0, sigEnd;
 	UINT32 zerocnt;
 
 	while (valPos < bufferSize) {
-		// search next 1 in m_sigFlagVector
-		sigRunLen = SeekBitRange(m_sigFlagVector, valPos, bufferSize - valPos);
-
-		// search 1's in sigBits[valuePos..valuePos+sigRunLen)
+		// search next 1 in m_sigFlagVector using searching with sentinel
+		sigEnd = valPos;
+		while(!m_sigFlagVector[sigEnd]) { sigEnd++; }
+		sigEnd -= valPos;
+		sigEnd += sigPos;
+
+		// search 1's in sigBits[sigPos..sigEnd)
 		// these 1's are significant bits
-		sigEnd = sigPos + sigRunLen;
 		while (sigPos < sigEnd) {
 			// search 0's
 			zerocnt = SeekBitRange(sigBits, sigPos, sigEnd - sigPos);
@@ -641,13 +738,11 @@
 				SetBitAtPos(valPos, planeMask);
 
 				// copy sign bit
-				SetSign(valPos, GetBit(signBits, signPos)); 
-				signPos++;
+				SetSign(valPos, GetBit(signBits, signPos++));
 
 				// update significance flag vector
-				SetBit(m_sigFlagVector, valPos);
-				sigPos++; 
-				valPos++;
+				m_sigFlagVector[valPos++] = true;
+				sigPos++;
 			}
 		}
 		// refinement bit
@@ -668,135 +763,228 @@
 	return sigPos;
 }
 
-//////////////////////////////////////////////////////////////////////
-// Adaptive run-Length decoder for significant bits with a lot of zeros and sign bits.
-// Returns length of sigBits.
+////////////////////////////////////////////////////////////////////
+// Reconstruct bitplane from significant bitset and refinement bitset
+// returns length [bits] of decoded significant bits
+// input:  RL encoded sigBits and signBits in m_codeBuffer, refBits
+// output: m_value
+// RLE:
 // - Decode run of 2^k zeros by a single 0.
 // - Decode run of count 0's followed by a 1 with codeword: 1<count>x
 // - x is 0: if a positive sign has been stored, otherwise 1
-// - Read each bit from m_codeBuffer[m_codePos] and increment m_codePos.
-UINT32 CDecoder::RLDSigsAndSigns(UINT32 bufferSize, UINT32 codeLen, UINT32* sigBits, UINT32* signBits) {
-	ASSERT(sigBits);
-	ASSERT(signBits);
-	ASSERT(m_codePos < CodeBufferBitLen);
-	const UINT32 inEndPos = m_codePos + codeLen; ASSERT(inEndPos < CodeBufferBitLen);
-
+// - Read each bit from m_codeBuffer[codePos] and increment codePos.
+UINT32 CDecoder::CMacroBlock::ComposeBitplaneRLD(UINT32 bufferSize, DataT planeMask, UINT32 codePos, UINT32* refBits) {
+	ASSERT(refBits);
+
+	UINT32 valPos = 0, refPos = 0;
+	UINT32 sigPos = 0, sigEnd;
 	UINT32 k = 3;
 	UINT32 runlen = 1 << k; // = 2^k
-	UINT32 count = 0;
-	UINT32 sigPos = 0, signPos = 0;
-
-	ASSERT(inEndPos < CodeBufferBitLen);
-	while (m_codePos < inEndPos) {
-		if (GetBit(m_codeBuffer, m_codePos)) {
-			m_codePos++;
-			
-			// extract counter and generate zero run of length count
-			if (k > 0) {
-				// extract counter
-				count = GetValueBlock(m_codeBuffer, m_codePos, k); 
-				m_codePos += k;
-				if (count > 0) {
-					ClearBitBlock(sigBits, sigPos, count); 
-					sigPos += count;
+	UINT32 count = 0, rest = 0;
+	bool set1 = false;
+
+	while (valPos < bufferSize) {
+		// search next 1 in m_sigFlagVector using searching with sentinel
+		sigEnd = valPos;
+		while(!m_sigFlagVector[sigEnd]) { sigEnd++; }
+		sigEnd -= valPos;
+		sigEnd += sigPos;
+
+		while (sigPos < sigEnd) {
+			if (rest || set1) {
+				// rest of last run
+				sigPos += rest;
+				valPos += rest;
+				rest = 0;
+			} else {
+				// decode significant bits
+				if (GetBit(m_codeBuffer, codePos++)) {
+					// extract counter and generate zero run of length count
+					if (k > 0) {
+						// extract counter
+						count = GetValueBlock(m_codeBuffer, codePos, k);
+						codePos += k;
+						if (count > 0) {
+							sigPos += count;
+							valPos += count;
+						}
+
+						// adapt k (half run-length interval)
+						k--;
+						runlen >>= 1;
+					}
+
+					set1 = true;
+
+				} else {
+					// generate zero run of length 2^k
+					sigPos += runlen;
+					valPos += runlen;
+
+					// adapt k (double run-length interval)
+					if (k < WordWidth) {
+						k++;
+						runlen <<= 1;
+					}
 				}
 			}
-			// write 1 bit
-			if (sigPos < bufferSize) {
-				SetBit(sigBits, sigPos); sigPos++;
-			}
-
-			// get sign bit
-			if (GetBit(m_codeBuffer, m_codePos)) {
-				SetBit(signBits, signPos);
+
+			if (sigPos < sigEnd) {
+				if (set1) {
+					set1 = false;
+
+					// write 1 bit
+					SetBitAtPos(valPos, planeMask);
+
+					// set sign bit
+					SetSign(valPos, GetBit(m_codeBuffer, codePos++));
+
+					// update significance flag vector
+					m_sigFlagVector[valPos++] = true;
+					sigPos++;
+				}
 			} else {
-				ClearBit(signBits, signPos);
-			}
-			signPos++; m_codePos++;
-
-			// adapt k (half run-length interval)
-			if (k > 0) {
-				k--;
-				runlen >>= 1;
-			}
-		} else {
-			m_codePos++;
-			// generate zero run of length 2^k
-			//ASSERT(sigPos + runlen <= BufferSize);
-			ClearBitBlock(sigBits, sigPos, runlen); 
-			sigPos += runlen;
-
-			// adapt k (double run-length interval)
-			if (k < WordWidth) {
-				k++;
-				runlen <<= 1;
-			}
-		}
-	}
+				rest = sigPos - sigEnd;
+				sigPos = sigEnd;
+				valPos -= rest;
+			}
+
+		}
+
+		// refinement bit
+		if (valPos < bufferSize) {
+			// write one refinement bit
+			if (GetBit(refBits, refPos)) {
+				SetBitAtPos(valPos, planeMask);
+			}
+			refPos++;
+			valPos++;
+		}
+	}
+	ASSERT(sigPos <= bufferSize);
+	ASSERT(refPos <= bufferSize);
+	ASSERT(valPos == bufferSize);
+
 	return sigPos;
 }
 
-/////////////////////////////////////////////////////
-// Adaptive run-length decoder.
-// Returns signLen in bits.
-// decodes codeLen bits from m_codeBuffer at m_codePos
+////////////////////////////////////////////////////////////////////
+// Reconstruct bitplane from significant bitset, refinement bitset, and RL encoded sign bits
+// returns length [bits] of sigBits
+// input:  sigBits, refBits, RL encoded signBits
+// output: m_value
+// RLE:
 // decode run of 2^k 1's by a single 1
 // decode run of count 1's followed by a 0 with codeword: 0<count>
-// output is stored in signBits
-UINT32 CDecoder::RLDSigns(UINT32 bufferSize, UINT32 codeLen, UINT32* signBits) {
+UINT32 CDecoder::CMacroBlock::ComposeBitplaneRLD(UINT32 bufferSize, DataT planeMask, UINT32* sigBits, UINT32* refBits, UINT32* signBits) {
+	ASSERT(sigBits);
+	ASSERT(refBits);
 	ASSERT(signBits);
-	ASSERT(0 <= m_codePos && m_codePos < CodeBufferBitLen);
-	const UINT32 inEndPos = m_codePos + codeLen; ASSERT(inEndPos < CodeBufferBitLen);
-
+
+	UINT32 valPos = 0, signPos = 0, refPos = 0;
+	UINT32 sigPos = 0, sigEnd;
+	UINT32 zerocnt, count = 0;
 	UINT32 k = 0;
 	UINT32 runlen = 1 << k; // = 2^k
-	UINT32 count = 0, signPos = 0;
-
-	while (m_codePos < inEndPos) {
-		if (GetBit(m_codeBuffer, m_codePos)) {
-			m_codePos++;
-			// generate 1's run of length 2^k
-			SetBitBlock(signBits, signPos, runlen); 
-			signPos += runlen;
-			
-			// adapt k (double run-length interval)
-			if (k < WordWidth) {
-				k++; 
-				runlen <<= 1;
-			}
-		} else {
-			m_codePos++;
-			// extract counter and generate zero run of length count
-			if (k > 0) {
-				// extract counter
-				count = GetValueBlock(m_codeBuffer, m_codePos, k); 
-				m_codePos += k;
-				if (count > 0) {
-					SetBitBlock(signBits, signPos, count); 
-					signPos += count;
+	bool signBit = false;
+	bool zeroAfterRun = false;
+
+	while (valPos < bufferSize) {
+		// search next 1 in m_sigFlagVector using searching with sentinel
+		sigEnd = valPos;
+		while(!m_sigFlagVector[sigEnd]) { sigEnd++; }
+		sigEnd -= valPos;
+		sigEnd += sigPos;
+
+		// search 1's in sigBits[sigPos..sigEnd)
+		// these 1's are significant bits
+		while (sigPos < sigEnd) {
+			// search 0's
+			zerocnt = SeekBitRange(sigBits, sigPos, sigEnd - sigPos);
+			sigPos += zerocnt;
+			valPos += zerocnt;
+			if (sigPos < sigEnd) {
+				// write bit to m_value
+				SetBitAtPos(valPos, planeMask);
+
+				// check sign bit
+				if (count == 0) {
+					// all 1's have been set
+					if (zeroAfterRun) {
+						// finish the run with a 0
+						signBit = false;
+						zeroAfterRun = false;
+					} else {
+						// decode next sign bit
+						if (GetBit(signBits, signPos++)) {
+							// generate 1's run of length 2^k
+							count = runlen - 1;
+							signBit = true;
+
+							// adapt k (double run-length interval)
+							if (k < WordWidth) {
+								k++;
+								runlen <<= 1;
+							}
+						} else {
+							// extract counter and generate 1's run of length count
+							if (k > 0) {
+								// extract counter
+								count = GetValueBlock(signBits, signPos, k);
+								signPos += k;
+
+								// adapt k (half run-length interval)
+								k--;
+								runlen >>= 1;
+							}
+							if (count > 0) {
+								count--;
+								signBit = true;
+								zeroAfterRun = true;
+							} else {
+								signBit = false;
+							}
+						}
+					}
+				} else {
+					ASSERT(count > 0);
+					ASSERT(signBit);
+					count--;
 				}
-			}
-			if (signPos < bufferSize) {
-				ClearBit(signBits, signPos); 
-				signPos++;
-			}
-			
-			// adapt k (half run-length interval)
-			if (k > 0) {
-				k--; 
-				runlen >>= 1;
-			}
-		}
-	}
-	return signPos;
+
+				// copy sign bit
+				SetSign(valPos, signBit);
+
+				// update significance flag vector
+				m_sigFlagVector[valPos++] = true;
+				sigPos++;
+			}
+		}
+
+		// refinement bit
+		if (valPos < bufferSize) {
+			// write one refinement bit
+			if (GetBit(refBits, refPos)) {
+				SetBitAtPos(valPos, planeMask);
+			}
+			refPos++;
+			valPos++;
+		}
+	}
+	ASSERT(sigPos <= bufferSize);
+	ASSERT(refPos <= bufferSize);
+	ASSERT(signPos <= bufferSize);
+	ASSERT(valPos == bufferSize);
+
+	return sigPos;
 }
 
 ////////////////////////////////////////////////////////////////////
 #ifdef TRACE
 void CDecoder::DumpBuffer() {
-	printf("\nDump\n");
-	for (int i=0; i < BufferSize; i++) {
-		printf("%d", m_value[i]);
-	}
+	//printf("\nDump\n");
+	//for (int i=0; i < BufferSize; i++) {
+	//	printf("%d", m_value[i]);
+	//}
 }
 #endif //TRACE

Modified: trunk/Scribus/scribus/third_party/pgf/Decoder.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16771&path=/trunk/Scribus/scribus/third_party/pgf/Decoder.h
==============================================================================
--- trunk/Scribus/scribus/third_party/pgf/Decoder.h (original)
+++ trunk/Scribus/scribus/third_party/pgf/Decoder.h Mon Aug  8 18:19:05 2011
@@ -1,34 +1,38 @@
 /*
  * The Progressive Graphics File; http://www.libpgf.org
- * 
+ *
  * $Date: 2006-06-04 22:05:59 +0200 (So, 04 Jun 2006) $
  * $Revision: 229 $
- * 
+ *
  * This file Copyright (C) 2006 xeraina GmbH, Switzerland
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
  * as published by the Free Software Foundation; either version 2.1
  * of the License, or (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+//////////////////////////////////////////////////////////////////////
+/// @file Decoder.h
+/// @brief PGF decoder class
+/// @author C. Stamm, R. Spuler
+
 #ifndef PGF_DECODER_H
 #define PGF_DECODER_H
 
-#include "PGFtypes.h"
+#include "PGFstream.h"
 #include "BitStream.h"
 #include "Subband.h"
 #include "WaveletTransform.h"
-#include "Stream.h"
 
 /////////////////////////////////////////////////////////////////////
 // Constants
@@ -37,13 +41,41 @@
 /////////////////////////////////////////////////////////////////////
 /// PGF decoder class.
 /// @author C. Stamm, R. Spuler
+/// @brief PGF decoder
 class CDecoder {
+	//////////////////////////////////////////////////////////////////////
+	/// PGF decoder macro block class.
+	/// @author C. Stamm, I. Bauersachs
+	/// @brief A macro block is a decoding unit of fixed size (uncoded)
+	class CMacroBlock {
+	public:
+		CMacroBlock(CDecoder *decoder)
+		: m_header(0)
+        , m_valuePos(0)
+		, m_decoder(decoder)
+		{
+			ASSERT(m_decoder);
+		}
+
+		void  BitplaneDecode();						// several macro blocks can be encoded in parallel
+
+		ROIBlockHeader m_header;					// block header
+		DataT  m_value[BufferSize];					// output buffer of values with index m_valuePos
+		UINT32 m_codeBuffer[BufferSize];			// input buffer for encoded bitstream
+		UINT32 m_valuePos;							// current position in m_value
+
+	private:
+		UINT32 ComposeBitplane(UINT32 bufferSize, DataT planeMask, UINT32* sigBits, UINT32* refBits, UINT32* signBits);
+		UINT32 ComposeBitplaneRLD(UINT32 bufferSize, DataT planeMask, UINT32 sigPos, UINT32* refBits);
+		UINT32 ComposeBitplaneRLD(UINT32 bufferSize, DataT planeMask, UINT32* sigBits, UINT32* refBits, UINT32* signBits);
+		void  SetBitAtPos(UINT32 pos, DataT planeMask)			{ (m_value[pos] >= 0) ? m_value[pos] |= planeMask : m_value[pos] -= planeMask; }
+		void  SetSign(UINT32 pos, bool sign)					{ m_value[pos] = -m_value[pos]*sign + m_value[pos]*(!sign); }
+
+		CDecoder *m_decoder;						// outer class
+		bool m_sigFlagVector[BufferSize+1];			// see paper from Malvar, Fast Progressive Wavelet Coder
+	};
+
 public:
-	/////////////////////////////////////////////////////////////////////
-	/// Constructor: Initialize PGF stream and buffer position.
-	/// @param stream A PGF stream or NULL
-	CDecoder(CPGFStream* stream = NULL);
-
 	/////////////////////////////////////////////////////////////////////
 	/// Constructor: Read pre-header, header, and levelLength at current stream position.
 	/// It might throw an IOException.
@@ -52,7 +84,8 @@
 	/// @param header [out] A PGF header
 	/// @param postHeader [out] A PGF post-header
 	/// @param levelLength The location of the levelLength array. The array is allocated in this method. The caller has to delete this array.
-	CDecoder(CPGFStream* stream, PGFPreHeader& preHeader, PGFHeader& header, PGFPostHeader& postHeader, UINT32*& levelLength) THROW_; // throws IOException
+	/// @param useOMP If true, then the decoder will use multi-threading based on openMP
+	CDecoder(CPGFStream* stream, PGFPreHeader& preHeader, PGFHeader& header, PGFPostHeader& postHeader, UINT32*& levelLength, bool useOMP = true) THROW_; // throws IOException
 
 	/////////////////////////////////////////////////////////////////////
 	/// Destructor
@@ -90,7 +123,7 @@
 	void SetStreamPosToStart() THROW_				{ ASSERT(m_stream); m_stream->SetPos(FSFromStart, m_startPos); }
 
 	////////////////////////////////////////////////////////////////////
-	/// Reset stream position to beginning of PGF pre header
+	/// Reset stream position to beginning of data block
 	void SetStreamPosToData() THROW_				{ ASSERT(m_stream); m_stream->SetPos(FSFromStart, m_startPos + m_encodedHeaderLength); }
 
 	////////////////////////////////////////////////////////////////////
@@ -113,16 +146,21 @@
 	/// @return The number of bytes copied to the target buffer
 	UINT32 ReadEncodedData(UINT8* target, UINT32 len) const THROW_;
 
+	/////////////////////////////////////////////////////////////////////
+	/// Reads stream and decodes tile buffer
+	/// It might throw an IOException.
+	void DecodeBuffer() THROW_;
+
 #ifdef __PGFROISUPPORT__
 	/////////////////////////////////////////////////////////////////////
 	/// Reads stream and decodes tile buffer
 	/// It might throw an IOException.
-	void DecodeTileBuffer() THROW_ 	{ ASSERT(m_valuePos >= 0 && m_valuePos <= BufferSize); DecodeBuffer(); }
+	void DecodeTileBuffer() THROW_;
 
 	/////////////////////////////////////////////////////////////////////
 	/// Resets stream position to next tile.
 	/// It might throw an IOException.
-	void SkipTileBuffer() THROW_	{ ASSERT(m_valuePos >= 0 && m_valuePos <= BufferSize); SkipBuffer(); }
+	void SkipTileBuffer() THROW_;
 
 	/////////////////////////////////////////////////////////////////////
 	/// Enables region of interest (ROI) status.
@@ -134,30 +172,19 @@
 #endif
 
 private:
-	void  BitplaneDecode(UINT32 bufferSize);
-	UINT32 RLDSigsAndSigns(UINT32 bufferSize, UINT32 codeLen, UINT32* sigBits, UINT32* signBits);
-	UINT32 RLDSigns(UINT32 bufferSize, UINT32 codeLen, UINT32* signBits);
-	UINT32 ComposeBitplane(UINT32 bufferSize, UINT32 planeMask, UINT32* sigBits, UINT32* refBits, UINT32* signBits);
-	void  DecodeBuffer() THROW_; // throws IOException
-	void  SetBitAtPos(UINT32 pos, UINT32 planeMask)			{ (m_value[pos] >= 0) ? m_value[pos] |= planeMask : m_value[pos] -= planeMask; }
-	void  SetSign(UINT32 pos, bool sign)					{ m_value[pos] = -m_value[pos]*sign + m_value[pos]*(!sign); }
-	//void  SetSign(UINT32 pos, bool sign)					{ if (sign && m_value[pos] >= 0) m_value[pos] = -m_value[pos]; }
-	void  SkipBuffer() THROW_; //throws IOException
+	void ReadMacroBlock(CMacroBlock* block) THROW_; // throws IOException
 
-protected:
 	CPGFStream *m_stream;						// input pgf stream
 	UINT64 m_startPos;							// stream position at the beginning of the PGF pre header
+	UINT64 m_streamSizeEstimation;				// estimation of stream size
 	UINT32 m_encodedHeaderLength;				// stream offset from startPos to the beginning of the data part (highest level)
 
-	DataT  m_value[BufferSize];					// buffer of values with index m_valuePos
-	UINT32 m_codeBuffer[BufferSize];			// buffer for encoded bitstream
+	CMacroBlock **m_macroBlocks;				// array of macroblocks
+	int m_currentBlockIndex;					// index of current macro block
+	int	m_macroBlockLen;						// array length
+	int	m_macroBlocksAvailable;					// number of decoded macro blocks
+	CMacroBlock *m_currentBlock;				// current macro block (used by main thread)
 
-	UINT32 m_sigFlagVector[BufferLen];			// see paper from Malvar, Fast Progressive Wavelet Coder
-
-	UINT32 m_valuePos;							// current position in m_value
-	UINT32 m_codePos;							// current bit position in m_codeBuffer
-
-	bool   m_bufferIsAvailable;					// buffer contains needed coefficients
 #ifdef __PGFROISUPPORT__
 	bool   m_roi;								// true: ensures region of interest (ROI) decoding
 #endif

Modified: trunk/Scribus/scribus/third_party/pgf/Encoder.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16771&path=/trunk/Scribus/scribus/third_party/pgf/Encoder.cpp
==============================================================================
--- trunk/Scribus/scribus/third_party/pgf/Encoder.cpp (original)
+++ trunk/Scribus/scribus/third_party/pgf/Encoder.cpp Mon Aug  8 18:19:05 2011
@@ -1,27 +1,33 @@
 /*
  * The Progressive Graphics File; http://www.libpgf.org
- * 
+ *
  * $Date: 2007-02-03 13:04:21 +0100 (Sa, 03 Feb 2007) $
  * $Revision: 280 $
- * 
+ *
  * This file Copyright (C) 2006 xeraina GmbH, Switzerland
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
  * as published by the Free Software Foundation; either version 2.1
  * of the License, or (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+//////////////////////////////////////////////////////////////////////
+/// @file Encoder.cpp
+/// @brief PGF encoder class implementation
+/// @author C. Stamm, R. Spuler
+
 #include "Encoder.h"
+
 #ifdef TRACE
 	#include <stdio.h>
 #endif
@@ -47,7 +53,7 @@
 //                m_codeBuffer  (for each plane: RLcodeLength (16 bit), RLcoded sigBits + m_sign, refBits)
 //                      |
 //                    file      (for each buffer: packedLength (16 bit), packed bits)
-//  
+//
 
 // Constants
 #define CodeBufferBitLen		(BufferSize*WordWidth)		// max number of bits in m_codeBuffer
@@ -56,13 +62,15 @@
 //////////////////////////////////////////////////////
 // Constructor
 // Write pre-header, header, postHeader, and levelLength.
-// Throws IOException
+// It might throw an IOException.
 // preHeader and header must not be references, because on BigEndian platforms they are modified
-CEncoder::CEncoder(CPGFStream* stream, PGFPreHeader preHeader, PGFHeader header, const PGFPostHeader& postHeader, UINT32*& levelLength) THROW_
+CEncoder::CEncoder(CPGFStream* stream, PGFPreHeader preHeader, PGFHeader header, const PGFPostHeader& postHeader, UINT32*& levelLength, bool useOMP /*= true*/) THROW_
 : m_stream(stream)
 , m_startPosition(0)
-, m_valuePos(0)
-, m_maxAbsValue(0)
+, m_currLevelIndex(0)
+, m_nLevels(header.nLevels)
+, m_favorSpeed(false)
+, m_forceWriting(false)
 #ifdef __PGFROISUPPORT__
 , m_roi(false)
 #endif
@@ -71,6 +79,28 @@
 
 	int count;
 
+	// set number of threads
+#ifdef LIBPGF_USE_OPENMP
+	m_macroBlockLen = omp_get_num_procs();
+#else
+	m_macroBlockLen = 1;
+#endif
+
+	if (useOMP && m_macroBlockLen > 1) {
+#ifdef LIBPGF_USE_OPENMP
+		omp_set_num_threads(m_macroBlockLen);
+#endif
+
+		// create macro block array
+		m_macroBlocks = new CMacroBlock*[m_macroBlockLen];
+		for (int i=0; i < m_macroBlockLen; i++) m_macroBlocks[i] = new CMacroBlock(this);
+		m_lastMacroBlock = 0;
+		m_currentBlock = m_macroBlocks[m_lastMacroBlock++];
+	} else {
+		m_macroBlocks = 0;
+		m_currentBlock = new CMacroBlock(this);
+	}
+
 	// save file position
 	m_startPosition = m_stream->GetPos();
 
@@ -97,28 +127,27 @@
 		m_stream->Write(&count, postHeader.userData);
 	}
 
-	m_currLevelIndex = 0;
-	m_isLevelEncoded = false;
-
 	// renew levelLength
 	delete[] levelLength;
-	levelLength = new UINT32[header.nLevels];
+	levelLength = new UINT32[m_nLevels];
 	if (!levelLength) ReturnWithError(InsufficientMemory);
-	for (UINT8 l = 0; l < header.nLevels; l++) levelLength[l] = 0;
+	for (UINT8 l = 0; l < m_nLevels; l++) levelLength[l] = 0;
 	m_levelLength = levelLength;
 
 	// write dummy levelLength
 	m_levelLengthPos = m_stream->GetPos();
-	count = header.nLevels*WordBytes;
+	count = m_nLevels*WordBytes;
 	m_stream->Write(&count, m_levelLength);
 
 	// save current file position
-	m_currPosition = m_stream->GetPos();
+	SetBufferStartPos();
 }
 
 //////////////////////////////////////////////////////
 // Destructor
-CEncoder::~CEncoder() {	
+CEncoder::~CEncoder() {
+	delete m_currentBlock;
+	delete[] m_macroBlocks;
 }
 
 /////////////////////////////////////////////////////////////////////
@@ -138,17 +167,16 @@
 	const div_t ww = div(width, LinBlockSize);
 	const int ws = pitch - LinBlockSize;
 	const int wr = pitch - ww.rem;
-	int x, y, i, j;
 	int pos, base = startPos, base2;
 
 	// main height
-	for (i=0; i < hh.quot; i++) {
+	for (int i=0; i < hh.quot; i++) {
 		// main width
 		base2 = base;
-		for (j=0; j < ww.quot; j++) {
+		for (int j=0; j < ww.quot; j++) {
 			pos = base2;
-			for (y=0; y < LinBlockSize; y++) {
-				for (x=0; x < LinBlockSize; x++) {
+			for (int y=0; y < LinBlockSize; y++) {
+				for (int x=0; x < LinBlockSize; x++) {
 					WriteValue(band, pos);
 					pos++;
 				}
@@ -158,8 +186,8 @@
 		}
 		// rest of width
 		pos = base2;
-		for (y=0; y < LinBlockSize; y++) {
-			for (x=0; x < ww.rem; x++) {
+		for (int y=0; y < LinBlockSize; y++) {
+			for (int x=0; x < ww.rem; x++) {
 				WriteValue(band, pos);
 				pos++;
 			}
@@ -167,13 +195,13 @@
 			base += pitch;
 		}
 	}
-	// main width 
+	// main width
 	base2 = base;
-	for (j=0; j < ww.quot; j++) {
+	for (int j=0; j < ww.quot; j++) {
 		// rest of height
 		pos = base2;
-		for (y=0; y < hh.rem; y++) {
-			for (x=0; x < LinBlockSize; x++) {
+		for (int y=0; y < hh.rem; y++) {
+			for (int x=0; x < LinBlockSize; x++) {
 				WriteValue(band, pos);
 				pos++;
 			}
@@ -183,9 +211,9 @@
 	}
 	// rest of height
 	pos = base2;
-	for (y=0; y < hh.rem; y++) {
+	for (int y=0; y < hh.rem; y++) {
 		// rest of width
-		for (x=0; x < ww.rem; x++) {
+		for (int x=0; x < ww.rem; x++) {
 			WriteValue(band, pos);
 			pos++;
 		}
@@ -194,48 +222,43 @@
 }
 
 //////////////////////////////////////////////////////
-// Pad buffer with zeros, encode buffer, write levelLength into header
-// Return number of bytes written into stream
-// Throws IOException
-UINT32 CEncoder::Flush() THROW_ {
-	UINT32 retValue;
-
-#ifdef __PGFROISUPPORT__
-	if (!m_roi) {
-#endif
-		// pad buffer with zeros
-		while (m_valuePos < BufferSize) {
-			m_value[m_valuePos] = 0; 
-			m_valuePos++;
-		}
-#ifdef __PGFROISUPPORT__
-	}
-#endif
+/// Pad buffer with zeros and encode buffer.
+/// It might throw an IOException.
+void CEncoder::Flush() THROW_ {
+	// pad buffer with zeros
+	memset(&(m_currentBlock->m_value[m_currentBlock->m_valuePos]), 0, (BufferSize - m_currentBlock->m_valuePos)*DataTSize);
+	m_currentBlock->m_valuePos = BufferSize;
 
 	// encode buffer
-	EncodeBuffer(ROIBlockHeader(m_valuePos, true));
-
-	retValue = UINT32(m_stream->GetPos() - m_startPosition);
+	m_forceWriting = true;	// makes sure that the following EncodeBuffer is really written into the stream
+	EncodeBuffer(ROIBlockHeader(m_currentBlock->m_valuePos, true));
+}
+
+//////////////////////////////////////////////////////
+/// Write levelLength into header.
+/// @return number of bytes written into stream
+/// It might throw an IOException.
+UINT32 CEncoder::WriteLevelLength() THROW_ {
+	UINT64 curPos = m_stream->GetPos();
+	UINT32 retValue = UINT32(curPos - m_startPosition);
 
 	if (m_levelLength) {
 		// append levelLength to file, directly after post-header
-		UINT64 curPos = m_stream->GetPos();
-
 		// set file pos to levelLength
 		m_stream->SetPos(FSFromStart, m_levelLengthPos);
-#ifdef PGF_USE_BIG_ENDIAN 
+	#ifdef PGF_USE_BIG_ENDIAN
 		UINT32 levelLength;
 		int count = WordBytes;
-		
+
 		for (int i=0; i < m_currLevelIndex; i++) {
 			levelLength = __VAL(UINT32(m_levelLength[i]));
 			m_stream->Write(&count, &levelLength);
 		}
-#else
+	#else
 		int count = m_currLevelIndex*WordBytes;
-		
+
 		m_stream->Write(&count, m_levelLength);
-#endif //PGF_USE_BIG_ENDIAN 
+	#endif //PGF_USE_BIG_ENDIAN
 
 		// restore file position
 		m_stream->SetPos(FSFromStart, curPos);
@@ -247,313 +270,409 @@
 /////////////////////////////////////////////////////////////////////
 // Stores band value from given position bandPos into buffer m_value at position m_valuePos
 // If buffer is full encode it to file
-// Throws IOException
+// It might throw an IOException.
 void CEncoder::WriteValue(CSubband* band, int bandPos) THROW_ {
-	if (m_valuePos == BufferSize) {
+	if (m_currentBlock->m_valuePos == BufferSize) {
 		EncodeBuffer(ROIBlockHeader(BufferSize, false));
 	}
-	m_value[m_valuePos] = band->GetData(bandPos);
-	UINT32 v = abs(m_value[m_valuePos]);
-	if (v > m_maxAbsValue) m_maxAbsValue = v;
-	m_valuePos++;
-}
-
-///////////////////////////////////////////////////////
+	DataT val = m_currentBlock->m_value[m_currentBlock->m_valuePos++] = band->GetData(bandPos);
+	UINT32 v = abs(val);
+	if (v > m_currentBlock->m_maxAbsValue) m_currentBlock->m_maxAbsValue = v;
+}
+
+/////////////////////////////////////////////////////////////////////
+// Write encoded macro block into stream.
+// It might throw an IOException.
+void CEncoder::WriteMacroBlock(CMacroBlock* block) THROW_ {
+	ASSERT(block);
+
+	ROIBlockHeader h = block->m_header;
+	UINT16 wordLen = UINT16(NumberOfWords(block->m_codePos)); ASSERT(wordLen <= BufferSize);
+	int count = sizeof(UINT16);
+
+#ifdef TRACE
+	//UINT32 filePos = (UINT32)m_stream->GetPos();
+	//printf("EncodeBuffer: %d\n", filePos);
+#endif
+
+#ifdef PGF_USE_BIG_ENDIAN
+	// write wordLen
+	UINT16 wl = __VAL(wordLen);
+	m_stream->Write(&count, &wl); ASSERT(count == sizeof(UINT16));
+
+#ifdef __PGFROISUPPORT__
+	// write ROIBlockHeader
+	if (m_roi) {
+		h.val = __VAL(h.val);
+		m_stream->Write(&count, &h.val); ASSERT(count == sizeof(UINT16));
+	}
+#endif // __PGFROISUPPORT__
+
+	// convert data
+	for (int i=0; i < wordLen; i++) {
+		m_codeBuffer[i] = __VAL(m_codeBuffer[i]);
+	}
+#else
+	// write wordLen
+	m_stream->Write(&count, &wordLen); ASSERT(count == sizeof(UINT16));
+
+#ifdef __PGFROISUPPORT__
+	// write ROIBlockHeader
+	if (m_roi) {
+		m_stream->Write(&count, &h.val); ASSERT(count == sizeof(UINT16));
+	}
+#endif // __PGFROISUPPORT__
+#endif // PGF_USE_BIG_ENDIAN
+
+	// write encoded data into stream
+	count = wordLen*WordBytes;
+	m_stream->Write(&count, block->m_codeBuffer);
+
+	// store levelLength
+	if (m_levelLength) {
+		// store level length
+		// EncodeBuffer has been called after m_lastLevelIndex has been updated
+		m_levelLength[m_currLevelIndex] += ComputeBufferLength();
+		m_currLevelIndex = block->m_lastLevelIndex + 1;
+
+	}
+
+	// prepare for next buffer
+	SetBufferStartPos();
+
+	// reset values
+	block->m_valuePos = 0;
+	block->m_maxAbsValue = 0;
+}
+
+/////////////////////////////////////////////////////////////////////
 // Encode buffer and write data into stream.
 // h contains buffer size and flag indicating end of tile.
 // Encoding scheme: <wordLen>(16 bits) [ ROI ] data
 //		ROI	  ::= <bufferSize>(15 bits) <eofTile>(1 bit)
-// Throws IOException
+// It might throw an IOException.
 void CEncoder::EncodeBuffer(ROIBlockHeader h) THROW_ {
+	ASSERT(m_currentBlock);
 #ifdef __PGFROISUPPORT__
-	ASSERT(m_roi && h.bufferSize <= BufferSize || h.bufferSize == BufferSize);
+	ASSERT(m_roi && h.rbh.bufferSize <= BufferSize || h.rbh.bufferSize == BufferSize);
 #else
-	ASSERT(h.bufferSize == BufferSize);
+	ASSERT(h.rbh.bufferSize == BufferSize);
 #endif
-
-	UINT32 codeLen = BitplaneEncode(h.bufferSize);
-	UINT16 wordLen = UINT16(AlignWordPos(codeLen)/WordWidth);
-	ASSERT(wordLen <= BufferSize);
-	
-	int count = sizeof(UINT16);
-
-#ifdef PGF_USE_BIG_ENDIAN 
-	// write wordLen
-	UINT16 wordLen2 = __VAL(wordLen);
-	m_stream->Write(&count, &wordLen2);
-
-	#ifdef __PGFROISUPPORT__
-		// write ROIBlockHeader
-		if (m_roi) {
-			h.val = __VAL(h.val);
-			m_stream->Write(&count, &h.val); ASSERT(count == sizeof(UINT16));
-		}
-	#endif // __PGFROISUPPORT__
-
-	// convert data
-	for (int i=0; i < wordLen; i++) {
-		m_codeBuffer[i] = __VAL(m_codeBuffer[i]);
-	}
-#else
-	// write wordLen
-	m_stream->Write(&count, &wordLen); ASSERT(count == sizeof(UINT16));
-
-	#ifdef __PGFROISUPPORT__
-		// write ROIBlockHeader
-		if (m_roi) {
-			m_stream->Write(&count, &h.val); ASSERT(count == sizeof(UINT16));
-		}
-	#endif // __PGFROISUPPORT__
-#endif // PGF_USE_BIG_ENDIAN 
-
-	// write data
-	count = wordLen*WordBytes;
-	m_stream->Write(&count, m_codeBuffer);
-
-	// store levelLength
-	if (m_levelLength && m_isLevelEncoded) {
-		m_isLevelEncoded = false;
-		UINT64 streamPos = m_stream->GetPos();
-		ASSERT(streamPos - m_currPosition <= UINT_MAX);
-		m_levelLength[m_currLevelIndex++] = UINT32(streamPos - m_currPosition);
-		m_currPosition = streamPos;
-	}
-
-	// reset values
-	m_valuePos = 0;
-	m_maxAbsValue = 0;
+	m_currentBlock->m_header = h;
+
+	// macro block management
+	if (m_macroBlockLen == 1) {
+		m_currentBlock->BitplaneEncode();
+		WriteMacroBlock(m_currentBlock);
+	} else {
+		// save last level index
+		int lastLevelIndex = m_currentBlock->m_lastLevelIndex;
+
+		if (m_forceWriting || m_lastMacroBlock == m_macroBlockLen) {
+			// encode macro blocks
+			/*
+			volatile OSError error = NoError;
+			#pragma omp parallel for ordered default(shared)
+			for (int i=0; i < m_lastMacroBlock; i++) {
+				if (error == NoError) {
+					m_macroBlocks[i]->BitplaneEncode();
+					#pragma omp ordered
+					{
+						try {
+							WriteMacroBlock(m_macroBlocks[i]);
+						} catch (IOException& e) {
+							error = e.error;
+						}
+						delete m_macroBlocks[i]; m_macroBlocks[i] = 0;
+					}
+				}
+			}
+			if (error != NoError) ReturnWithError(error);
+			*/
+			#pragma omp parallel for default(shared) //no declared exceptions in next block
+			for (int i=0; i < m_lastMacroBlock; i++) {
+				m_macroBlocks[i]->BitplaneEncode();
+			}
+			for (int i=0; i < m_lastMacroBlock; i++) {
+				WriteMacroBlock(m_macroBlocks[i]);
+			}
+
+			// prepare for next round
+			m_forceWriting = false;
+			m_lastMacroBlock = 0;
+		}
+		// re-initialize macro block
+		m_currentBlock = m_macroBlocks[m_lastMacroBlock++];
+		m_currentBlock->Init(lastLevelIndex);
+	}
 }
 
 ////////////////////////////////////////////////////////
 // Encode buffer of given size using bit plane coding.
 // A buffer contains bufferLen UINT32 values, thus, bufferSize bits per bit plane.
-// Following coding scheme is used: 
-//		Buffer		::= <nPlanes>(5 bits) foreach(plane i): Plane[i]  
+// Following coding scheme is used:
+//		Buffer		::= <nPlanes>(5 bits) foreach(plane i): Plane[i]
 //		Plane[i]	::= [ Sig1 | Sig2 ] [DWORD alignment] refBits
-//		Sig1		::= 1 <codeLen>(15 bits) codedSigAndSignBits 
-//		Sig2		::= 0 <sigLen>(15 bits) [Sign1 | Sign2 ] sigBits 
+//		Sig1		::= 1 <codeLen>(15 bits) codedSigAndSignBits
+//		Sig2		::= 0 <sigLen>(15 bits) [Sign1 | Sign2 ] sigBits
 //		Sign1		::= 1 <codeLen>(15 bits) [DWORD alignment] codedSignBits
 //		Sign2		::= 0 <signLen>(15 bits) [DWORD alignment] signBits
-// returns number of bits in m_codeBuffer
-UINT32 CEncoder::BitplaneEncode(UINT32 bufferSize) {
-	ASSERT(bufferSize <= BufferSize);
-	const UINT32 bufferLen = AlignWordPos(bufferSize)/WordWidth;
-
+void CEncoder::CMacroBlock::BitplaneEncode() {
 	UINT8	nPlanes;
-	UINT32	sigLen, codeLen = 0, codePos = 0, wordPos, refLen, signLen, k;
-	int     plane;
-	UINT32  sigBits[BufferLen];
-	UINT32  refBits[BufferLen];
-	UINT32  signBits[BufferLen];
+	UINT32	sigLen, codeLen = 0, wordPos, refLen, signLen;
+	UINT32  sigBits[BufferLen] = { 0 };
+	UINT32  refBits[BufferLen] = { 0 };
+	UINT32  signBits[BufferLen] = { 0 };
 	UINT32  planeMask;
+	UINT32	bufferSize = m_header.rbh.bufferSize; ASSERT(bufferSize <= BufferSize);
 	bool	useRL;
+	//const UINT32 bufferLen = NumberOfWords(m_bufferSize);
+
+#ifdef TRACE
+	//printf("which thread: %d\n", omp_get_thread_num());
+#endif
 
 	// clear significance vector
-	for (k=0; k < bufferLen; k++) {
-		m_sigFlagVector[k] = 0;
-	}
+	for (UINT32 k=0; k < bufferSize; k++) {
+		m_sigFlagVector[k] = false;
+	}
+	m_sigFlagVector[bufferSize] = true; // sentinel
+
+	// clear output buffer
+	for (UINT32 k=0; k < bufferSize; k++) {
+		m_codeBuffer[k] = 0;
+	}
+	m_codePos = 0;
 
 	// compute number of bit planes and split buffer into separate bit planes
 	nPlanes = NumberOfBitplanes();
 
 	// write number of bit planes to m_codeBuffer
 	SetValueBlock(m_codeBuffer, 0, nPlanes, MaxBitPlanesLog);
-	codePos += MaxBitPlanesLog;
+	m_codePos += MaxBitPlanesLog;
 
 	// loop through all bit planes
 	if (nPlanes == 0) nPlanes = MaxBitPlanes + 1;
 	planeMask = 1 << (nPlanes - 1);
 
-	for (plane = nPlanes - 1; plane >= 0; plane--) {
+	for (int plane = nPlanes - 1; plane >= 0; plane--) {
 		// clear significant bitset
-		for (k=0; k < bufferLen; k++) {
+		for (UINT32 k=0; k < BufferLen; k++) {
 			sigBits[k] = 0;
 		}
 
 		// split bitplane in significant bitset and refinement bitset
-		sigLen = DecomposeBitplane(bufferSize, planeMask, sigBits, refBits, signBits, signLen);
-
-		if (sigLen > 0) {
-			useRL = true;
-			// run-length encode significant bits and signs and append them to the m_codeBuffer
-			m_codePos = codePos + RLblockSizeLen + 1; 
-			codeLen = RLESigsAndSigns(sigBits, sigLen, signBits, signLen);
+		sigLen = DecomposeBitplane(bufferSize, planeMask, m_codePos + RLblockSizeLen + 1, sigBits, refBits, signBits, signLen, codeLen);
+
+		if (sigLen > 0 && codeLen <= MaxCodeLen && codeLen < AlignWordPos(sigLen) + AlignWordPos(signLen) + 2*RLblockSizeLen) {
+			// set RL code bit
+			SetBit(m_codeBuffer, m_codePos++);
+
+			// write length codeLen to m_codeBuffer
+			SetValueBlock(m_codeBuffer, m_codePos, codeLen, RLblockSizeLen);
+			m_codePos += RLblockSizeLen + codeLen;
 		} else {
-			useRL = false;
-		}
-
-		if (useRL && codeLen <= MaxCodeLen && codeLen < AlignWordPos(sigLen) + AlignWordPos(signLen) + 2*RLblockSizeLen) {
-			// set RL code bit
-			SetBit(m_codeBuffer, codePos);
-			codePos++;
-
-			// write length codeLen to m_codeBuffer
-			SetValueBlock(m_codeBuffer, codePos, codeLen, RLblockSizeLen);
-			codePos += RLblockSizeLen + codeLen;
-		} else {
-			#ifdef TRACE
-			printf("new\n");
-			for (UINT32 i=0; i < bufferSize; i++) {
-				printf("%s", (GetBit(sigBits, i)) ? "1" : "_");
-				if (i%120 == 119) printf("\n");
-			}
-			printf("\n");
-			#endif // TRACE
+		#ifdef TRACE
+			//printf("new\n");
+			//for (UINT32 i=0; i < bufferSize; i++) {
+			//	printf("%s", (GetBit(sigBits, i)) ? "1" : "_");
+			//	if (i%120 == 119) printf("\n");
+			//}
+			//printf("\n");
+		#endif // TRACE
 
 			// run-length coding wasn't efficient enough
 			// we don't use RL coding for sigBits
-			ClearBit(m_codeBuffer, codePos);
-			codePos++;
+			ClearBit(m_codeBuffer, m_codePos++);
 
 			// write length sigLen to m_codeBuffer
-			ASSERT(sigLen <= MaxCodeLen); 
-			SetValueBlock(m_codeBuffer, codePos, sigLen, RLblockSizeLen);
-			codePos += RLblockSizeLen;
-
-			// overwrite m_codeBuffer
-			if (signLen > 0) {
+			ASSERT(sigLen <= MaxCodeLen);
+			SetValueBlock(m_codeBuffer, m_codePos, sigLen, RLblockSizeLen);
+			m_codePos += RLblockSizeLen;
+
+			if (m_encoder->m_favorSpeed || signLen == 0) {
+				useRL = false;
+			} else {
+				// overwrite m_codeBuffer
 				useRL = true;
 				// run-length encode m_sign and append them to the m_codeBuffer
-				m_codePos = codePos + RLblockSizeLen + 1;
-				codeLen = RLESigns(signBits, signLen);
-			} else {
-				useRL = false;
+				codeLen = RLESigns(m_codePos + RLblockSizeLen + 1, signBits, signLen);
 			}
 
 			if (useRL && codeLen <= MaxCodeLen && codeLen < signLen) {
 				// RL encoding of m_sign was efficient
 				// write RL code bit
-				SetBit(m_codeBuffer, codePos);
-				codePos++;
-				
+				SetBit(m_codeBuffer, m_codePos++);
+
 				// write codeLen to m_codeBuffer
-				SetValueBlock(m_codeBuffer, codePos, codeLen, RLblockSizeLen);
-
-				// adjust code buffer position
-				codePos += codeLen + RLblockSizeLen;
-				codePos = AlignWordPos(codePos);
+				SetValueBlock(m_codeBuffer, m_codePos, codeLen, RLblockSizeLen);
 
 				// compute position of sigBits
-				wordPos = codePos >> WordWidthLog;
+				wordPos = NumberOfWords(m_codePos + codeLen + RLblockSizeLen);
 				ASSERT(0 <= wordPos && wordPos < BufferSize);
 			} else {
 				// RL encoding of signBits wasn't efficient
 				// clear RL code bit
-				ClearBit(m_codeBuffer, codePos);
-				codePos++;
+				ClearBit(m_codeBuffer, m_codePos++);
 
 				// write signLen to m_codeBuffer
-				ASSERT(signLen <= MaxCodeLen); 
-				SetValueBlock(m_codeBuffer, codePos, signLen, RLblockSizeLen);
-				codePos += RLblockSizeLen;
+				ASSERT(signLen <= MaxCodeLen);
+				SetValueBlock(m_codeBuffer, m_codePos, signLen, RLblockSizeLen);
 
 				// write signBits to m_codeBuffer
-				codePos = AlignWordPos(codePos);
-				wordPos = codePos >> WordWidthLog;
+				wordPos = NumberOfWords(m_codePos + RLblockSizeLen);
 				ASSERT(0 <= wordPos && wordPos < BufferSize);
-				codeLen = AlignWordPos(signLen) >> WordWidthLog;
-
-				for (k=0; k < codeLen; k++) {
-					m_codeBuffer[wordPos] = signBits[k];
-					wordPos++;
+				codeLen = NumberOfWords(signLen);
+
+				for (UINT32 k=0; k < codeLen; k++) {
+					m_codeBuffer[wordPos++] = signBits[k];
 				}
-				
+
 			}
 
 			// write sigBits
 			ASSERT(0 <= wordPos && wordPos < BufferSize);
-			refLen = AlignWordPos(sigLen) >> WordWidthLog;
-
-			for (k=0; k < refLen; k++) {
-				m_codeBuffer[wordPos] = sigBits[k];
-				wordPos++;
-			}
-			codePos = wordPos << WordWidthLog;
+			refLen = NumberOfWords(sigLen);
+
+			for (UINT32 k=0; k < refLen; k++) {
+				m_codeBuffer[wordPos++] = sigBits[k];
+			}
+			m_codePos = wordPos << WordWidthLog;
 		}
 
 		// append refinement bitset (aligned to word boundary)
-		codePos = AlignWordPos(codePos);
-		wordPos = codePos >> WordWidthLog;
+		wordPos = NumberOfWords(m_codePos);
 		ASSERT(0 <= wordPos && wordPos < BufferSize);
-		refLen = AlignWordPos(bufferSize - sigLen)/WordWidth;
-
-		for (k=0; k < refLen; k++) {
-			m_codeBuffer[wordPos] = refBits[k];
-			wordPos++;
-		}
-		codePos = wordPos << WordWidthLog;
+		refLen = NumberOfWords(bufferSize - sigLen);
+
+		for (UINT32 k=0; k < refLen; k++) {
+			m_codeBuffer[wordPos++] = refBits[k];
+		}
+		m_codePos = wordPos << WordWidthLog;
 		planeMask >>= 1;
 	}
-	ASSERT(0 <= codePos && codePos <= CodeBufferBitLen);
-	return codePos;
+	ASSERT(0 <= m_codePos && m_codePos <= CodeBufferBitLen);
 }
 
 //////////////////////////////////////////////////////////
 // Split bitplane of length bufferSize into significant and refinement bitset
 // returns length [bits] of significant bits
-// input:  m_value
-// output: sigBits, refBits, signBits, signLen [bits]
-UINT32 CEncoder::DecomposeBitplane(UINT32 bufferSize, UINT32 planeMask, UINT32* sigBits, UINT32* refBits, UINT32* signBits, UINT32& signLen) {
+// input:  bufferSize, planeMask, codePos
+// output: sigBits, refBits, signBits, signLen [bits], codeLen [bits]
+// RLE
+// - Encode run of 2^k zeros by a single 0.
+// - Encode run of count 0's followed by a 1 with codeword: 1<count>x
+// - x is 0: if a positive sign is stored, otherwise 1
+// - Store each bit in m_codeBuffer[codePos] and increment codePos.
+UINT32 CEncoder::CMacroBlock::DecomposeBitplane(UINT32 bufferSize, UINT32 planeMask, UINT32 codePos, UINT32* sigBits, UINT32* refBits, UINT32* signBits, UINT32& signLen, UINT32& codeLen) {
 	ASSERT(sigBits);
 	ASSERT(refBits);
 	ASSERT(signBits);
-
-	UINT32 sigRunLen;
+	ASSERT(codePos < CodeBufferBitLen);
+
 	UINT32 sigPos = 0;
 	UINT32 valuePos = 0, valueEnd;
 	UINT32 refPos = 0;
 
+	// set output value
 	signLen = 0;
 
+	// prepare RLE of Sigs and Signs
+	const UINT32 outStartPos = codePos;
+	UINT32 k = 3;
+	UINT32 runlen = 1 << k; // = 2^k
+	UINT32 count = 0;
+
 	while (valuePos < bufferSize) {
-		// search next 1 in m_sigFlagVector
-		sigRunLen = SeekBitRange(m_sigFlagVector, valuePos, bufferSize - valuePos);
-
-		// search 1's in m_value[plane][valuePos..valuePos+sigRunLen)
+		// search next 1 in m_sigFlagVector using searching with sentinel
+		valueEnd = valuePos;
+		while(!m_sigFlagVector[valueEnd]) { valueEnd++; }
+
+		// search 1's in m_value[plane][valuePos..valueEnd)
 		// these 1's are significant bits
-		valueEnd = valuePos + sigRunLen;
 		while (valuePos < valueEnd) {
-			// search 0's
-			while (valuePos < valueEnd && !GetBitAtPos(valuePos, planeMask)) {
-				valuePos++;
+			if (GetBitAtPos(valuePos, planeMask)) {
+				// RLE encoding
+				// encode run of count 0's followed by a 1
+				// with codeword: 1<count>(signBits[signPos])
+				SetBit(m_codeBuffer, codePos++);
+				if (k > 0) {
+					SetValueBlock(m_codeBuffer, codePos, count, k);
+					codePos += k;
+
+					// adapt k (half the zero run-length)
+					k--;
+					runlen >>= 1;
+				}
+
+				// copy and write sign bit
+				if (m_value[valuePos] < 0) {
+					SetBit(signBits, signLen++);
+					SetBit(m_codeBuffer, codePos++);
+				} else {
+					ClearBit(signBits, signLen++);
+					ClearBit(m_codeBuffer, codePos++);
+				}
+
+				// write a 1 to sigBits
+				SetBit(sigBits, sigPos++);
+
+				// update m_sigFlagVector
+				m_sigFlagVector[valuePos] = true;
+
+				// prepare for next run
+				count = 0;
+			} else {
+				// RLE encoding
+				count++;
+				if (count == runlen) {
+					// encode run of 2^k zeros by a single 0
+					ClearBit(m_codeBuffer, codePos++);
+					// adapt k (double the zero run-length)
+					if (k < WordWidth) {
+						k++;
+						runlen <<= 1;
+					}
+
+					// prepare for next run
+					count = 0;
+				}
+
 				// write 0 to sigBits
 				sigPos++;
 			}
-			if (valuePos < valueEnd) {
-				// write a 1 to sigBits
-				SetBit(sigBits, sigPos); 
-				sigPos++;
-
-				// copy the sign bit
-				if (m_value[valuePos] < 0) {
-					SetBit(signBits, signLen);
-				} else {
-					ClearBit(signBits, signLen);
-				}
-				signLen++;
-
-				// update m_sigFlagVector
-				SetBit(m_sigFlagVector, valuePos);
-				valuePos++;
-			}
+			valuePos++;
 		}
 		// refinement bit
 		if (valuePos < bufferSize) {
 			// write one refinement bit
-			if (GetBitAtPos(valuePos, planeMask)) {
+			if (GetBitAtPos(valuePos++, planeMask)) {
 				SetBit(refBits, refPos);
 			} else {
 				ClearBit(refBits, refPos);
 			}
 			refPos++;
-			valuePos++;
-		}
-	}
+		}
+	}
+	// RLE encoding of the rest of the plane
+	// encode run of count 0's followed by a 1
+	// with codeword: 1<count>(signBits[signPos])
+	SetBit(m_codeBuffer, codePos++);
+	if (k > 0) {
+		SetValueBlock(m_codeBuffer, codePos, count, k);
+		codePos += k;
+	}
+	// write dmmy sign bit
+	SetBit(m_codeBuffer, codePos++);
+
+	// write word filler zeros
 
 	ASSERT(sigPos <= bufferSize);
 	ASSERT(refPos <= bufferSize);
 	ASSERT(signLen <= bufferSize);
 	ASSERT(valuePos == bufferSize);
+	ASSERT(codePos >= outStartPos && codePos < CodeBufferBitLen);
+	codeLen = codePos - outStartPos;
 
 	return sigPos;
 }
@@ -561,7 +680,7 @@
 
 ///////////////////////////////////////////////////////
 // Compute number of bit planes needed
-UINT8 CEncoder::NumberOfBitplanes() {
+UINT8 CEncoder::CMacroBlock::NumberOfBitplanes() {
 	UINT8 cnt = 0;
 
 	// determine number of bitplanes for max value
@@ -579,84 +698,18 @@
 	}
 }
 
-////////////////////////////////////////////////////////
-// Adaptive run-Length encoder for significant bits with a lot of zeros and sign bits.
-// sigLen and signLen are in bits
-// Returns length of output in bits.
-// - Encode run of 2^k zeros by a single 0.
-// - Encode run of count 0's followed by a 1 with codeword: 1<count>x
-// - x is 0: if a positive sign is stored, otherwise 1
-// - Store each bit in m_codeBuffer[m_codePos] and increment m_codePos.
-UINT32 CEncoder::RLESigsAndSigns(UINT32* sigBits, UINT32 sigLen, UINT32* signBits, UINT32 signLen) {
-	ASSERT(sigBits);
-	ASSERT(signBits);
-	ASSERT(m_codePos < CodeBufferBitLen);
-	ASSERT(0 < sigLen && sigLen <= BufferSize);
-	ASSERT(signLen <= BufferSize);
-
-	const UINT32 outStartPos = m_codePos;
-
-	UINT32 k = 3;
-	UINT32 runlen = 1 << k; // = 2^k
-	UINT32 count = 0;
-	UINT32 sigPos = 0, signPos = 0;
-
-	while (sigPos < sigLen) {
-		// search next 1 in sigBits starting at position sigPos
-		count = SeekBitRange(sigBits, sigPos, __min(runlen, sigLen - sigPos));
-		// count 0's found
-		if (count == runlen) {
-			// encode run of 2^k zeros by a single 0
-			sigPos += count; 
-			ClearBit(m_codeBuffer, m_codePos); m_codePos++;
-			// adapt k (double the zero run-length)
-			if (k < WordWidth) {
-				k++;
-				runlen <<= 1;
-			}
-		} else {
-			// encode run of count 0's followed by a 1
-			// with codeword: 1<count>(signBits[signPos])
-			sigPos += count + 1;
-			SetBit(m_codeBuffer, m_codePos); 
-			m_codePos++;
-			if (k > 0) {
-				SetValueBlock(m_codeBuffer, m_codePos, count, k);
-				m_codePos += k;
-			}
-			// sign bit
-			if (GetBit(signBits, signPos)) {
-				SetBit(m_codeBuffer, m_codePos);
-			} else {
-				ClearBit(m_codeBuffer, m_codePos);
-			}
-			signPos++; m_codePos++;
-
-			// adapt k (half the zero run-length)
-			if (k > 0) {
-				k--; 
-				runlen >>= 1;
-			}
-		}
-	}
-	ASSERT(sigPos == sigLen || sigPos == sigLen + 1);
-	ASSERT(signPos == signLen || signPos == signLen + 1);
-	ASSERT(m_codePos >= outStartPos && m_codePos < CodeBufferBitLen);
-	return m_codePos - outStartPos;
-}
-
 //////////////////////////////////////////////////////
 // Adaptive Run-Length encoder for long sequences of ones.
 // Returns length of output in bits.
 // - Encode run of 2^k ones by a single 1.
 // - Encode run of count 1's followed by a 0 with codeword: 0<count>.
-// - Store each bit in m_codeBuffer[m_codePos] and increment m_codePos.
-UINT32 CEncoder::RLESigns(UINT32* signBits, UINT32 signLen) {
+// - Store each bit in m_codeBuffer[codePos] and increment codePos.
+UINT32 CEncoder::CMacroBlock::RLESigns(UINT32 codePos, UINT32* signBits, UINT32 signLen) {
 	ASSERT(signBits);
-	ASSERT(0 <= m_codePos && m_codePos < CodeBufferBitLen);
+	ASSERT(0 <= codePos && codePos < CodeBufferBitLen);
 	ASSERT(0 < signLen && signLen <= BufferSize);
-	
-	const UINT32  outStartPos = m_codePos;
+
+	const UINT32  outStartPos = codePos;
 	UINT32 k = 0;
 	UINT32 runlen = 1 << k; // = 2^k
 	UINT32 count = 0;
@@ -668,42 +721,42 @@
 		// count 1's found
 		if (count == runlen) {
 			// encode run of 2^k ones by a single 1
-			signPos += count; 
-			SetBit(m_codeBuffer, m_codePos); m_codePos++;
+			signPos += count;
+			SetBit(m_codeBuffer, codePos++);
 			// adapt k (double the 1's run-length)
 			if (k < WordWidth) {
-				k++; 
+				k++;
 				runlen <<= 1;
 			}
 		} else {
 			// encode run of count 1's followed by a 0
 			// with codeword: 0(count)
 			signPos += count + 1;
-			ClearBit(m_codeBuffer, m_codePos); m_codePos++;
+			ClearBit(m_codeBuffer, codePos++);
 			if (k > 0) {
-				SetValueBlock(m_codeBuffer, m_codePos, count, k);
-				m_codePos += k;
+				SetValueBlock(m_codeBuffer, codePos, count, k);
+				codePos += k;
 			}
 			// adapt k (half the 1's run-length)
 			if (k > 0) {
-				k--; 
+				k--;
 				runlen >>= 1;
 			}
 		}
 	}
 	ASSERT(signPos == signLen || signPos == signLen + 1);
-	ASSERT(m_codePos >= outStartPos && m_codePos < CodeBufferBitLen);
-	return m_codePos - outStartPos;
+	ASSERT(codePos >= outStartPos && codePos < CodeBufferBitLen);
+	return codePos - outStartPos;
 }
 
 //////////////////////////////////////////////////////
 #ifdef TRACE
 void CEncoder::DumpBuffer() const {
-	printf("\nDump\n");
-	for (UINT32 i=0; i < BufferSize; i++) {
-		printf("%d", m_value[i]);
-	}
-	printf("\n");
+	//printf("\nDump\n");
+	//for (UINT32 i=0; i < BufferSize; i++) {
+	//	printf("%d", m_value[i]);
+	//}
+	//printf("\n");
 }
 #endif //TRACE
 

Modified: trunk/Scribus/scribus/third_party/pgf/Encoder.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16771&path=/trunk/Scribus/scribus/third_party/pgf/Encoder.h
==============================================================================
--- trunk/Scribus/scribus/third_party/pgf/Encoder.h (original)
+++ trunk/Scribus/scribus/third_party/pgf/Encoder.h Mon Aug  8 18:19:05 2011
@@ -1,34 +1,38 @@
 /*
  * The Progressive Graphics File; http://www.libpgf.org
- * 
+ *
  * $Date: 2006-06-04 22:05:59 +0200 (So, 04 Jun 2006) $
  * $Revision: 229 $
- * 
+ *
  * This file Copyright (C) 2006 xeraina GmbH, Switzerland
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
  * as published by the Free Software Foundation; either version 2.1
  * of the License, or (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+//////////////////////////////////////////////////////////////////////
+/// @file Encoder.h
+/// @brief PGF encoder class
+/// @author C. Stamm, R. Spuler
+
 #ifndef PGF_ENCODER_H
 #define PGF_ENCODER_H
 
-#include "PGFtypes.h"
+#include "PGFstream.h"
 #include "BitStream.h"
 #include "Subband.h"
 #include "WaveletTransform.h"
-#include "Stream.h"
 
 /////////////////////////////////////////////////////////////////////
 // Constants
@@ -36,8 +40,49 @@
 
 /////////////////////////////////////////////////////////////////////
 /// PGF encoder class.
-/// @author C. Stamm, R. Spuler
+/// @author C. Stamm
+/// @brief PGF encoder
 class CEncoder {
+	//////////////////////////////////////////////////////////////////////
+	/// PGF encoder macro block class.
+	/// @author C. Stamm, I. Bauersachs
+	/// @brief A macro block is an encoding unit of fixed size (uncoded)
+	class CMacroBlock {
+	public:
+		CMacroBlock(CEncoder *encoder)
+		: m_header(0)
+        , m_encoder(encoder)
+		{
+			ASSERT(m_encoder);
+			Init(-1);
+		}
+
+		DataT	m_value[BufferSize];				// input buffer of values with index m_valuePos
+		UINT32	m_codeBuffer[BufferSize];			// output buffer for encoded bitstream
+
+		ROIBlockHeader m_header;					// block header
+		UINT32	m_valuePos;							// current buffer position
+		UINT32	m_maxAbsValue;						// maximum absolute coefficient in each buffer
+		UINT32	m_codePos;							// current position in encoded bitstream
+		int		m_lastLevelIndex;					// index of last encoded level: [0, nLevels); used because a level-end can occur before a buffer is full
+
+		void Init(int lastLevelIndex) {				// initialize for reusage
+			m_valuePos = 0;
+			m_maxAbsValue = 0;
+			m_codePos = 0;
+			m_lastLevelIndex = lastLevelIndex;
+		}
+		void BitplaneEncode();						// several macro blocks can be encoded in parallel
+	private:
+		UINT32 RLESigns(UINT32 codePos, UINT32* signBits, UINT32 signLen);
+		UINT32 DecomposeBitplane(UINT32 bufferSize, UINT32 planeMask, UINT32 codePos, UINT32* sigBits, UINT32* refBits, UINT32* signBits, UINT32& signLen, UINT32& codeLen);
+		UINT8  NumberOfBitplanes();
+		bool   GetBitAtPos(UINT32 pos, UINT32 planeMask) const	{ return (abs(m_value[pos]) & planeMask) > 0; }
+
+		CEncoder *m_encoder;						// encoder instance
+		bool	m_sigFlagVector[BufferSize+1];		// see paper from Malvar, Fast Progressive Wavelet Coder
+	};
+
 public:
 	/////////////////////////////////////////////////////////////////////
 	/// Write pre-header, header, postHeader, and levelLength.
@@ -47,17 +92,27 @@
 	/// @param header An already filled in PGF header
 	/// @param postHeader [in] A already filled in PGF post header (containing color table, user data, ...)
 	/// @param levelLength A reference to an integer array, large enough to save the relative file positions of all PGF levels
-	CEncoder(CPGFStream* stream, PGFPreHeader preHeader, PGFHeader header, const PGFPostHeader& postHeader, UINT32*& levelLength) THROW_; // throws IOException
+	/// @param useOMP If true, then the encoder will use multi-threading based on openMP
+	CEncoder(CPGFStream* stream, PGFPreHeader preHeader, PGFHeader header, const PGFPostHeader& postHeader, UINT32*& levelLength, bool useOMP = true) THROW_; // throws IOException
 
 	/////////////////////////////////////////////////////////////////////
 	/// Destructor
 	~CEncoder();
 
 	/////////////////////////////////////////////////////////////////////
-	/// Pad buffer with zeros, encode buffer, write levelLength into header
-	/// Return number of bytes written into stream
+	/// Encoder favors speed over compression size
+	void FavorSpeedOverSize() { m_favorSpeed = true; }
+
+	/////////////////////////////////////////////////////////////////////
+	/// Pad buffer with zeros and encode buffer.
 	/// It might throw an IOException.
-	UINT32 Flush() THROW_;
+	void Flush() THROW_;
+
+	/////////////////////////////////////////////////////////////////////
+	/// Write levelLength into header.
+	/// @return number of bytes written into stream
+	/// It might throw an IOException.
+	UINT32 WriteLevelLength() THROW_;
 
 	/////////////////////////////////////////////////////////////////////
 	/// Partitions a rectangular region of a given subband.
@@ -72,10 +127,9 @@
 	void Partition(CSubband* band, int width, int height, int startPos, int pitch) THROW_;
 
 	/////////////////////////////////////////////////////////////////////
-	/// Set or clear flag. The flag must be set to true as soon a wavelet
-	/// transform level is encoded.
-	/// @param b A flag value
-	void SetLevelIsEncoded(bool b) { m_isLevelEncoded = b; }
+	/// Informs the encoder about the encoded level.
+	/// @param currentLevel encoded level [0, nLevels)
+	void SetEncodedLevel(int currentLevel) { ASSERT(currentLevel >= 0); m_currentBlock->m_lastLevelIndex = m_nLevels - currentLevel - 1; m_forceWriting = true; }
 
 	/////////////////////////////////////////////////////////////////////
 	/// Write a single value into subband at given position.
@@ -84,11 +138,25 @@
 	/// @param bandPos A valid position in subband band
 	void WriteValue(CSubband* band, int bandPos) THROW_;
 
+	/////////////////////////////////////////////////////////////////////
+	/// Compute stream length of header.
+	/// @return header length
+	UINT32 ComputeHeaderLength() const { return UINT32(m_bufferStartPos - m_startPosition); }
+
+	/////////////////////////////////////////////////////////////////////
+	/// Compute stream length of encoded buffer.
+	/// @return encoded buffer length
+	UINT32 ComputeBufferLength() const { return UINT32(m_stream->GetPos() - m_bufferStartPos); }
+
+	/////////////////////////////////////////////////////////////////////
+	/// Save current stream position as beginning of current level.
+	void SetBufferStartPos() { m_bufferStartPos = m_stream->GetPos(); }
+
 #ifdef __PGFROISUPPORT__
 	/////////////////////////////////////////////////////////////////////
 	/// Encodes tile buffer and writes it into stream
 	/// It might throw an IOException.
-	void EncodeTileBuffer() THROW_	{ ASSERT(m_valuePos >= 0 && m_valuePos <= BufferSize); EncodeBuffer(ROIBlockHeader(m_valuePos, true)); }
+	void EncodeTileBuffer() THROW_	{ ASSERT(m_currentBlock && m_currentBlock->m_valuePos >= 0 && m_currentBlock->m_valuePos <= BufferSize); EncodeBuffer(ROIBlockHeader(m_currentBlock->m_valuePos, true)); }
 
 	/////////////////////////////////////////////////////////////////////
 	/// Enables region of interest (ROI) status.
@@ -100,32 +168,24 @@
 #endif
 
 private:
-	UINT32 BitplaneEncode(UINT32 bufferSize);
-	UINT32 RLESigsAndSigns(UINT32* sigBits, UINT32 sigLen, UINT32* signBits, UINT32 signLen);
-	UINT32 RLESigns(UINT32* signBits, UINT32 signLen);
-	UINT32 DecomposeBitplane(UINT32 bufferSize, UINT32 planeMask, UINT32* sigBits, UINT32* refBits, UINT32* signBits, UINT32& signLen);
-	UINT8 NumberOfBitplanes();
-	bool  GetBitAtPos(UINT32 pos, UINT32 planeMask) const	{ return (abs(m_value[pos]) & planeMask) > 0; }	
-	void  EncodeBuffer(ROIBlockHeader h) THROW_; // throws IOException
+	void EncodeBuffer(ROIBlockHeader h) THROW_; // throws IOException
+	void WriteMacroBlock(CMacroBlock* block) THROW_; // throws IOException
 
-protected:
 	CPGFStream *m_stream;
 	UINT64	m_startPosition;					// file position of PGF start (PreHeader)
 	UINT64  m_levelLengthPos;					// file position of Metadata
-	UINT64  m_currPosition;						// Already accumulated size from lower levels
-	
-	DataT	m_value[BufferSize];				// buffer of values with index m_valuePos
-	UINT32	m_codeBuffer[BufferSize];			// buffer for encoded bitstream
+	UINT64  m_bufferStartPos;					// file position of encoded buffer
 
-	UINT32	m_sigFlagVector[BufferLen];			// see paper from Malvar, Fast Progressive Wavelet Coder
-
-	UINT32	m_valuePos;							// current buffer position
-	UINT32	m_codePos;							// current bit position in m_codeBuffer
-	UINT32	m_maxAbsValue;						// maximum absolute coefficient in each buffer
+	CMacroBlock **m_macroBlocks;				// array of macroblocks
+	int		m_macroBlockLen;					// array length
+	int		m_lastMacroBlock;					// array index of the last created macro block
+	CMacroBlock *m_currentBlock;				// current macro block (used by main thread)
 
 	UINT32* m_levelLength;						// temporary saves the level index
 	int     m_currLevelIndex;					// counts where (=index) to save next value
-	bool    m_isLevelEncoded;					// Already enough data available to set level-block-size
+	UINT8	m_nLevels;							// number of levels
+	bool	m_favorSpeed;						// favor speed over size
+	bool	m_forceWriting;						// all macro blocks have to be written into the stream
 #ifdef __PGFROISUPPORT__
 	bool	m_roi;								// true: ensures region of interest (ROI) encoding
 #endif

Modified: trunk/Scribus/scribus/third_party/pgf/PGFimage.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16771&path=/trunk/Scribus/scribus/third_party/pgf/PGFimage.cpp
==============================================================================
--- trunk/Scribus/scribus/third_party/pgf/PGFimage.cpp (original)
+++ trunk/Scribus/scribus/third_party/pgf/PGFimage.cpp Mon Aug  8 18:19:05 2011
@@ -1,30 +1,36 @@
 /*
  * The Progressive Graphics File; http://www.libpgf.org
- * 
+ *
  * $Date: 2007-02-03 13:04:21 +0100 (Sa, 03 Feb 2007) $
  * $Revision: 280 $
- * 
+ *
  * This file Copyright (C) 2006 xeraina GmbH, Switzerland
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
  * as published by the Free Software Foundation; either version 2.1
  * of the License, or (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+//////////////////////////////////////////////////////////////////////
+/// @file PGFimage.cpp
+/// @brief PGF image class implementation
+/// @author C. Stamm
+
 #include "PGFimage.h"
 #include "Decoder.h"
 #include "Encoder.h"
 #include <cmath>
+#include <cstring>
 
 #define YUVoffset4		8				// 2^3
 #define YUVoffset6		32				// 2^5
@@ -47,8 +53,21 @@
 
 //////////////////////////////////////////////////////////////////////
 // Standard constructor: It is used to create a PGF instance for opening and reading.
-CPGFImage::CPGFImage() 
-: m_decoder(0), m_levelLength(0), m_quant(0), m_downsample(false), m_cb(0), m_cbArg(0)
+CPGFImage::CPGFImage()
+: m_decoder(0)
+, m_encoder(0)
+, m_levelLength(0)
+, m_quant(0)
+, m_downsample(false)
+, m_favorSpeedOverSize(false)
+, m_useOMPinEncoder(true)
+, m_useOMPinDecoder(true)
+#ifdef __PGFROISUPPORT__
+, m_levelwise(true)
+, m_streamReinitialized(false)
+#endif
+, m_cb(0)
+, m_cbArg(0)
 {
 
 	// init preHeader
@@ -89,6 +108,7 @@
 	}
 	delete[] m_postHeader.userData; m_postHeader.userData = 0; m_postHeader.userDataLen = 0;
 	delete[] m_levelLength; m_levelLength = 0;
+	delete m_encoder; m_encoder = NULL;
 }
 
 //////////////////////////////////////////////////////////////////////
@@ -106,19 +126,12 @@
 void CPGFImage::Open(CPGFStream *stream) THROW_ {
 	ASSERT(stream);
 
-	m_decoder = new CDecoder(stream, m_preHeader, m_header, m_postHeader, m_levelLength);
+	m_decoder = new CDecoder(stream, m_preHeader, m_header, m_postHeader, m_levelLength, m_useOMPinDecoder);
 	if (!m_decoder) ReturnWithError(InsufficientMemory);
+	ASSERT(m_decoder);
 
 	if (m_header.nLevels > MaxLevel) ReturnWithError(FormatCannotRead);
 
-	Init();
-
-	ASSERT(m_decoder);
-}
-
-////////////////////////////////////////////////////////////
-// Initialize an open pgf file
-void CPGFImage::Init() THROW_ {
 	// set current level
 	m_currentLevel = m_header.nLevels;
 
@@ -126,7 +139,64 @@
 	m_width[0] = m_header.width;
 	m_height[0] = m_header.height;
 
-	// set or correct image mode
+	// complete header
+	CompleteHeader();
+
+	// interpret quant parameter
+	if (m_header.quality > DownsampleThreshold &&
+		(m_header.mode == ImageModeRGBColor ||
+		 m_header.mode == ImageModeRGBA ||
+		 m_header.mode == ImageModeRGB48 ||
+		 m_header.mode == ImageModeCMYKColor ||
+		 m_header.mode == ImageModeCMYK64 ||
+		 m_header.mode == ImageModeLabColor ||
+		 m_header.mode == ImageModeLab48)) {
+		m_downsample = true;
+		m_quant = m_header.quality - 1;
+	} else {
+		m_downsample = false;
+		m_quant = m_header.quality;
+	}
+
+	// set channel dimensions (chrominance is subsampled by factor 2)
+	if (m_downsample) {
+		for (int i=1; i < m_header.channels; i++) {
+			m_width[i] = (m_width[0] + 1)/2;
+			m_height[i] = (m_height[0] + 1)/2;
+		}
+	} else {
+		for (int i=1; i < m_header.channels; i++) {
+			m_width[i] = m_width[0];
+			m_height[i] = m_height[0];
+		}
+	}
+
+	if (m_header.nLevels > 0) {
+		// init wavelet subbands
+		for (int i=0; i < m_header.channels; i++) {
+			m_wtChannel[i] = new CWaveletTransform(m_width[i], m_height[i], m_header.nLevels);
+			if (!m_wtChannel[i]) ReturnWithError(InsufficientMemory);
+		}
+	} else {
+		// very small image: we don't use DWT and encoding
+
+		// read channels
+		for (int c=0; c < m_header.channels; c++) {
+			const UINT32 size = m_width[c]*m_height[c];
+			m_channel[c] = new DataT[size];
+
+			// read channel data from stream
+			for (UINT32 i=0; i < size; i++) {
+				int count = DataTSize;
+				stream->Read(&count, &m_channel[c][i]);
+				if (count != DataTSize) ReturnWithError(MissingData);
+			}
+		}
+	}
+}
+
+////////////////////////////////////////////////////////////
+void CPGFImage::CompleteHeader() {
 	if (m_header.mode == ImageModeUnknown) {
 		// undefined mode
 		switch(m_header.bpp) {
@@ -139,7 +209,48 @@
 		case 48: m_header.mode = ImageModeRGB48; break;
 		default: m_header.mode = ImageModeRGBColor; break;
 		}
-	} else if (m_header.mode == ImageModeRGBColor && m_header.bpp == 32) {
+	}
+	if (!m_header.bpp) {
+		// undefined bpp
+		switch(m_header.mode) {
+		case ImageModeBitmap:
+			m_header.bpp = 1;
+			break;
+		case ImageModeIndexedColor:
+		case ImageModeGrayScale:
+			m_header.bpp = 8;
+			break;
+		case ImageModeRGB12:
+			m_header.bpp = 12;
+			break;
+		case ImageModeRGB16:
+		case ImageModeGray16:
+			m_header.bpp = 16;
+			break;
+		case ImageModeRGBColor:
+		case ImageModeLabColor:
+			m_header.bpp = 24;
+			break;
+		case ImageModeRGBA:
+		case ImageModeCMYKColor:
+	#ifdef __PGF32SUPPORT__
+		case ImageModeGray31:
+	#endif
+			m_header.bpp = 32;
+			break;
+		case ImageModeRGB48:
+		case ImageModeLab48:
+			m_header.bpp = 48;
+			break;
+		case ImageModeCMYK64:
+			m_header.bpp = 64;
+			break;
+		default:
+			ASSERT(false);
+			m_header.bpp = 24;
+		}
+	}
+	if (m_header.mode == ImageModeRGBColor && m_header.bpp == 32) {
 		// change mode
 		m_header.mode = ImageModeRGBA;
 	}
@@ -159,12 +270,14 @@
 	// set number of channels
 	if (!m_header.channels) {
 		switch(m_header.mode) {
-		case ImageModeBitmap: 
+		case ImageModeBitmap:
 		case ImageModeIndexedColor:
 		case ImageModeGrayScale:
 		case ImageModeGray16:
+	#ifdef __PGF32SUPPORT__
 		case ImageModeGray31:
-			m_header.channels = 1; 
+	#endif
+			m_header.channels = 1;
 			break;
 		case ImageModeRGBColor:
 		case ImageModeRGB12:
@@ -179,53 +292,11 @@
 		case ImageModeCMYK64:
 			m_header.channels = 4;
 			break;
-		}
-	}
-
-	// interprete quant parameter
-	if (m_header.quality > DownsampleThreshold && 
-		(m_header.mode == ImageModeRGBColor || 
-		 m_header.mode == ImageModeRGBA || 
-		 m_header.mode == ImageModeRGB48 || 
-		 m_header.mode == ImageModeCMYKColor || 
-		 m_header.mode == ImageModeCMYK64 || 
-		 m_header.mode == ImageModeLabColor || 
-		 m_header.mode == ImageModeLab48)) {
-		m_downsample = true;
-		m_quant = m_header.quality - 1;
-	} else {
-		m_downsample = false;
-		m_quant = m_header.quality;
-	}
-
-	// set channel dimensions (chrominance is subsampled by factor 2)
-	if (m_downsample) {
-		for (int i=1; i < m_header.channels; i++) {
-			m_width[i] = (m_width[0] + 1)/2;
-			m_height[i] = (m_height[0] + 1)/2;
-		}
-	} else {
-		for (int i=1; i < m_header.channels; i++) {
-			m_width[i] = m_width[0];
-			m_height[i] = m_height[0];
-		}
-	}
-
-	// init wavelet subbands
-	for (int i=0; i < m_header.channels; i++) {
-		m_wtChannel[i] = new CWaveletTransform(m_width[i], m_height[i], m_header.nLevels);
-		if (!m_wtChannel[i]) ReturnWithError(InsufficientMemory);
-	}
-
-	// set background
-	/*
-	if (m_header.mode == ImageModeRGBA &&
-		(m_header.background.rgbtBlue != DefaultBGColor ||
-		m_header.background.rgbtGreen != DefaultBGColor ||
-		m_header.background.rgbtRed != DefaultBGColor)) {
-		m_backgroundSet = true;
-	}
-	*/
+		default:
+			ASSERT(false);
+			m_header.channels = 3;
+		}
+	}
 }
 
 //////////////////////////////////////////////////////////////////////
@@ -235,6 +306,49 @@
 const UINT8* CPGFImage::GetUserData(UINT32& size) const {
 	size = m_postHeader.userDataLen;
 	return m_postHeader.userData;
+}
+
+//////////////////////////////////////////////////////////////////////
+/// After you've written a PGF image, you can call this method followed by GetBitmap/GetYUV
+/// to get a quick reconstruction (coded -> decoded image).
+/// @param level The image level of the resulting image in the internal image buffer.
+void CPGFImage::Reconstruct(int level /*= 0*/) {
+	if (m_header.nLevels == 0) {
+		// image didn't use wavelet transform
+		if (level == 0) {
+			for (int i=0; i < m_header.channels; i++) {
+				ASSERT(m_wtChannel[i]);
+				m_channel[i] = m_wtChannel[i]->GetSubband(0, LL)->GetBuffer();
+			}
+		}
+	} else {
+		int currentLevel = m_header.nLevels;
+
+		if (ROIisSupported()) {
+			// enable ROI reading
+			SetROI(PGFRect(0, 0, m_header.width, m_header.height));
+		}
+
+		while (currentLevel > level) {
+			for (int i=0; i < m_header.channels; i++) {
+				ASSERT(m_wtChannel[i]);
+				// dequantize subbands
+				if (currentLevel == m_header.nLevels) {
+					// last level also has LL band
+					m_wtChannel[i]->GetSubband(currentLevel, LL)->Dequantize(m_quant);
+				}
+				m_wtChannel[i]->GetSubband(currentLevel, HL)->Dequantize(m_quant);
+				m_wtChannel[i]->GetSubband(currentLevel, LH)->Dequantize(m_quant);
+				m_wtChannel[i]->GetSubband(currentLevel, HH)->Dequantize(m_quant);
+
+				// inverse transform from m_wtChannel to m_channel
+				m_wtChannel[i]->InverseTransform(currentLevel, &m_width[i], &m_height[i], &m_channel[i]);
+				ASSERT(m_channel[i]);
+			}
+
+			currentLevel--;
+		}
+	}
 }
 
 //////////////////////////////////////////////////////////////////////
@@ -252,7 +366,6 @@
 void CPGFImage::Read(int level /*= 0*/, CallbackPtr cb /*= NULL*/, void *data /*=NULL*/) THROW_ {
 	ASSERT((level >= 0 && level < m_header.nLevels) || m_header.nLevels == 0); // m_header.nLevels == 0: image didn't use wavelet transform
 	ASSERT(m_decoder);
-	int i;
 
 #ifdef __PGFROISUPPORT__
 	if (ROIisSupported() && m_header.nLevels > 0) {
@@ -264,24 +377,23 @@
 #endif
 
 	if (m_header.nLevels == 0) {
-		// image didn't use wavelet transform
-		for (i=0; i < m_header.channels; i++) {
-			ASSERT(m_wtChannel[i]);
-			// decode file and write stream to m_channel
-			m_wtChannel[i]->GetSubband(0, LL)->PlaceTile(*m_decoder, m_quant);
-			m_channel[i] = m_wtChannel[i]->GetSubband(0, LL)->GetBuffer();
+		if (level == 0) {
+			// the data has already been read during open
+			// now update progress
+			if (cb) {
+				if ((*cb)(1.0, true, data)) ReturnWithError(EscapePressed);
+			}
 		}
 	} else {
 		const int levelDiff = m_currentLevel - level;
-		double p, percent = pow(0.25, levelDiff);
+		double percent = pow(0.25, levelDiff);
 
 		// encoding scheme without ROI
 		while (m_currentLevel > level) {
-			p = percent;
-			for (i=0; i < m_header.channels; i++) {
+			for (int i=0; i < m_header.channels; i++) {
 				ASSERT(m_wtChannel[i]);
 				// decode file and write stream to m_wtChannel
-				if (m_currentLevel == m_header.nLevels) { 
+				if (m_currentLevel == m_header.nLevels) {
 					// last level also has LL band
 					m_wtChannel[i]->GetSubband(m_currentLevel, LL)->PlaceTile(*m_decoder, m_quant);
 				}
@@ -294,17 +406,15 @@
 					m_decoder->DecodeInterleaved(m_wtChannel[i], m_currentLevel, m_quant);
 				}
 				m_wtChannel[i]->GetSubband(m_currentLevel, HH)->PlaceTile(*m_decoder, m_quant);
-
+			}
+
+			#pragma omp parallel for default(shared)
+			for (int i=0; i < m_header.channels; i++) {
 				// inverse transform from m_wtChannel to m_channel
 				m_wtChannel[i]->InverseTransform(m_currentLevel, &m_width[i], &m_height[i], &m_channel[i]);
 				ASSERT(m_channel[i]);
-
-				// now update progress
-				if (i < m_header.channels - 1 && cb) {
-					percent += 3*p/m_header.channels;
-					(*cb)(percent, false, data);
-				}
-			}
+			}
+
 			// set new level: must be done before refresh callback
 			m_currentLevel--;
 
@@ -313,96 +423,17 @@
 
 			// now update progress
 			if (cb) {
-				percent += 3*p/m_header.channels;
+				percent += 3*percent;
 				if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
 			}
 		}
 	}
-}
-
-//////////////////////////////////////////////////////////////////////
-/// After you've written a PGF image, you can call this method followed by GetBitmap/GetYUV
-/// to get a quick reconstruction (coded -> decoded image).
-void CPGFImage::Reconstruct() THROW_ {
-	int i;
-
-	if (m_header.nLevels == 0) {
-		// image didn't use wavelet transform
-		for (i=0; i < m_header.channels; i++) {
-			ASSERT(m_wtChannel[i]);
-			m_channel[i] = m_wtChannel[i]->GetSubband(0, LL)->GetBuffer();
-		}
-	} else {
-		int currentLevel = m_header.nLevels;
-
-		// old encoding scheme without ROI
-		while (currentLevel > 0) {
-			for (i=0; i < m_header.channels; i++) {
-				ASSERT(m_wtChannel[i]);
-				// dequantize subbands
-				if (currentLevel == m_header.nLevels) { 
-					// last level also has LL band
-					m_wtChannel[i]->GetSubband(currentLevel, LL)->Dequantize(m_quant, currentLevel);
-				}
-				m_wtChannel[i]->GetSubband(currentLevel, HL)->Dequantize(m_quant, currentLevel);
-				m_wtChannel[i]->GetSubband(currentLevel, LH)->Dequantize(m_quant, currentLevel);
-				m_wtChannel[i]->GetSubband(currentLevel, HH)->Dequantize(m_quant, currentLevel);
-
-				// inverse transform from m_wtChannel to m_channel
-				m_wtChannel[i]->InverseTransform(currentLevel, &m_width[i], &m_height[i], &m_channel[i]);
-				ASSERT(m_channel[i]);
-			}
-			// now we have to refresh the display
-			if (m_cb) m_cb(m_cbArg);
-
-			currentLevel--;
-		}
-	}
+
+	// automatically closing
+	if (m_currentLevel == 0) Close();
 }
 
 #ifdef __PGFROISUPPORT__
-//////////////////////////////////////////////////////////////////////
-/// Compute ROIs for each channel and each level
-/// @param rect rectangular region of interest (ROI)
-void CPGFImage::SetROI(PGFRect rect) {
-	ASSERT(m_decoder);
-	ASSERT(ROIisSupported());
-
-	// store ROI for a later call of GetBitmap
-	m_roi = rect;
-
-	// enable ROI decoding
-	m_decoder->SetROI();
-
-	// enlarge ROI because of border artefacts
-	const UINT32 dx = FilterWidth/2*(1 << m_currentLevel);
-	const UINT32 dy = FilterHeight/2*(1 << m_currentLevel);
-
-	if (rect.left < dx) rect.left = 0;
-	else rect.left -= dx;
-	if (rect.top < dy) rect.top = 0;
-	else rect.top -= dy;
-	rect.right += dx;
-	if (rect.right > m_header.width) rect.right = m_header.width;
-	rect.bottom += dy;
-	if (rect.bottom > m_header.height) rect.bottom = m_header.height;
-
-	// prepare wavelet channels for using ROI
-	ASSERT(m_wtChannel[0]);
-	m_wtChannel[0]->SetROI(rect);
-	if (m_downsample && m_header.channels > 1) {
-		// all further channels are downsampled, therefore downsample ROI
-		rect.left >>= 1;
-		rect.top >>= 1;
-		rect.right >>= 1;
-		rect.bottom >>= 1;
-	}
-	for (int i=1; i < m_header.channels; i++) {
-		ASSERT(m_wtChannel[i]);
-		m_wtChannel[i]->SetROI(rect);
-	}
-}
-
 //////////////////////////////////////////////////////////////////////
 /// 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.
@@ -415,7 +446,6 @@
 void CPGFImage::Read(PGFRect& rect, int level /*= 0*/, CallbackPtr cb /*= NULL*/, void *data /*=NULL*/) THROW_ {
 	ASSERT((level >= 0 && level < m_header.nLevels) || m_header.nLevels == 0); // m_header.nLevels == 0: image didn't use wavelet transform
 	ASSERT(m_decoder);
-	int i;
 
 	if (m_header.nLevels == 0 || !ROIisSupported()) {
 		rect.left = rect.top = 0;
@@ -426,8 +456,8 @@
 		// new encoding scheme supporting ROI
 		ASSERT(rect.left < m_header.width && rect.top < m_header.height);
 		const int levelDiff = m_currentLevel - level;
-		double p, percent = pow(0.25, levelDiff);
-		
+		double percent = pow(0.25, levelDiff);
+
 		// check level difference
 		if (levelDiff <= 0) {
 			// it is a new read call, probably with a new ROI
@@ -438,13 +468,12 @@
 		// check rectangle
 		if (rect.right == 0 || rect.right > m_header.width) rect.right = m_header.width;
 		if (rect.bottom == 0 || rect.bottom > m_header.height) rect.bottom = m_header.height;
-		
+
 		// enable ROI decoding and reading
 		SetROI(rect);
 
 		while (m_currentLevel > level) {
-			p = percent;
-			for (i=0; i < m_header.channels; i++) {
+			for (int i=0; i < m_header.channels; i++) {
 				ASSERT(m_wtChannel[i]);
 
 				// get number of tiles and tile indices
@@ -471,17 +500,15 @@
 						}
 					}
 				}
-
+			}
+
+			#pragma omp parallel for default(shared)
+			for (int i=0; i < m_header.channels; i++) {
 				// inverse transform from m_wtChannel to m_channel
 				m_wtChannel[i]->InverseTransform(m_currentLevel, &m_width[i], &m_height[i], &m_channel[i]);
 				ASSERT(m_channel[i]);
-
-				// now update progress
-				if (i < m_header.channels - 1 && cb) {
-					percent += 3*p/m_header.channels;
-					(*cb)(percent, false, data);
-				}
-			}
+			}
+
 			// set new level: must be done before refresh callback
 			m_currentLevel--;
 
@@ -490,20 +517,67 @@
 
 			// now update progress
 			if (cb) {
-				percent += 3*p/m_header.channels;
+				percent += 3*percent;
 				if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
 			}
 		}
 	}
-}
-#endif
+
+	// automatically closing
+	if (m_currentLevel == 0) Close();
+}
+
+//////////////////////////////////////////////////////////////////////
+/// Compute ROIs for each channel and each level
+/// @param rect rectangular region of interest (ROI)
+void CPGFImage::SetROI(PGFRect rect) {
+	ASSERT(m_decoder);
+	ASSERT(ROIisSupported());
+
+	// store ROI for a later call of GetBitmap
+	m_roi = rect;
+
+	// enable ROI decoding
+	m_decoder->SetROI();
+
+	// enlarge ROI because of border artefacts
+	const UINT32 dx = FilterWidth/2*(1 << m_currentLevel);
+	const UINT32 dy = FilterHeight/2*(1 << m_currentLevel);
+
+	if (rect.left < dx) rect.left = 0;
+	else rect.left -= dx;
+	if (rect.top < dy) rect.top = 0;
+	else rect.top -= dy;
+	rect.right += dx;
+	if (rect.right > m_header.width) rect.right = m_header.width;
+	rect.bottom += dy;
+	if (rect.bottom > m_header.height) rect.bottom = m_header.height;
+
+	// prepare wavelet channels for using ROI
+	ASSERT(m_wtChannel[0]);
+	m_wtChannel[0]->SetROI(rect);
+	if (m_downsample && m_header.channels > 1) {
+		// all further channels are downsampled, therefore downsample ROI
+		rect.left >>= 1;
+		rect.top >>= 1;
+		rect.right >>= 1;
+		rect.bottom >>= 1;
+	}
+	for (int i=1; i < m_header.channels; i++) {
+		ASSERT(m_wtChannel[i]);
+		m_wtChannel[i]->SetROI(rect);
+	}
+}
+
+#endif // __PGFROISUPPORT__
 
 //////////////////////////////////////////////////////////////////////
 /// Return the length of all encoded headers in bytes.
+/// Precondition: The PGF image has been opened with a call of Open(...).
 /// @return The length of all encoded headers in bytes
-UINT32 CPGFImage::GetEncodedHeaderLength() const { 
-	ASSERT(m_decoder); 
-	return m_decoder->GetEncodedHeaderLength(); 
+UINT32 CPGFImage::GetEncodedHeaderLength() const {
+	ASSERT(m_decoder);
+	return m_decoder->GetEncodedHeaderLength();
 }
 
 //////////////////////////////////////////////////////////////////////
@@ -532,14 +606,14 @@
 }
 
 ////////////////////////////////////////////////////////////////////
-/// Reset stream position to beginning of PGF pre header
+/// Reset stream position to start of PGF pre-header
 void CPGFImage::ResetStreamPos() THROW_ {
 	ASSERT(m_decoder);
-	return m_decoder->SetStreamPosToStart(); 
+	return m_decoder->SetStreamPosToStart();
 }
 
 //////////////////////////////////////////////////////////////////////
-/// Reads the data of an encoded PGF level and copies it to a target buffer 
+/// 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.
@@ -577,82 +651,15 @@
 //////////////////////////////////////////////////////////////////
 // Set background of an RGB image with transparency channel or reset to default background.
 // @param bg A pointer to a background color or NULL (reset to default background)
-void CPGFImage::SetBackground(const RGBTRIPLE* bg) { 
-	if (bg) { 
-		m_header.background = *bg; 
-//		m_backgroundSet = true; 
+void CPGFImage::SetBackground(const RGBTRIPLE* bg) {
+	if (bg) {
+		m_header.background = *bg;
+//		m_backgroundSet = true;
 	} else {
 		m_header.background.rgbtBlue = DefaultBGColor;
 		m_header.background.rgbtGreen = DefaultBGColor;
 		m_header.background.rgbtRed = DefaultBGColor;
 //		m_backgroundSet = false;
-	}
-}
-
-//////////////////////////////////////////////////////////////////////
-/// 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.
-/// @param header A valid and already filled in PGF header structure
-/// @param flags A combination of additional version flags
-/// @param userData A user-defined memory block
-/// @param userDataLength The size of user-defined memory block in bytes
-void CPGFImage::SetHeader(const PGFHeader& header, BYTE flags /*=0*/, UINT8* userData /*= 0*/, UINT32 userDataLength /*= 0*/) THROW_ {
-	ASSERT(!m_decoder);	// current image must be closed
-	ASSERT(header.quality <= MaxQuality);
-	int i;
-
-	// init preHeader
-	memcpy(m_preHeader.magic, Magic, 3);
-	m_preHeader.version = PGFVersion | flags;
-	m_preHeader.hSize = HeaderSize;
-
-	// copy header
-	memcpy(&m_header, &header, HeaderSize);
-
-	// misuse background value to store bits per channel
-	BYTE bpc = m_header.bpp/m_header.channels;
-	if (bpc > 8) {
-		if (bpc > 31) bpc = 31;
-		m_header.background.rgbtBlue = bpc;
-	}
-
-	// check for downsample
-	if (m_header.quality > DownsampleThreshold &&  (m_header.mode == ImageModeRGBColor || 
-													m_header.mode == ImageModeRGBA || 
-													m_header.mode == ImageModeRGB48 || 
-													m_header.mode == ImageModeCMYKColor || 
-													m_header.mode == ImageModeCMYK64 || 
-													m_header.mode == ImageModeLabColor || 
-													m_header.mode == ImageModeLab48)) {
-		m_downsample = true;
-		m_quant = m_header.quality - 1;
-	} else {
-		m_downsample = false;
-		m_quant = m_header.quality;
-	}
-
-	// update header size and copy user data
-	if (m_header.mode == ImageModeIndexedColor) {
-		m_preHeader.hSize += ColorTableSize;
-	}
-	if (userDataLength && userData) {
-		m_postHeader.userData = new UINT8[userDataLength];
-		m_postHeader.userDataLen = userDataLength;
-		memcpy(m_postHeader.userData, userData, userDataLength);
-		m_preHeader.hSize += userDataLength;
-	}
-
-	// allocate channels
-	for (i=0; i < m_header.channels; i++) {
-		// set current width and height
-		m_width[i] = m_header.width;
-		m_height[i] = m_header.height;
-
-		// allocate channels
-		ASSERT(!m_channel[i]);
-		m_channel[i] = new DataT[m_header.width*m_header.height];
-		if (!m_channel[i]) ReturnWithError(InsufficientMemory);
 	}
 }
 
@@ -680,6 +687,7 @@
 	BYTE bpc = m_header.bpp/m_header.channels;
 
 	if (bpc > 8) {
+		// see also GetMaxValue()
 		return m_header.background.rgbtBlue;
 	} else {
 		return bpc;
@@ -749,7 +757,7 @@
 			loPos += 2; hiPos += 2;
 			sampledPos++;
 		}
-		if (oddW) { 
+		if (oddW) {
 			buff[sampledPos] = (buff[loPos] + buff[hiPos]) >> 1;
 			loPos++; hiPos++;
 			sampledPos++;
@@ -773,27 +781,21 @@
 }
 
 //////////////////////////////////////////////////////////////////////
-/// Compute and return number of levels. During PGF::Write the return
-/// value of this method is used in case the parameter levels is not a
-/// positive value. 
-/// 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.
-/// @param width Original image width
-/// @param height Original image height
-/// @return Number of PGF levels
-BYTE CPGFImage::ComputeLevels(UINT32 width, UINT32 height) {
+void CPGFImage::ComputeLevels() {
 	const int maxThumbnailWidth = 20*FilterWidth;
-	const int m = __min(width, height);
-	int s = m, levels = 1;
-
-	// compute a good value depending on the size of the image
-	while (s > maxThumbnailWidth) {
-		levels++;
-		s = s/2;
-	}
+	const int m = __min(m_header.width, m_header.height);
+	int s = m;
+
+	if (m_header.nLevels < 1 || m_header.nLevels > MaxLevel) {
+		m_header.nLevels = 1;
+		// compute a good value depending on the size of the image
+		while (s > maxThumbnailWidth) {
+			m_header.nLevels++;
+			s = s/2;
+		}
+	}
+
+	int levels = m_header.nLevels; // we need a signed value during level reduction
 
 	// reduce number of levels if the image size is smaller than FilterWidth*2^levels
 	s = FilterWidth*(1 << levels);	// must be at least the double filter size because of subsampling
@@ -801,11 +803,248 @@
 		levels--;
 		s = s/2;
 	}
-	if (levels > MaxLevel) levels = MaxLevel;
-	if (levels < 0) levels = 0;
-	ASSERT(0 <= levels && levels <= MaxLevel);
-	
-	return (BYTE)levels;
+	if (levels > MaxLevel) m_header.nLevels = MaxLevel;
+	else if (levels < 0) m_header.nLevels = 0;
+	else m_header.nLevels = (UINT8)levels;
+
+	ASSERT(0 <= m_header.nLevels && m_header.nLevels <= MaxLevel);
+}
+
+//////////////////////////////////////////////////////////////////////
+/// 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.
+/// @param header A valid and already filled in PGF header structure
+/// @param flags A combination of additional version flags
+/// @param userData A user-defined memory block
+/// @param userDataLength The size of user-defined memory block in bytes
+void CPGFImage::SetHeader(const PGFHeader& header, BYTE flags /*=0*/, UINT8* userData /*= 0*/, UINT32 userDataLength /*= 0*/) THROW_ {
+	ASSERT(!m_decoder);	// current image must be closed
+	ASSERT(header.quality <= MaxQuality);
+	int i;
+
+	// init state
+#ifdef __PGFROISUPPORT__
+	m_levelwise = true;
+	m_streamReinitialized = false;
+#endif
+
+	// init preHeader
+	memcpy(m_preHeader.magic, Magic, 3);
+	m_preHeader.version = PGFVersion | flags;
+	m_preHeader.hSize = HeaderSize;
+
+	// copy header
+	memcpy(&m_header, &header, HeaderSize);
+
+	// complete header
+	CompleteHeader();
+
+	// check and set number of levels
+	ComputeLevels();
+
+	// misuse background value to store bits per channel
+	BYTE bpc = m_header.bpp/m_header.channels;
+	if (bpc > 8) {
+		if (bpc > 31) bpc = 31;
+		m_header.background.rgbtBlue = bpc;
+	}
+
+	// check for downsample
+	if (m_header.quality > DownsampleThreshold &&  (m_header.mode == ImageModeRGBColor ||
+													m_header.mode == ImageModeRGBA ||
+													m_header.mode == ImageModeRGB48 ||
+													m_header.mode == ImageModeCMYKColor ||
+													m_header.mode == ImageModeCMYK64 ||
+													m_header.mode == ImageModeLabColor ||
+													m_header.mode == ImageModeLab48)) {
+		m_downsample = true;
+		m_quant = m_header.quality - 1;
+	} else {
+		m_downsample = false;
+		m_quant = m_header.quality;
+	}
+
+	// update header size and copy user data
+	if (m_header.mode == ImageModeIndexedColor) {
+		m_preHeader.hSize += ColorTableSize;
+	}
+	if (userDataLength && userData) {
+		m_postHeader.userData = new UINT8[userDataLength];
+		m_postHeader.userDataLen = userDataLength;
+		memcpy(m_postHeader.userData, userData, userDataLength);
+		m_preHeader.hSize += userDataLength;
+	}
+
+	// allocate channels
+	for (i=0; i < m_header.channels; i++) {
+		// set current width and height
+		m_width[i] = m_header.width;
+		m_height[i] = m_header.height;
+
+		// allocate channels
+		ASSERT(!m_channel[i]);
+		m_channel[i] = new DataT[m_header.width*m_header.height];
+		if (!m_channel[i]) ReturnWithError(InsufficientMemory);
+	}
+}
+
+//////////////////////////////////////////////////////////////////
+// Create wavelet transform channels and encoder.
+// Call this method before your first call of Write(int level), but after SetHeader().
+// Don't use this method when you call Write().
+// It might throw an IOException.
+// @param stream A PGF stream
+// @return The number of bytes written into stream.
+UINT32 CPGFImage::WriteHeader(CPGFStream* stream) THROW_ {
+	ASSERT(m_header.nLevels <= MaxLevel);
+	ASSERT(m_header.quality <= MaxQuality); // quality is already initialized
+
+	if (m_header.nLevels > 0) {
+		volatile OSError error = NoError; // volatile prevents optimizations
+		// create new wt channels
+		#pragma omp parallel for default(shared)
+		for (int i=0; i < m_header.channels; i++) {
+			DataT *temp = NULL;
+			if (error == NoError) {
+				if (m_wtChannel[i]) {
+					ASSERT(m_channel[i]);
+					// copy m_channel to temp
+					int size = m_height[i]*m_width[i];
+					temp = new DataT[size];
+					if (temp) {
+						memcpy(temp, m_channel[i], size*DataTSize);
+						delete m_wtChannel[i];	// also deletes m_channel
+					} else {
+						error = InsufficientMemory;
+					}
+				}
+				if (temp) m_channel[i] = temp;
+				m_wtChannel[i] = new CWaveletTransform(m_width[i], m_height[i], m_header.nLevels, m_channel[i]);
+				if (m_wtChannel[i]) {
+					// wavelet subband decomposition
+					for (int l=0; l < m_header.nLevels; l++) {
+						m_wtChannel[i]->ForwardTransform(l);
+					}
+				} else {
+					delete temp;
+					error = InsufficientMemory;
+				}
+			}
+		}
+		if (error != NoError) ReturnWithError(error);
+
+		m_currentLevel = m_header.nLevels;
+
+	#ifdef __PGFROISUPPORT__
+		if (m_levelwise) {
+			m_preHeader.version |= PGFROI;
+		}
+	#endif
+
+		// create encoder and eventually write headers and levelLength
+		m_encoder = new CEncoder(stream, m_preHeader, m_header, m_postHeader, m_levelLength, m_useOMPinEncoder);
+		if (m_favorSpeedOverSize) m_encoder->FavorSpeedOverSize();
+
+	#ifdef __PGFROISUPPORT__
+		if (ROIisSupported()) {
+			// new encoding scheme supporting ROI
+			m_encoder->SetROI();
+		}
+	#endif
+
+		// return number of written bytes
+		return m_encoder->ComputeHeaderLength();
+
+	} else {
+		// very small image: we don't use DWT and encoding
+
+		// create encoder and eventually write headers and levelLength
+		m_encoder = new CEncoder(stream, m_preHeader, m_header, m_postHeader, m_levelLength, m_useOMPinEncoder);
+
+		// write channels
+		for (int c=0; c < m_header.channels; c++) {
+			const UINT32 size = m_width[c]*m_height[c];
+
+			// write channel data into stream
+			for (UINT32 i=0; i < size; i++) {
+				int count = DataTSize;
+				stream->Write(&count, &m_channel[c][i]);
+			}
+		}
+
+		// write level lengths
+		UINT32 nBytes = m_encoder->WriteLevelLength(); // return written bytes inclusive header
+
+		// delete encoder
+		delete m_encoder; m_encoder = NULL;
+
+		// return number of written bytes
+		return nBytes;
+	}
+}
+
+//////////////////////////////////////////////////////////////////
+// Encode and write next level 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.
+// It might throw an IOException.
+void CPGFImage::WriteLevel() THROW_ {
+	ASSERT(m_encoder);
+	ASSERT(m_currentLevel > 0);
+	ASSERT(m_header.nLevels > 0);
+
+#ifdef __PGFROISUPPORT__
+	if (ROIisSupported()) {
+		const int lastChannel = m_header.channels - 1;
+
+		for (int i=0; i < m_header.channels; i++) {
+			m_wtChannel[i]->SetROI();
+
+			// get number of tiles and tile indices
+			const UINT32 nTiles = m_wtChannel[i]->GetNofTiles(m_currentLevel);
+			const UINT32 lastTile = nTiles - 1;
+
+			if (m_currentLevel == m_header.nLevels) {
+				// last level also has LL band
+				ASSERT(nTiles == 1);
+				m_wtChannel[i]->GetSubband(m_currentLevel, LL)->ExtractTile(*m_encoder, m_quant);
+				m_encoder->EncodeTileBuffer();
+			}
+			for (UINT32 tileY=0; tileY < nTiles; tileY++) {
+				for (UINT32 tileX=0; tileX < nTiles; tileX++) {
+					m_wtChannel[i]->GetSubband(m_currentLevel, HL)->ExtractTile(*m_encoder, m_quant, true, tileX, tileY);
+					m_wtChannel[i]->GetSubband(m_currentLevel, LH)->ExtractTile(*m_encoder, m_quant, true, tileX, tileY);
+					m_wtChannel[i]->GetSubband(m_currentLevel, HH)->ExtractTile(*m_encoder, m_quant, true, tileX, tileY);
+					if (i == lastChannel && tileY == lastTile && tileX == lastTile) {
+						// all necessary data are buffered. next call of EncodeBuffer will write the last piece of data of the current level.
+						m_encoder->SetEncodedLevel(--m_currentLevel);
+					}
+					m_encoder->EncodeTileBuffer();
+				}
+			}
+		}
+	} else
+#endif
+	{
+		for (int i=0; i < m_header.channels; i++) {
+			ASSERT(m_wtChannel[i]);
+			if (m_currentLevel == m_header.nLevels) {
+				// last level also has LL band
+				m_wtChannel[i]->GetSubband(m_currentLevel, LL)->ExtractTile(*m_encoder, m_quant);
+			}
+			//encoder.EncodeInterleaved(m_wtChannel[i], m_currentLevel, m_quant); // until version 4
+			m_wtChannel[i]->GetSubband(m_currentLevel, HL)->ExtractTile(*m_encoder, m_quant); // since version 5
+			m_wtChannel[i]->GetSubband(m_currentLevel, LH)->ExtractTile(*m_encoder, m_quant); // since version 5
+			m_wtChannel[i]->GetSubband(m_currentLevel, HH)->ExtractTile(*m_encoder, m_quant);
+		}
+
+		// all necessary data are buffered. next call of EncodeBuffer will write the last piece of data of the current level.
+		m_encoder->SetEncodedLevel(--m_currentLevel);
+	}
 }
 
 //////////////////////////////////////////////////////////////////
@@ -818,148 +1057,129 @@
 // Precondition: the PGF image contains a valid header (see also SetHeader(...)).
 // It might throw an IOException.
 // @param stream A PGF stream
-// @param levels The positive number of levels used in layering or 0 meaning a useful number of levels is computed.
-// @param cb A pointer to a callback procedure. The procedure is called after reading a single level. If cb returns true, then it stops proceeding.
 // @param nWrittenBytes [in-out] The number of bytes written into stream are added to the input value.
+// @param cb A pointer to a callback procedure. The procedure is called after writing a single level. If cb returns true, then it stops proceeding.
 // @param data Data Pointer to C++ class container to host callback procedure.
-void CPGFImage::Write(CPGFStream* stream, int levels /* = 0*/, CallbackPtr cb /*= NULL*/, UINT32* nWrittenBytes /*= NULL*/, void *data /*=NULL*/) THROW_ {
+void CPGFImage::Write(CPGFStream* stream, UINT32* nWrittenBytes /*= NULL*/, CallbackPtr cb /*= NULL*/, void *data /*=NULL*/) THROW_ {
 	ASSERT(stream);
 	ASSERT(m_preHeader.hSize);
-	int i;
-	UINT32 nBytes = 0;
-	DataT *temp;
-
-	// check and set number of levels
-	if (levels < 1) {
-		levels = m_header.nLevels = ComputeLevels(m_header.width, m_header.height);
+
+#ifdef __PGFROISUPPORT__
+	// don't use level-wise writing
+	m_levelwise = false;
+#endif
+
+	// create wavelet transform channels and encoder
+	WriteHeader(stream);
+
+	int levels = m_header.nLevels;
+	double percent = pow(0.25, levels - 1);
+
+	if (levels == 0) {
+		// data has been written in WriteHeader
+		// now update progress
+		if (cb) {
+			if ((*cb)(1, true, data)) ReturnWithError(EscapePressed);
+		}
 	} else {
-		if (levels > MaxLevel) levels = MaxLevel;
-		m_header.nLevels = levels;
-	}
-	ASSERT(m_header.nLevels <= MaxLevel);
-	ASSERT(m_header.quality <= MaxQuality); // quality is already initialized
-
-	// create new wt channels
-	for (i=0; i < m_header.channels; i++) {
-		temp = NULL;
-		if (m_wtChannel[i]) {
-			ASSERT(m_channel[i]);
-			// copy m_channel to temp
-			int size = m_height[i]*m_width[i];
-			temp = new DataT[size]; 
-			if (!temp) ReturnWithError(InsufficientMemory);
-			memcpy(temp, m_channel[i], size*sizeof(INT16));
-			delete m_wtChannel[i];	// also deletes m_channel
-		}
-		if (temp) m_channel[i] = temp;
-		m_wtChannel[i] = new CWaveletTransform(m_width[i], m_height[i], levels, m_channel[i]);
-		if (!m_wtChannel[i]) {
-			delete temp;
-			ReturnWithError(InsufficientMemory);
-		}
-
-		// wavelet subband decomposition 
-		for (m_currentLevel=0; m_currentLevel < levels; m_currentLevel++) {
-			m_wtChannel[i]->ForwardTransform(m_currentLevel);
-		}
-	}
-	double percent = pow(0.25, levels - 1);
-
-	// open encoder and eventually write headers and levelLength
-	CEncoder encoder(stream, m_preHeader, m_header, m_postHeader, m_levelLength);
-
-	if (levels > 0) {
 		// encode quantized wavelet coefficients and write to PGF file
 		// encode subbands, higher levels first
 		// color channels are interleaved
 
+		// encode all levels
+		for (m_currentLevel = levels; m_currentLevel > 0; ) {
+			WriteLevel(); // decrements m_currentLevel
+
+			// now update progress
+			if (cb) {
+				percent *= 4;
+				if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
+			}
+		}
+
+		// flush encoder and write level lengths
+		m_encoder->Flush();
+		UINT32 nBytes = m_encoder->WriteLevelLength(); // inclusive header
+
+		// delete encoder
+		delete m_encoder; m_encoder = NULL;
+
+		// return written bytes
+		if (nWrittenBytes) *nWrittenBytes += nBytes;
+	}
+
+	ASSERT(!m_encoder);
+}
+
 #ifdef __PGFROISUPPORT__
-		if (ROIisSupported()) {
-			// new encoding scheme supporting ROI
-			encoder.SetROI();
-
-			for (m_currentLevel = (UINT8)levels; m_currentLevel > 0; m_currentLevel--) {
-				for (i=0; i < m_header.channels; i++) {
-					m_wtChannel[i]->SetROI();
-
-					// get number of tiles and tile indices
-					const UINT32 nTiles = m_wtChannel[i]->GetNofTiles(m_currentLevel);
-
-					if (m_currentLevel == levels) {
-						ASSERT(nTiles == 1);
-						m_wtChannel[i]->GetSubband(m_currentLevel, LL)->ExtractTile(encoder, m_quant);
-						encoder.EncodeTileBuffer();
-					}
-					for (UINT32 tileY=0; tileY < nTiles; tileY++) {
-						for (UINT32 tileX=0; tileX < nTiles; tileX++) {
-							m_wtChannel[i]->GetSubband(m_currentLevel, HL)->ExtractTile(encoder, m_quant, true, tileX, tileY);
-							m_wtChannel[i]->GetSubband(m_currentLevel, LH)->ExtractTile(encoder, m_quant, true, tileX, tileY);
-							m_wtChannel[i]->GetSubband(m_currentLevel, HH)->ExtractTile(encoder, m_quant, true, tileX, tileY);
-							encoder.EncodeTileBuffer();
-						}
-					}
-				}
-
-				// all necessary data of a level is buffered!
-				encoder.SetLevelIsEncoded(true);
-
-				// now update progress
-				if (cb) {
-					percent *= 4;
-					if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
-				}
-			}
-		} else 
-#endif
-		{
-			// encoding scheme without ROI
-			m_currentLevel = (UINT8)levels;
-			for (i=0; i < m_header.channels; i++) {
-				m_wtChannel[i]->GetSubband(m_currentLevel, LL)->ExtractTile(encoder, m_quant);
-				//encoder.EncodeInterleaved(m_wtChannel[i], m_currentLevel, m_quant); // until version 4
-				m_wtChannel[i]->GetSubband(m_currentLevel, HL)->ExtractTile(encoder, m_quant); // since version 5
-				m_wtChannel[i]->GetSubband(m_currentLevel, LH)->ExtractTile(encoder, m_quant); // since version 5
-				m_wtChannel[i]->GetSubband(m_currentLevel, HH)->ExtractTile(encoder, m_quant);
-			}
-			// all necessary data buffered!
-			encoder.SetLevelIsEncoded(true);
-			m_currentLevel--;
-
-			for (; m_currentLevel > 0; m_currentLevel--) {
-				for (i=0; i < m_header.channels; i++) {
-					//encoder.EncodeInterleaved(m_wtChannel[i], m_currentLevel, m_quant); // until version 4
-					m_wtChannel[i]->GetSubband(m_currentLevel, HL)->ExtractTile(encoder, m_quant); // since version 5
-					m_wtChannel[i]->GetSubband(m_currentLevel, LH)->ExtractTile(encoder, m_quant); // since version 5
-					m_wtChannel[i]->GetSubband(m_currentLevel, HH)->ExtractTile(encoder, m_quant);
-				}
-				// all necessary data of a level buffered!
-				encoder.SetLevelIsEncoded(true);
-
-				// now update progress
-				if (cb) {
-					percent *= 4;
-					if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
-				}
-			}
-		}
-	} else {
-		// write untransformed m_channel
-		for (i=0; i < m_header.channels; i++) {
-			m_wtChannel[i]->GetSubband(0, LL)->ExtractTile(encoder, m_quant);
-		}
-	}
-	
-	// flush encoder
-	nBytes = encoder.Flush();
-	if (nWrittenBytes) *nWrittenBytes += nBytes;
-}
+//////////////////////////////////////////////////////////////////
+// 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.
+// Precondition: the PGF image contains a valid header (see also SetHeader(...)) and WriteHeader() has been called before Write().
+// The ROI encoding scheme is used.
+// It might throw an IOException.
+// @param level The image level of the resulting image in the internal image buffer.
+// @param cb A pointer to a callback procedure. The procedure is called after writing a single level. If cb returns true, then it stops proceeding.
+// @param data Data Pointer to C++ class container to host callback procedure.
+// @return The number of bytes written into stream.
+UINT32 CPGFImage::Write(int level, CallbackPtr cb /*= NULL*/, void *data /*=NULL*/) THROW_ {
+	ASSERT(m_header.nLevels > 0);
+	ASSERT(0 <= level && level < m_header.nLevels);
+	ASSERT(m_encoder);
+	ASSERT(ROIisSupported());
+
+	// prepare for next level: save current file position, because the stream might have been reinitialized
+	UINT32 diff = m_encoder->ComputeBufferLength();
+	if (diff) {
+		m_streamReinitialized = true;
+		m_encoder->SetBufferStartPos();
+	}
+
+	const int levelDiff = m_currentLevel - level;
+	double percent = pow(0.25, levelDiff);
+	UINT32 nWrittenBytes = 0;
+	int levelIndex = m_header.nLevels - 1 - m_currentLevel;
+
+	// encoding scheme with ROI
+	while (m_currentLevel > level) {
+		levelIndex++;
+
+		WriteLevel();
+
+		if (m_levelLength) nWrittenBytes += m_levelLength[levelIndex];
+
+		// now update progress
+		if (cb) {
+			percent *= 4;
+			if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
+		}
+	}
+
+	// automatically closing
+	if (m_currentLevel == 0) {
+		if (!m_streamReinitialized) {
+			// don't write level lengths, if the stream position changed inbetween two Write operations
+			m_encoder->WriteLevelLength();
+		}
+		// delete encoder
+		delete m_encoder; m_encoder = NULL;
+	}
+
+	return nWrittenBytes;
+}
+#endif // __PGFROISUPPORT__
+
 
 //////////////////////////////////////////////////////////////////
 // Check for valid import image mode.
 // @param mode Image mode
 // @return True if an image of given mode can be imported with ImportBitmap(...)
 bool CPGFImage::ImportIsSupported(BYTE mode) {
-	size_t size = sizeof(DataT);
+	size_t size = DataTSize;
 
 	if (size >= 2) {
 		switch(mode) {
@@ -1057,7 +1277,7 @@
 			ASSERT(m_header.channels == 1);
 			ASSERT(m_header.bpp == 1);
 			ASSERT(bpp == 1);
-			
+
 			const UINT32 w2 = (m_header.width + 7)/8;
 			DataT* y = m_channel[0]; ASSERT(y);
 
@@ -1070,7 +1290,7 @@
 				for (UINT32 w=0; w < w2; w++) {
 					y[yPos++] = buff[w] - YUVoffset8;
 				}
-				buff += pitch;	
+				buff += pitch;
 			}
 		}
 		break;
@@ -1099,7 +1319,7 @@
 					cnt += channels;
 					yPos++;
 				}
-				buff += pitch;	
+				buff += pitch;
 			}
 		}
 		break;
@@ -1113,7 +1333,7 @@
 			UINT16 *buff16 = (UINT16 *)buff;
 			const int pitch16 = pitch/2;
 			const int channels = bpp/16; ASSERT(channels >= m_header.channels);
-			const int yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
+			const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
 
 			for (UINT32 h=0; h < m_header.height; h++) {
 				if (cb) {
@@ -1164,7 +1384,7 @@
 					cnt += channels;
 				}
 				buff += pitch;
-			}	
+			}
 		}
 		break;
 	case ImageModeRGB48:
@@ -1176,7 +1396,7 @@
 			UINT16 *buff16 = (UINT16 *)buff;
 			const int pitch16 = pitch/2;
 			const int channels = bpp/16; ASSERT(channels >= m_header.channels);
-			const int yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
+			const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
 
 			DataT* y = m_channel[0]; ASSERT(y);
 			DataT* u = m_channel[1]; ASSERT(u);
@@ -1202,7 +1422,7 @@
 					cnt += channels;
 				}
 				buff16 += pitch16;
-			}	
+			}
 		}
 		break;
 	case ImageModeRGBA:
@@ -1238,7 +1458,7 @@
 					cnt += channels;
 				}
 				buff += pitch;
-			}	
+			}
 		}
 		break;
 	case ImageModeCMYK64:
@@ -1250,8 +1470,8 @@
 			UINT16 *buff16 = (UINT16 *)buff;
 			const int pitch16 = pitch/2;
 			const int channels = bpp/16; ASSERT(channels >= m_header.channels);
-			const int yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
-			
+			const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
+
 			DataT* y = m_channel[0]; ASSERT(y);
 			DataT* u = m_channel[1]; ASSERT(u);
 			DataT* v = m_channel[2]; ASSERT(v);
@@ -1277,20 +1497,22 @@
 					cnt += channels;
 				}
 				buff16 += pitch16;
-			}	
+			}
 		}
 		break;
+#ifdef __PGF32SUPPORT__
 	case ImageModeGray31:
 		{
 			ASSERT(m_header.channels == 1);
 			ASSERT(m_header.bpp == 32);
 			ASSERT(bpp == 32);
+			ASSERT(DataTSize == sizeof(UINT32));
 
 			DataT* y = m_channel[0]; ASSERT(y);
 
 			UINT32 *buff32 = (UINT32 *)buff;
 			const int pitch32 = pitch/4;
-			const int yuvOffset31 = 1 << (UsedBitsPerChannel() - 1);
+			const DataT yuvOffset31 = 1 << (UsedBitsPerChannel() - 1);
 
 			for (UINT32 h=0; h < m_header.height; h++) {
 				if (cb) {
@@ -1306,6 +1528,7 @@
 			}
 		}
 		break;
+#endif
 	case ImageModeRGB12:
 		{
 			ASSERT(m_header.channels == 3);
@@ -1351,7 +1574,7 @@
 					yPos++;
 				}
 				buff += pitch;
-			}	
+			}
 		}
 		break;
 	case ImageModeRGB16:
@@ -1359,7 +1582,7 @@
 			ASSERT(m_header.channels == 3);
 			ASSERT(m_header.bpp == 16);
 			ASSERT(bpp == 16);
-			
+
 			DataT* y = m_channel[0]; ASSERT(y);
 			DataT* u = m_channel[1]; ASSERT(u);
 			DataT* v = m_channel[2]; ASSERT(v);
@@ -1374,7 +1597,7 @@
 					percent += dP;
 				}
 				for (UINT32 w=0; w < m_header.width; w++) {
-					rgb = buff16[w]; 
+					rgb = buff16[w];
 					r = (rgb & 0xF800) >> 10;	// highest 5 bits
 					g = (rgb & 0x07E0) >> 5;	// middle 6 bits
 					b = (rgb & 0x001F) << 1;	// lowest 5 bits
@@ -1386,7 +1609,7 @@
 				}
 
 				buff16 += pitch16;
-			}	
+			}
 		}
 		break;
 	default:
@@ -1396,7 +1619,7 @@
 
 //////////////////////////////////////////////////////////////////
 // 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 
+// 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).
@@ -1423,8 +1646,8 @@
 	const PGFRect& roi = (ROIisSupported()) ? m_wtChannel[0]->GetROI(m_currentLevel) : PGFRect(0, 0, w, h); // roi is usually larger than m_roi
 	const PGFRect levelRoi(LevelWidth(m_roi.left, m_currentLevel), LevelHeight(m_roi.top, m_currentLevel), LevelWidth(m_roi.Width(), m_currentLevel), LevelHeight(m_roi.Height(), m_currentLevel));
 	ASSERT(w == roi.Width() && h == roi.Height());
-	ASSERT(roi.left <= levelRoi.left && levelRoi.right <= roi.right); 
-	ASSERT(roi.top <= levelRoi.top && levelRoi.bottom <= roi.bottom); 
+	ASSERT(roi.left <= levelRoi.left && levelRoi.right <= roi.right);
+	ASSERT(roi.top <= levelRoi.top && levelRoi.bottom <= roi.bottom);
 
 	if (ROIisSupported() && (levelRoi.Width() < w || levelRoi.Height() < h)) {
 		// ROI is used -> create a temporary image buffer for roi
@@ -1505,7 +1728,7 @@
 			ASSERT(m_header.channels >= 1);
 			ASSERT(m_header.bpp == m_header.channels*16);
 
-			const int yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
+			const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
 			const int shift = UsedBitsPerChannel() - 8;
 			int cnt, channels;
 
@@ -1533,12 +1756,12 @@
 			} else {
 				ASSERT(bpp%8 == 0);
 				channels = bpp/8; ASSERT(channels >= m_header.channels);
-				
+
 				for (i=0; i < h; i++) {
 					cnt = 0;
 					for (j=0; j < w; j++) {
 						for (int c=0; c < m_header.channels; c++) {
-							buff[cnt + channelMap[c]] = Clamp16(m_channel[c][yPos] + yuvOffset16) >> shift;
+							buff[cnt + channelMap[c]] = UINT8(Clamp16(m_channel[c][yPos] + yuvOffset16) >> shift);
 						}
 						cnt += channels;
 						yPos++;
@@ -1564,8 +1787,8 @@
 			DataT* u = m_channel[1]; ASSERT(u);
 			DataT* v = m_channel[2]; ASSERT(v);
 			UINT8 *buffg = &buff[channelMap[1]],
-				*buffu = &buff[channelMap[2]],
-				*buffv = &buff[channelMap[0]];
+				  *buffr = &buff[channelMap[2]],
+				  *buffb = &buff[channelMap[0]];
 			UINT8 g;
 			int cnt, channels = bpp/8;
 			if(m_downsample){
@@ -1578,15 +1801,15 @@
 						vAvg = v[sampledPos];
 						// Yuv
 						buffg[cnt] = g = Clamp(y[yPos] + YUVoffset8 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
-						buffu[cnt] = Clamp(uAvg + g);
-						buffv[cnt] = Clamp(vAvg + g);
+						buffr[cnt] = Clamp(uAvg + g);
+						buffb[cnt] = Clamp(vAvg + g);
 						yPos++;
 						cnt += channels;
 						if (j%2) sampledPos++;
 					}
+					buffb += pitch;
 					buffg += pitch;
-					buffu += pitch;
-					buffv += pitch;
+					buffr += pitch;
 					if (wOdd) sampledPos++;
 					if (cb) {
 						percent += dP;
@@ -1601,14 +1824,14 @@
 						vAvg = v[yPos];
 						// Yuv
 						buffg[cnt] = g = Clamp(y[yPos] + YUVoffset8 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
-						buffu[cnt] = Clamp(uAvg + g);
-						buffv[cnt] = Clamp(vAvg + g);
+						buffr[cnt] = Clamp(uAvg + g);
+						buffb[cnt] = Clamp(vAvg + g);
 						yPos++;
 						cnt += channels;
 					}
+					buffb += pitch;
 					buffg += pitch;
-					buffu += pitch;
-					buffv += pitch;
+					buffr += pitch;
 
 					if (cb) {
 						percent += dP;
@@ -1623,7 +1846,7 @@
 			ASSERT(m_header.channels == 3);
 			ASSERT(m_header.bpp == 48);
 
-			const int yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
+			const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
 			const int shift = UsedBitsPerChannel() - 8;
 
 			DataT* y = m_channel[0]; ASSERT(y);
@@ -1653,7 +1876,7 @@
 						buff16[cnt + channelMap[1]] = g = Clamp16(y[yPos] + yuvOffset16 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
 						buff16[cnt + channelMap[2]] = Clamp16(uAvg + g);
 						buff16[cnt + channelMap[0]] = Clamp16(vAvg + g);
-						yPos++; 
+						yPos++;
 						cnt += channels;
 						if (j%2) sampledPos++;
 					}
@@ -1683,10 +1906,10 @@
 						}
 						// Yuv
 						g = Clamp16(y[yPos] + yuvOffset16 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
-						buff[cnt + channelMap[1]] = g >> shift; 
-						buff[cnt + channelMap[2]] = Clamp16(uAvg + g) >> shift;
-						buff[cnt + channelMap[0]] = Clamp16(vAvg + g) >> shift;
-						yPos++; 
+						buff[cnt + channelMap[1]] = UINT8(g >> shift);
+						buff[cnt + channelMap[2]] = UINT8(Clamp16(uAvg + g) >> shift);
+						buff[cnt + channelMap[0]] = UINT8(Clamp16(vAvg + g) >> shift);
+						yPos++;
 						cnt += channels;
 						if (j%2) sampledPos++;
 					}
@@ -1725,7 +1948,7 @@
 						vAvg = b[yPos];
 					}
 					buff[cnt + channelMap[0]] = Clamp(l[yPos] + YUVoffset8);
-					buff[cnt + channelMap[1]] = Clamp(uAvg + YUVoffset8); 
+					buff[cnt + channelMap[1]] = Clamp(uAvg + YUVoffset8);
 					buff[cnt + channelMap[2]] = Clamp(vAvg + YUVoffset8);
 					cnt += channels;
 					yPos++;
@@ -1746,7 +1969,7 @@
 			ASSERT(m_header.channels == 3);
 			ASSERT(m_header.bpp == m_header.channels*16);
 
-			const int yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
+			const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
 			const int shift = UsedBitsPerChannel() - 8;
 
 			DataT* l = m_channel[0]; ASSERT(l);
@@ -1802,9 +2025,9 @@
 							uAvg = a[yPos];
 							vAvg = b[yPos];
 						}
-						buff[cnt + channelMap[0]] = Clamp16(l[yPos] + yuvOffset16) >> shift;
-						buff[cnt + channelMap[1]] = Clamp16(uAvg + yuvOffset16) >> shift;
-						buff[cnt + channelMap[2]] = Clamp16(vAvg + yuvOffset16) >> shift;
+						buff[cnt + channelMap[0]] = UINT8(Clamp16(l[yPos] + yuvOffset16) >> shift);
+						buff[cnt + channelMap[1]] = UINT8(Clamp16(uAvg + yuvOffset16) >> shift);
+						buff[cnt + channelMap[2]] = UINT8(Clamp16(vAvg + yuvOffset16) >> shift);
 						cnt += channels;
 						yPos++;
 						if (j%2) sampledPos++;
@@ -1853,7 +2076,7 @@
 					buff[cnt + channelMap[2]] = Clamp(uAvg + g);
 					buff[cnt + channelMap[0]] = Clamp(vAvg + g);
 					buff[cnt + channelMap[3]] = aAvg;
-					yPos++; 
+					yPos++;
 					cnt += channels;
 					if (j%2) sampledPos++;
 				}
@@ -1867,12 +2090,12 @@
 			}
 			break;
 		}
-	case ImageModeCMYK64: 
+	case ImageModeCMYK64:
 		{
 			ASSERT(m_header.channels == 4);
 			ASSERT(m_header.bpp == 64);
 
-			const int yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
+			const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
 			const int shift = UsedBitsPerChannel() - 8;
 
 			DataT* y = m_channel[0]; ASSERT(y);
@@ -1906,7 +2129,7 @@
 						buff16[cnt + channelMap[2]] = Clamp16(uAvg + g);
 						buff16[cnt + channelMap[0]] = Clamp16(vAvg + g);
 						buff16[cnt + channelMap[3]] = aAvg;
-						yPos++; 
+						yPos++;
 						cnt += channels;
 						if (j%2) sampledPos++;
 					}
@@ -1938,11 +2161,11 @@
 						}
 						// Yuv
 						g = Clamp16(y[yPos] + yuvOffset16 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
-						buff[cnt + channelMap[1]] = g >> shift; 
-						buff[cnt + channelMap[2]] = Clamp16(uAvg + g) >> shift;
-						buff[cnt + channelMap[0]] = Clamp16(vAvg + g) >> shift;
-						buff[cnt + channelMap[3]] = aAvg >> shift;
-						yPos++; 
+						buff[cnt + channelMap[1]] = UINT8(g >> shift);
+						buff[cnt + channelMap[2]] = UINT8(Clamp16(uAvg + g) >> shift);
+						buff[cnt + channelMap[0]] = UINT8(Clamp16(vAvg + g) >> shift);
+						buff[cnt + channelMap[3]] = UINT8(aAvg >> shift);
+						yPos++;
 						cnt += channels;
 						if (j%2) sampledPos++;
 					}
@@ -1957,6 +2180,7 @@
 			}
 			break;
 		}
+#ifdef __PGF32SUPPORT__
 	case ImageModeGray31:
 		{
 			ASSERT(m_header.channels == 1);
@@ -1984,10 +2208,10 @@
 				}
 			} else {
 				ASSERT(bpp == 8);
-				
+
 				for (i=0; i < h; i++) {
 					for (j=0; j < w; j++) {
-						buff[j] = Clamp31(y[yPos++] + yuvOffset31) >> shift;
+						buff[j] = UINT8(Clamp31(y[yPos++] + yuvOffset31) >> shift);
 					}
 					buff += pitch;
 
@@ -1997,9 +2221,10 @@
 					}
 				}
 			}
-			break;	
-		}
-	case ImageModeRGB12: 
+			break;
+		}
+#endif
+	case ImageModeRGB12:
 		{
 			ASSERT(m_header.channels == 3);
 			ASSERT(m_header.bpp == m_header.channels*4);
@@ -2020,13 +2245,13 @@
 					vAvg = v[yPos];
 					yval = Clamp4(y[yPos++] + YUVoffset4 - ((uAvg + vAvg ) >> 2)); // must be logical shift operator
 					if (j%2 == 0) {
-						buff[cnt] = Clamp4(vAvg + yval) | (yval << 4);
+						buff[cnt] = UINT8(Clamp4(vAvg + yval) | (yval << 4));
 						cnt++;
 						buff[cnt] = Clamp4(uAvg + yval);
 					} else {
 						buff[cnt] |= Clamp4(vAvg + yval) << 4;
 						cnt++;
-						buff[cnt] = yval | (Clamp4(uAvg + yval) << 4);
+						buff[cnt] = UINT8(yval | (Clamp4(uAvg + yval) << 4));
 						cnt++;
 					}
 				}
@@ -2039,7 +2264,7 @@
 			}
 			break;
 		}
-	case ImageModeRGB16: 
+	case ImageModeRGB16:
 		{
 			ASSERT(m_header.channels == 3);
 			ASSERT(m_header.bpp == 16);
@@ -2097,7 +2322,7 @@
 		delete[] buffStart;
 	}
 #endif
-}			
+}
 
 //////////////////////////////////////////////////////////////////////
 /// Get YUV image data in interleaved format: (ordering is YUV[A])
@@ -2118,12 +2343,11 @@
 	const UINT32 w = m_width[0];
 	const UINT32 h = m_height[0];
 	const bool wOdd = (1 == w%2);
-	const int bits = m_header.bpp/m_header.channels;
-	const int dataBits = sizeof(DataT)*8; ASSERT(dataBits == 16 || dataBits == 32);
-	const int pitch2 = pitch/sizeof(DataT);
+	const int dataBits = DataTSize*8; ASSERT(dataBits == 16 || dataBits == 32);
+	const int pitch2 = pitch/DataTSize;
 	const int yuvOffset = (dataBits == 16) ? YUVoffset8 : YUVoffset16;
 	const double dP = 1.0/h;
-	
+
 	int defMap[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; ASSERT(sizeof(defMap)/sizeof(defMap[0]) == MaxChannels);
 	if (channelMap == NULL) channelMap = defMap;
 	int sampledPos = 0, yPos = 0;
@@ -2131,8 +2355,7 @@
 	double percent = 0;
 	UINT32 i, j;
 
-	if (m_header.channels == 3) { 
-		ASSERT(m_header.bpp == m_header.channels*bits);
+	if (m_header.channels == 3) {
 		ASSERT(bpp%dataBits == 0);
 
 		DataT* y = m_channel[0]; ASSERT(y);
@@ -2155,7 +2378,7 @@
 				buff[cnt + channelMap[0]] = y[yPos];
 				buff[cnt + channelMap[1]] = uAvg;
 				buff[cnt + channelMap[2]] = vAvg;
-				yPos++; 
+				yPos++;
 				cnt += channels;
 				if (j%2) sampledPos++;
 			}
@@ -2197,7 +2420,7 @@
 				buff[cnt + channelMap[1]] = uAvg;
 				buff[cnt + channelMap[2]] = vAvg;
 				buff[cnt + channelMap[3]] = aAvg;
-				yPos++; 
+				yPos++;
 				cnt += channels;
 				if (j%2) sampledPos++;
 			}
@@ -2229,9 +2452,8 @@
 void CPGFImage::ImportYUV(int pitch, DataT *buff, BYTE bpp, int channelMap[] /*= NULL*/, CallbackPtr cb /*= NULL*/, void *data /*=NULL*/) THROW_ {
 	ASSERT(buff);
 	const double dP = 1.0/m_header.height;
-	const int bits = m_header.bpp/m_header.channels;
-	const int dataBits = sizeof(DataT)*8; ASSERT(dataBits == 16 || dataBits == 32);
-	const int pitch2 = pitch/sizeof(DataT);
+	const int dataBits = DataTSize*8; ASSERT(dataBits == 16 || dataBits == 32);
+	const int pitch2 = pitch/DataTSize;
 	const int yuvOffset = (dataBits == 16) ? YUVoffset8 : YUVoffset16;
 
 	int yPos = 0, cnt = 0;
@@ -2241,7 +2463,6 @@
 	if (channelMap == NULL) channelMap = defMap;
 
 	if (m_header.channels == 3)	{
-		ASSERT(m_header.bpp == m_header.channels*bits);
 		ASSERT(bpp%dataBits == 0);
 
 		DataT* y = m_channel[0]; ASSERT(y);
@@ -2264,9 +2485,8 @@
 				cnt += channels;
 			}
 			buff += pitch2;
-		}	
+		}
 	} else if (m_header.channels == 4) {
-		ASSERT(m_header.bpp == m_header.channels*bits);
 		ASSERT(bpp%dataBits == 0);
 
 		DataT* y = m_channel[0]; ASSERT(y);
@@ -2291,7 +2511,7 @@
 				cnt += channels;
 			}
 			buff += pitch2;
-		}	
+		}
 	}
 
 	if (m_downsample) {

Modified: trunk/Scribus/scribus/third_party/pgf/PGFimage.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16771&path=/trunk/Scribus/scribus/third_party/pgf/PGFimage.h
==============================================================================
--- trunk/Scribus/scribus/third_party/pgf/PGFimage.h (original)
+++ trunk/Scribus/scribus/third_party/pgf/PGFimage.h Mon Aug  8 18:19:05 2011
@@ -1,41 +1,56 @@
 /*
  * The Progressive Graphics File; http://www.libpgf.org
- * 
+ *
  * $Date: 2007-02-03 13:04:21 +0100 (Sa, 03 Feb 2007) $
  * $Revision: 280 $
- * 
+ *
  * This file Copyright (C) 2006 xeraina GmbH, Switzerland
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
  * as published by the Free Software Foundation; either version 2.1
  * of the License, or (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+//////////////////////////////////////////////////////////////////////
+/// @file PGFimage.h
+/// @brief PGF image class
+/// @author C. Stamm
+
 #ifndef PGF_PGFIMAGE_H
 #define PGF_PGFIMAGE_H
 
-#include "PGFtypes.h"
-#include "Stream.h"
+#include "PGFstream.h"
 
 class CDecoder;
+class CEncoder;
 class CWaveletTransform;
 
 //////////////////////////////////////////////////////////////////////
-/// PGF image 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
+/// @brief PGF main class
 class CPGFImage {
 public:
-	
+
 	//////////////////////////////////////////////////////////////////////
 	/// Standard constructor: It is used to create a PGF instance for opening and reading.
 	CPGFImage();
@@ -45,11 +60,25 @@
 	virtual ~CPGFImage();
 
 	//////////////////////////////////////////////////////////////////////
+	/// Close PGF image after opening and reading.
+	/// Destructor calls this method during destruction.
+	virtual void Close();
+
+	//////////////////////////////////////////////////////////////////////
+	/// Destroy internal data structures.
+	/// Destructor calls this method during destruction.
+	virtual void Destroy();
+
+	//////////////////////////////////////////////////////////////////////
 	/// 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.
 	/// @param stream A PGF stream
 	void Open(CPGFStream* stream) THROW_;
+
+	//////////////////////////////////////////////////////////////////////
+	/// Returns true if the PGF has been opened and not closed.
+	bool IsOpen() const	{ return m_decoder != NULL; }
 
 	//////////////////////////////////////////////////////////////////////
 	/// Read and decode some levels of a PGF image at current stream position.
@@ -60,7 +89,7 @@
 	/// 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.
-	/// @param level The image level of the resulting image in the internal image buffer.
+	/// @param level [0, nLevels) The image level of the resulting image in the internal image buffer.
 	/// @param cb A pointer to a callback procedure. The procedure is called after reading a single level. If cb returns true, then it stops proceeding.
 	/// @param data Data Pointer to C++ class container to host callback procedure.
 	void Read(int level = 0, CallbackPtr cb = NULL, void *data = NULL) THROW_;
@@ -72,7 +101,7 @@
 	/// All coordinates are measured in pixels.
 	/// It might throw an IOException.
 	/// @param rect [inout] Rectangular region of interest (ROI). The rect might be cropped.
-	/// @param level The image level of the resulting image in the internal image buffer.
+	/// @param level [0, nLevels) The image level of the resulting image in the internal image buffer.
 	/// @param cb A pointer to a callback procedure. The procedure is called after reading a single level. If cb returns true, then it stops proceeding.
 	/// @param data Data Pointer to C++ class container to host callback procedure.
 	void Read(PGFRect& rect, int level = 0, CallbackPtr cb = NULL, void *data = NULL) THROW_;
@@ -88,28 +117,19 @@
 	//////////////////////////////////////////////////////////////////////
 	/// After you've written a PGF image, you can call this method followed by GetBitmap/GetYUV
 	/// to get a quick reconstruction (coded -> decoded image).
-	void Reconstruct() THROW_;
-
-	//////////////////////////////////////////////////////////////////////
-	/// Close PGF image after opening and reading.
-	/// Destructor calls this method during destruction.
-	void Close();
-
-	//////////////////////////////////////////////////////////////////////
-	/// Destroy internal data structures.
-	/// Destructor calls this method during destruction.
-	void Destroy();
+	/// @param level The image level of the resulting image in the internal image buffer.
+	void Reconstruct(int level = 0);
 
 	//////////////////////////////////////////////////////////////////////
 	/// 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 
+	/// 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 }.
+	/// If your provided image buffer expects a channel sequence ARGB, then the channelMap looks like { 3, 2, 1, 0 }.
 	/// It might throw an IOException.
 	/// @param pitch The number of bytes of a row of the image buffer.
 	/// @param buff An image buffer.
@@ -144,7 +164,7 @@
 	/// 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 }.
+	/// If your provided image buffer contains a channel sequence ARGB, then the channelMap looks like { 3, 2, 1, 0 }.
 	/// It might throw an IOException.
 	/// @param pitch The number of bytes of a row of the image buffer.
 	/// @param buff An image buffer.
@@ -179,13 +199,53 @@
 	/// 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(...)).
+	/// Please note: the earlier parameter nLevels has now to be set with SetHeader. Either specify the number of levels
+	/// or use the value 0 for automatic setting.
 	/// It might throw an IOException.
 	/// @param stream A PGF stream
-	/// @param levels The positive number of levels used in layering or 0 meaning a useful number of levels is computed.
-	/// @param cb A pointer to a callback procedure. The procedure is called after reading a single level. If cb returns true, then it stops proceeding.
 	/// @param nWrittenBytes [in-out] The number of bytes written into stream are added to the input value.
-	/// @param data Data Pointer to C++ class container to host callback procedure.
-	void Write(CPGFStream* stream, int levels = 0, CallbackPtr cb = NULL, UINT32* nWrittenBytes = NULL, void *data = NULL) THROW_;
+	/// @param cb A pointer to a callback procedure. The procedure is called after writing a single level. If cb returns true, then it stops proceeding.
+	/// @param data Data Pointer to C++ class container to host callback procedure.
+	void Write(CPGFStream* stream, UINT32* nWrittenBytes = NULL, CallbackPtr cb = NULL, void *data = NULL) THROW_;
+
+	//////////////////////////////////////////////////////////////////
+	/// Create wavelet transform channels and encoder.
+	/// Call this method before your first call of Write(int level), but after SetHeader().
+	/// Don't use this method when you call Write().
+	/// It might throw an IOException.
+	/// @param stream A PGF stream
+	/// @return The number of bytes written into stream.
+	UINT32 WriteHeader(CPGFStream* stream) THROW_;
+
+#ifdef __PGFROISUPPORT__
+	//////////////////////////////////////////////////////////////////
+	/// 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.
+	/// Precondition: the PGF image contains a valid header (see also SetHeader(...)) and
+	/// WriteHeader() has been called before Write().
+	/// The ROI encoding scheme is used.
+	/// It might throw an IOException.
+	/// @param level [0, nLevels) The image level of the resulting image in the internal image buffer.
+	/// @param cb A pointer to a callback procedure. The procedure is called after writing a single level. If cb returns true, then it stops proceeding.
+	/// @param data Data Pointer to C++ class container to host callback procedure.
+	/// @return The number of bytes written into stream.
+	UINT32 Write(int level, CallbackPtr cb = NULL, void *data = NULL) THROW_;
+#endif
+
+	/////////////////////////////////////////////////////////////////////
+	/// Configures the encoder.
+	/// @param useOMP Use parallel threading with Open MP during encoding. Default value: true. Influences the encoding only if the codec has been compiled with OpenMP support.
+	/// @param favorSpeedOverSize Favors encoding speed over compression ratio. Default value: false
+	void ConfigureEncoder(bool useOMP = true, bool favorSpeedOverSize = false) { m_useOMPinEncoder = useOMP; m_favorSpeedOverSize = favorSpeedOverSize; }
+
+	/////////////////////////////////////////////////////////////////////
+	/// Configures the encoder.
+	/// @param useOMP Use parallel threading with Open MP during decoding. Default value: true. Influences the decoding only if the codec has been compiled with OpenMP support.
+	void ConfigureDecoder(bool useOMP = true) { m_useOMPinDecoder = useOMP; }
 
 	//////////////////////////////////////////////////////////////////////
 	/// Set background of an RGB image with transparency channel or reset to default background.
@@ -285,17 +345,19 @@
 
 	//////////////////////////////////////////////////////////////////////
 	/// Return the length of all encoded headers in bytes.
+	/// Precondition: The PGF image has been opened with a call of Open(...).
 	/// @return The length of all encoded headers in bytes
 	UINT32 GetEncodedHeaderLength() const;
 
 	//////////////////////////////////////////////////////////////////////
 	/// Return the length of an encoded PGF level in bytes.
+	/// Precondition: The PGF image has been opened with a call of Open(...).
 	/// @param level The image level
 	/// @return The length of a PGF level in bytes
 	UINT32 GetEncodedLevelLength(int level) const					{ ASSERT(level >= 0 && level < m_header.nLevels); return m_levelLength[m_header.nLevels - level - 1]; }
 
 	////////////////////////////////////////////////////////////////////
-	/// Reset stream position to beginning of PGF pre header
+	/// Reset stream position to start of PGF pre-header
 	void ResetStreamPos() THROW_;
 
 	//////////////////////////////////////////////////////////////////////
@@ -308,7 +370,7 @@
 	UINT32 ReadEncodedHeader(UINT8* target, UINT32 targetLen) const THROW_;
 
 	//////////////////////////////////////////////////////////////////////
-	/// Reads the data of an encoded PGF level and copies it to a target buffer 
+	/// 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.
@@ -335,7 +397,7 @@
 	//////////////////////////////////////////////////////////////////////
 	/// Return bits per channel.
 	/// @return Bits per channel
-	BYTE ChannelDepth() const										{ return sizeof(DataT)*8; }
+	BYTE ChannelDepth() const										{ return DataTSize*8; }
 
 	//////////////////////////////////////////////////////////////////////
 	/// Return image width of channel 0 at given level in pixels.
@@ -352,14 +414,14 @@
 	UINT32 Height(int level = 0) const								{ ASSERT(level >= 0); return LevelHeight(m_header.height, level); }
 
 	//////////////////////////////////////////////////////////////////////
-	/// Return current image level. 
+	/// 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().
 	/// @return Current image level
-	BYTE Level() const												{ return m_currentLevel; }
-
-	//////////////////////////////////////////////////////////////////////
-	/// Return the number of image levels. 
+	BYTE Level() const												{ return (BYTE)m_currentLevel; }
+
+	//////////////////////////////////////////////////////////////////////
+	/// Return the number of image levels.
 	/// @return Number of image levels
 	BYTE Levels() const												{ return m_header.nLevels; }
 
@@ -374,7 +436,7 @@
 	/// An image of type RGB contains 3 image channels (B, G, R).
 	/// @return Number of image channels
 	BYTE Channels() const											{ return m_header.channels; }
-	
+
 	//////////////////////////////////////////////////////////////////////
 	/// Return the image mode.
 	/// An image mode is a predefined constant value (see also PGFtypes.h) compatible with Adobe Photoshop.
@@ -391,7 +453,7 @@
 	//////////////////////////////////////////////////////////////////////
 	/// Return true if the pgf image supports Region Of Interest (ROI).
 	/// @return true if the pgf image supports ROI.
-	bool ROIisSupported() const										{ return (m_preHeader.version & PGFROI) != 0; }
+	bool ROIisSupported() const										{ return (m_preHeader.version & PGFROI) == PGFROI; }
 
 	//////////////////////////////////////////////////////////////////////
 	/// Returns highest supported version
@@ -419,44 +481,38 @@
 	/// @return Image level height in pixels
 	static UINT32 LevelHeight(UINT32 height, int level)				{ ASSERT(level >= 0); UINT32 h = (height >> level); return ((h << level) == height) ? h : h + 1; }
 
-	//////////////////////////////////////////////////////////////////////
-	/// Compute and return number of levels. During PGF::Write the return
-	/// value of this method is used in case the parameter levels is not a
-	/// positive value. 
-	/// 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.
-	/// @param width Original image width
-	/// @param height Original image height
-	/// @return Number of PGF levels
-	static BYTE ComputeLevels(UINT32 width, UINT32 height);
-
 protected:
 	CWaveletTransform* m_wtChannel[MaxChannels];	// wavelet transformed color channels
 	DataT* m_channel[MaxChannels];					// untransformed channels in YUV format
-	CDecoder* m_decoder;
+	CDecoder* m_decoder;			// PGF decoder
+	CEncoder* m_encoder;			// PGF encoder
 	UINT32* m_levelLength;			// length of each level in bytes; first level starts immediately after this array
 	UINT32 m_width[MaxChannels];	// width of each channel at current level
 	UINT32 m_height[MaxChannels];	// height of each channel at current level
 	PGFPreHeader m_preHeader;		// PGF pre header
 	PGFHeader m_header;				// PGF file header
 	PGFPostHeader m_postHeader;		// PGF post header
-	BYTE m_currentLevel;			// transform level of current image
+	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
 #ifdef __PGFROISUPPORT__
+	bool m_levelwise;				// write level-wise (only used with WriteNextLevel)
+	bool m_streamReinitialized;		// stream has been reinitialized
 	PGFRect m_roi;					// region of interest
 #endif
 
-private:	
+private:
 	RefreshCB m_cb;					// pointer to refresh callback procedure
 	void *m_cbArg;					// refresh callback argument
 
+	void ComputeLevels();
+	void CompleteHeader();
 	void RgbToYuv(int pitch, UINT8* rgbBuff, BYTE bpp, int channelMap[], CallbackPtr cb, void *data) THROW_;
 	void Downsample(int nChannel);
-	void Init() THROW_;
+	void WriteLevel() THROW_;
 
 #ifdef __PGFROISUPPORT__
 	void SetROI(PGFRect rect);
@@ -468,16 +524,16 @@
 	}
 	UINT8 Clamp4(DataT v) const {
 		if (v & 0xFFFFFFF0) return (v < 0) ? (UINT8)0: (UINT8)15; else return (UINT8)v;
-	}	
+	}
 	UINT16 Clamp6(DataT v) const {
 		if (v & 0xFFFFFFC0) return (v < 0) ? (UINT16)0: (UINT16)63; else return (UINT16)v;
-	}	
+	}
 	UINT16 Clamp16(DataT v) const {
 		if (v & 0xFFFF0000) return (v < 0) ? (UINT16)0: (UINT16)65535; else return (UINT16)v;
-	}	
+	}
 	UINT32 Clamp31(DataT v) const {
 		if (v < 0) return 0; else return (UINT32)v;
-	}	
+	}
 };
 
 #endif //PGF_PGFIMAGE_H

Modified: trunk/Scribus/scribus/third_party/pgf/PGFplatform.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16771&path=/trunk/Scribus/scribus/third_party/pgf/PGFplatform.h
==============================================================================
--- trunk/Scribus/scribus/third_party/pgf/PGFplatform.h (original)
+++ trunk/Scribus/scribus/third_party/pgf/PGFplatform.h Mon Aug  8 18:19:05 2011
@@ -1,52 +1,56 @@
 /*
  * The Progressive Graphics File; http://www.libpgf.org
- * 
+ *
  * $Date: 2007-06-12 19:27:47 +0200 (Di, 12 Jun 2007) $
  * $Revision: 307 $
- * 
+ *
  * This file Copyright (C) 2006 xeraina GmbH, Switzerland
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
  * as published by the Free Software Foundation; either version 2.1
  * of the License, or (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+//////////////////////////////////////////////////////////////////////
+/// @file PGFplatform.h
+/// @brief PGF platform specific definitions
+/// @author C. Stamm
+
 #ifndef PGF_PGFPLATFORM_H
 #define PGF_PGFPLATFORM_H
 
 #include <cassert>
-#include <cmath> 
-#include <cstdlib> 
-
-//-------------------------------------------------------------------------------
-// Taken from lcms2 header.
-// Try to detect big endian platforms. This list can be endless, so only some checks are performed over here.
-//-------------------------------------------------------------------------------
-
+#include <cmath>
+#include <cstdlib>
+
+//-------------------------------------------------------------------------------
+// Endianess detection taken from lcms2 header.
+// This list can be endless, so only some checks are performed over here.
+//-------------------------------------------------------------------------------
 #if defined(_HOST_BIG_ENDIAN) || defined(__BIG_ENDIAN__) || defined(WORDS_BIGENDIAN)
-# define PGF_USE_BIG_ENDIAN 1
-#endif
-
-#if defined(__sgi__) || defined(__sgi) || defined(__powerpc__) || defined(__sparc__)
-# define PGF_USE_BIG_ENDIAN 1
+#define PGF_USE_BIG_ENDIAN 1
+#endif
+
+#if defined(__sgi__) || defined(__sgi) || defined(__powerpc__) || defined(__sparc) || defined(__sparc__)
+#define PGF_USE_BIG_ENDIAN 1
 #endif
 
 #if defined(__ppc__) || defined(__s390__) || defined(__s390x__)
-# define PGF_USE_BIG_ENDIAN 1
+#define PGF_USE_BIG_ENDIAN 1
 #endif
 
 #ifdef TARGET_CPU_PPC
-# define PGF_USE_BIG_ENDIAN 1
+#define PGF_USE_BIG_ENDIAN 1
 #endif
 
 //-------------------------------------------------------------------------------
@@ -68,15 +72,16 @@
 //-------------------------------------------------------------------------------
 #define WordWidth			32					// WordBytes*8
 #define WordWidthLog		5					// ld of WordWidth
+#define WordMask			0xFFFFFFE0			// least WordWidthLog bits are zero
 #define WordBytes			4					// sizeof(UINT32)
 #define WordBytesLog		2					// ld of WordBytes
 
 //-------------------------------------------------------------------------------
 // Macros
 //-------------------------------------------------------------------------------
-#define DWWIDTH(bytes)		((((bytes) + WordBytes - 1) >> WordBytesLog) << WordBytesLog)	// aligns scanline width in bytes to DWORD value
-#define DWWIDTHBITS(bits)	((((bits) + WordWidth - 1) >> WordWidthLog) << WordBytesLog)	// aligns scanline width in bits to DWORD value
-#define DWWIDTHREST(bytes)	((WordBytes - (bytes)%WordBytes)%WordBytes)						// DWWIDTHBITS(bytes*8) - bytes
+//#define DWWIDTH(bytes)		((((bytes) + WordBytes - 1) >> WordBytesLog) << WordBytesLog)	// aligns scanline width in bytes to DWORD value
+//#define DWWIDTHBITS(bits)	((((bits) + WordWidth - 1) >> WordWidthLog) << WordBytesLog)	// aligns scanline width in bits to DWORD value
+//#define DWWIDTHREST(bytes)	((WordBytes - (bytes)%WordBytes)%WordBytes)						// DWWIDTHBITS(bytes*8) - bytes
 
 //-------------------------------------------------------------------------------
 // Min-Max macros
@@ -137,10 +142,10 @@
 #include <windows.h>
 #include <ole2.h>
 
-#endif // _MFC_VER 
-//-------------------------------------------------------------------------------
-
-#define DllExport   __declspec( dllexport ) 
+#endif // _MFC_VER
+//-------------------------------------------------------------------------------
+
+#define DllExport   __declspec( dllexport )
 
 //-------------------------------------------------------------------------------
 // unsigned number type definitions
@@ -152,8 +157,8 @@
 typedef	unsigned int		UINT32;
 typedef unsigned long       DWORD;
 typedef unsigned long       ULONG;
-typedef unsigned __int64	UINT64; 
-typedef unsigned __int64	ULONGLONG; 
+typedef unsigned __int64	UINT64;
+typedef unsigned __int64	ULONGLONG;
 
 //-------------------------------------------------------------------------------
 // signed number type definitions
@@ -183,9 +188,9 @@
 	#ifdef _DEBUG
 		#define ASSERT(x)	assert(x)
 	#else
-		#if defined(__GNUC__) 
-			#define ASSERT(ignore)((void) 0) 
-		#elif _MSC_VER >= 1300 
+		#if defined(__GNUC__)
+			#define ASSERT(ignore)((void) 0)
+		#elif _MSC_VER >= 1300
 			#define ASSERT		__noop
 		#else
 			#define ASSERT ((void)0)
@@ -232,12 +237,13 @@
 #define InsufficientMemory	0x20000001			// memory allocation wasn't successfull
 #define EndOfMemory			0x20000002			// like end-of-file (EOF) for memory stream
 #define EscapePressed		0x20000003			// user break by ESC
-#define WrongVersion		0x20000004			// wrong pgf version 
+#define WrongVersion		0x20000004			// wrong pgf version
 #define FormatCannotRead	0x20000005			// wrong data file format
 #define ImageTooSmall		0x20000006			// image is too small
 #define ZlibError			0x20000007			// error in zlib functions
 #define ColorTableError		0x20000008			// errors related to color table size
 #define PNGError			0x20000009			// errors in png functions
+#define MissingData			0x2000000A			// expected data cannot be read
 
 //-------------------------------------------------------------------------------
 // methods
@@ -312,35 +318,43 @@
 // Apple OSX
 //-------------------------------------------------------------------------------
 #ifdef __APPLE__
-#define __POSIX__ 
+#define __POSIX__
 #endif // __APPLE__
 
 
 //-------------------------------------------------------------------------------
-// LINUX / GLIBC
+// LINUX
 //-------------------------------------------------------------------------------
 #if defined(__linux__) || defined(__GLIBC__)
 #define __POSIX__
-#endif /* __linux__ */
+#endif // __linux__ or __GLIBC__
+
+
+//-------------------------------------------------------------------------------
+// SOLARIS
+//-------------------------------------------------------------------------------
+#ifdef __sun
+#define __POSIX__
+#endif // __sun
 
 
 //-------------------------------------------------------------------------------
 // NetBSD
 //-------------------------------------------------------------------------------
 #ifdef __NetBSD__
-#ifndef __POSIX__ 
-#define __POSIX__ 
-#endif 
-
-#ifndef off64_t 
-#define off64_t off_t 
-#endif 
-
-#ifndef lseek64 
-#define lseek64 lseek 
-#endif 
-
-#endif /* __NetBSD__ */
+#ifndef __POSIX__
+#define __POSIX__
+#endif
+
+#ifndef off64_t
+#define off64_t off_t
+#endif
+
+#ifndef lseek64
+#define lseek64 lseek
+#endif
+
+#endif // __NetBSD__
 
 
 //-------------------------------------------------------------------------------
@@ -383,7 +397,7 @@
 // other types
 //-------------------------------------------------------------------------------
 typedef int					OSError;
-typedef int					HANDLE;	
+typedef int					HANDLE;
 typedef unsigned long		ULONG_PTR;
 typedef void*				PVOID;
 typedef char*				LPTSTR;
@@ -430,8 +444,8 @@
 //-------------------------------------------------------------------------------
 // methods
 //-------------------------------------------------------------------------------
-/* The MulDiv function multiplies two 32-bit values and then divides the 64-bit 
- * result by a third 32-bit value. The return value is rounded up or down to 
+/* The MulDiv function multiplies two 32-bit values and then divides the 64-bit
+ * result by a third 32-bit value. The return value is rounded up or down to
  * the nearest integer.
  * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winprog/winprog/muldiv.asp
  * */
@@ -451,7 +465,7 @@
 	#ifdef _DEBUG
 		#define ASSERT(x)	assert(x)
 	#else
-		#define ASSERT(x)	
+		#define ASSERT(x)
 	#endif //_DEBUG
 #endif //ASSERT
 
@@ -487,12 +501,13 @@
 #define InsufficientMemory		0x2001			// memory allocation wasn't successfull
 #define EndOfMemory				0x2002			// like end-of-file (EOF) for memory stream
 #define EscapePressed			0x2003			// user break by ESC
-#define WrongVersion			0x2004			// wrong pgf version 
+#define WrongVersion			0x2004			// wrong pgf version
 #define FormatCannotRead		0x2005			// wrong data file format
 #define ImageTooSmall			0x2006			// image is too small
 #define ZlibError				0x2007			// error in zlib functions
 #define ColorTableError			0x2008			// errors related to color table size
 #define PNGError				0x2009			// errors in png functions
+#define MissingData				0x200A			// expected data cannot be read
 
 //-------------------------------------------------------------------------------
 // methods
@@ -558,7 +573,7 @@
 //-------------------------------------------------------------------------------
 //	Big Endian
 //-------------------------------------------------------------------------------
-#ifdef PGF_USE_BIG_ENDIAN 
+#ifdef PGF_USE_BIG_ENDIAN
 
 #ifndef _lrotl
 	#define _lrotl(x,n)	(((x) << ((UINT32)(n))) | ((x) >> (32 - (UINT32)(n))))
@@ -568,30 +583,61 @@
 	return ((wX & 0xFF00) >> 8) | ((wX & 0x00FF) << 8);
 }
 
-__inline UINT32 ByteSwap(UINT32 dwX) { 
-#ifdef _X86_     
-	_asm mov eax, dwX     
+__inline UINT32 ByteSwap(UINT32 dwX) {
+#ifdef _X86_
+	_asm mov eax, dwX
 	_asm bswap eax
-	_asm mov dwX, eax      
-	return dwX; 
-#else     
-	return _lrotl(((dwX & 0xFF00FF00) >> 8) | ((dwX & 0x00FF00FF) << 8), 16); 
-#endif 
+	_asm mov dwX, eax
+	return dwX;
+#else
+	return _lrotl(((dwX & 0xFF00FF00) >> 8) | ((dwX & 0x00FF00FF) << 8), 16);
+#endif
 }
 
 #if defined WIN32
-__inline UINT64 ByteSwap(UINT64 ui64) { 
+__inline UINT64 ByteSwap(UINT64 ui64) {
 	return _byteswap_uint64(ui64);
 }
 #endif
 
 #define __VAL(x) ByteSwap(x)
 
-#else //PGF_USE_BIG_ENDIAN 
+#else //PGF_USE_BIG_ENDIAN
 
 	#define __VAL(x) (x)
 
-#endif //PGF_USE_BIG_ENDIAN 
- 
+#endif //PGF_USE_BIG_ENDIAN
+
+// NOTE: Use LIBPGF_DISABLE_OPENMP to disable OpenMP support in whole libpgf
+#ifndef LIBPGF_DISABLE_OPENMP
+
+// OpenMP rules (inspired from libraw project)
+#if defined (_OPENMP)
+
+#if defined(WIN32)
+# if defined (_MSC_VER) && (_MSC_VER >= 1500)
+// VS2008 SP1 and VS2010+ : OpenMP works OK
+#   define LIBPGF_USE_OPENMP
+#elif defined (__INTEL_COMPILER) && (__INTEL_COMPILER >=910)
+//  Have not tested on 9.x and 10.x, but Intel documentation claims OpenMP 2.5 support in 9.1
+#   define LIBPGF_USE_OPENMP
+#else
+#  undef LIBPGF_USE_OPENMP
+#endif
+// Not Win32
+# elif (defined(__APPLE__) || defined(__MACOSX__)) && defined(_REENTRANT)
+#   undef LIBPGF_USE_OPENMP
+# else
+#   define LIBPGF_USE_OPENMP
+# endif
+
+#endif // defined (_OPENMP)
+
+#endif // ifndef LIBPGF_DISABLE_OPENMP
+
+#ifdef LIBPGF_USE_OPENMP
+#include <omp.h>
+#endif
+
 
 #endif //PGF_PGFPLATFORM_H

Modified: trunk/Scribus/scribus/third_party/pgf/PGFtypes.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16771&path=/trunk/Scribus/scribus/third_party/pgf/PGFtypes.h
==============================================================================
--- trunk/Scribus/scribus/third_party/pgf/PGFtypes.h (original)
+++ trunk/Scribus/scribus/third_party/pgf/PGFtypes.h Mon Aug  8 18:19:05 2011
@@ -1,25 +1,30 @@
 /*
  * The Progressive Graphics File; http://www.libpgf.org
- * 
+ *
  * $Date: 2007-06-11 10:56:17 +0200 (Mo, 11 Jun 2007) $
  * $Revision: 299 $
- * 
+ *
  * This file Copyright (C) 2006 xeraina GmbH, Switzerland
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
  * as published by the Free Software Foundation; either version 2.1
  * of the License, or (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
+
+//////////////////////////////////////////////////////////////////////
+/// @file PGFtypes.h
+/// @brief PGF definitions
+/// @author C. Stamm
 
 #ifndef PGF_PGFTYPES_H
 #define PGF_PGFTYPES_H
@@ -40,8 +45,10 @@
 // Version 6:	modified data structure PGFPreHeader: hSize (header size) is now a UINT32 instead of a UINT16 (backward compatibility assured)
 //
 //-------------------------------------------------------------------------------
-#define PGFCodecVersion		"6.09.44"			// Major number
+#define PGFCodecVersion		"6.11.24"			// Major number
 												// Minor number: Year (2) Week (2)
+
+#define PGFCodecVersionID   0x061124            // Codec version ID to use for API check in client implementation
 
 //-------------------------------------------------------------------------------
 //	Image constants
@@ -56,27 +63,27 @@
 // version flags
 #define Version2			2					// data structure PGFHeader of major version 2
 #ifdef __PGF32SUPPORT__
-#define PGF32				4					// 32 bit values are used -> allows at maximum 31 bits
-#else
-#define PGF32				0					// 16 bit values are used -> allows at maximum 15 bits
+	#define PGF32			4					// 32 bit values are used -> allows at maximum 31 bits
+#else
+	#define PGF32			0					// 16 bit values are used -> allows at maximum 15 bits
 #endif
 #define PGFROI				8					// supports Regions Of Interest
 #define Version5			16					// new coding scheme since major version 5
-#define Version6			32					// new HeaderSize: 32 bits instead of 16 bits 
+#define Version6			32					// new HeaderSize: 32 bits instead of 16 bits
 // version numbers
 #define PGFVersion			(Version2 | Version5 | Version6 | PGF32)	// current standard version
 
 //-------------------------------------------------------------------------------
 //	Coder constants
 //-------------------------------------------------------------------------------
-#define BufferSize			16384				// must be a multiple of WordWidth: RLblockSizeLen = 15
+#define BufferSize			16384				// must be a multiple of WordWidth
 #define RLblockSizeLen		15					// block size length (< 16): ld(BufferSize) < RLblockSizeLen <= 2*ld(BufferSize)
 #define LinBlockSize		8					// side length of a coefficient block in a HH or LL subband
 #define InterBlockSize		4					// side length of a coefficient block in a HL or LH subband
 #ifdef __PGF32SUPPORT__
-#define MaxBitPlanes		31					// maximum number of bit planes of m_value: 32 minus sign bit
-#else
-#define MaxBitPlanes		15					// maximum number of bit planes of m_value: 16 minus sign bit
+	#define MaxBitPlanes	31					// maximum number of bit planes of m_value: 32 minus sign bit
+#else
+	#define MaxBitPlanes	15					// maximum number of bit planes of m_value: 16 minus sign bit
 #endif
 #define MaxBitPlanesLog		5					// number of bits to code the maximum number of bit planes (in 32 or 16 bit mode)
 #define MaxQuality			MaxBitPlanes		// maximum quality
@@ -95,6 +102,7 @@
 /////////////////////////////////////////////////////////////////////
 /// PGF magic and version (part of PGF pre-header)
 /// @author C. Stamm
+/// @brief PGF identification and version
 struct PGFMagicVersion {
 	char magic[3];				// PGF identification = "PGF"
 	UINT8 version;				// PGF version
@@ -102,16 +110,18 @@
 };
 
 /////////////////////////////////////////////////////////////////////
-/// PGF pre-header
-/// @author C. Stamm
+/// PGF pre-header defined header length and PGF identification and version
+/// @author C. Stamm
+/// @brief PGF pre-header
 struct PGFPreHeader : PGFMagicVersion {
 	UINT32 hSize;				// total size of PGFHeader, [ColorTable], and [UserData] in bytes
 	// total: 8 Bytes
 };
 
 /////////////////////////////////////////////////////////////////////
-/// PGF header
-/// @author C. Stamm
+/// PGF header contains image information
+/// @author C. Stamm
+/// @brief PGF header
 struct PGFHeader {
 	UINT32 width;
 	UINT32 height;
@@ -125,8 +135,9 @@
 };
 
 /////////////////////////////////////////////////////////////////////
-/// PGF post-header is optional
-/// @author C. Stamm
+/// PGF post-header is optional. It contains color table and user data
+/// @author C. Stamm
+/// @brief Optional PGF post-header
 struct PGFPostHeader {
 	RGBQUAD clut[ColorTableLen];// color table for indexed color images
 	UINT8 *userData;			// user data of size userDataLen
@@ -134,8 +145,9 @@
 };
 
 /////////////////////////////////////////////////////////////////////
-/// ROI block header (used in ROI coding scheme)
-/// @author C. Stamm
+/// ROI block header is used with ROI coding scheme. It contains block size and tile end flag
+/// @author C. Stamm
+/// @brief Block header used with ROI coding scheme
 union ROIBlockHeader {
 	/// Constructor
 	/// @param v Buffer size
@@ -143,10 +155,11 @@
 	/// Constructor
 	/// @param size Buffer size
 	/// @param end 0/1 Flag; 1: last part of a tile
-	ROIBlockHeader(UINT32 size, bool end)	{ ASSERT(size < (1 << RLblockSizeLen)); bufferSize = size; tileEnd = end; }
+	ROIBlockHeader(UINT32 size, bool end)	{ ASSERT(size < (1 << RLblockSizeLen)); rbh.bufferSize = size; rbh.tileEnd = end; }
 
 	UINT16 val;
-	struct {
+	/// @brief Named ROI block header (part of the union)
+	struct RBH {
 #ifdef PGF_USE_BIG_ENDIAN
 		UINT16 tileEnd   :				1;	// 1: last part of a tile
 		UINT16 bufferSize: RLblockSizeLen;	// number of uncoded UINT32 values in a block
@@ -154,15 +167,16 @@
 		UINT16 bufferSize: RLblockSizeLen;	// number of uncoded UINT32 values in a block
 		UINT16 tileEnd   :				1;	// 1: last part of a tile
 #endif // PGF_USE_BIG_ENDIAN
-	};
+	} rbh;
 	// total: 2 Bytes
 };
 
 #pragma pack()
 
 /////////////////////////////////////////////////////////////////////
-/// PGF i/o exception structure
-/// @author C. Stamm
+/// PGF I/O exception
+/// @author C. Stamm
+/// @brief PGF exception
 struct IOException {
 	/// Standard constructor
 	IOException() : error(NoError) {}
@@ -176,6 +190,7 @@
 /////////////////////////////////////////////////////////////////////
 /// Rectangle
 /// @author C. Stamm
+/// @brief Rectangle
 struct PGFRect {
 	/// Standard constructor
 	PGFRect() : left(0), top(0), right(0), bottom(0) {}
@@ -190,7 +205,7 @@
 	UINT32 Width() const					{ return right - left; }
 	/// @return Rectangle height
 	UINT32 Height() const					{ return bottom - top; }
-	
+
 	/// Test if point (x,y) is inside this rectangle
 	/// @param x Point coordinate x
 	/// @param y Point coordinate y
@@ -215,5 +230,6 @@
 #define PreHeaderSize		sizeof(PGFPreHeader)
 #define HeaderSize			sizeof(PGFHeader)
 #define ColorTableSize		ColorTableLen*sizeof(RGBQUAD)
+#define DataTSize			sizeof(DataT)
 
 #endif //PGF_PGFTYPES_H

Modified: trunk/Scribus/scribus/third_party/pgf/Subband.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16771&path=/trunk/Scribus/scribus/third_party/pgf/Subband.cpp
==============================================================================
--- trunk/Scribus/scribus/third_party/pgf/Subband.cpp (original)
+++ trunk/Scribus/scribus/third_party/pgf/Subband.cpp Mon Aug  8 18:19:05 2011
@@ -1,26 +1,31 @@
 /*
  * The Progressive Graphics File; http://www.libpgf.org
- * 
+ *
  * $Date: 2006-06-04 22:05:59 +0200 (So, 04 Jun 2006) $
  * $Revision: 229 $
- * 
+ *
  * This file Copyright (C) 2006 xeraina GmbH, Switzerland
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
  * as published by the Free Software Foundation; either version 2.1
  * of the License, or (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+//////////////////////////////////////////////////////////////////////
+/// @file Subband.cpp
+/// @brief PGF wavelet subband class implementation
+/// @author C. Stamm
+
 #include "Subband.h"
 #include "Encoder.h"
 #include "Decoder.h"
@@ -29,7 +34,7 @@
 // Default constructor
 CSubband::CSubband() : m_size(0), m_data(0)
 #ifdef __PGFROISUPPORT__
-, m_ROIs(0), m_dataWidth(0) 
+, m_ROIs(0), m_dataWidth(0)
 #endif
 {
 }
@@ -43,8 +48,6 @@
 /////////////////////////////////////////////////////////////////////
 // Initialize subband parameters
 void CSubband::Initialize(UINT32 width, UINT32 height, int level, Orientation orient) {
-	ASSERT(!m_data);
-
 	m_width = width;
 	m_height = height;
 	m_size = m_width*m_height;
@@ -53,6 +56,7 @@
 	m_data = 0;
 	m_dataPos = 0;
 #ifdef __PGFROISUPPORT__
+	m_ROIs = 0;
 	m_dataWidth = width;
 #endif
 }
@@ -144,8 +148,7 @@
 /// A scalar quantization (with dead-zone) is used. A large quantization value
 /// results in strong quantization and therefore in big quality loss.
 /// @param quantParam A quantization parameter (larger or equal to 0)
-/// @param level Level
-void CSubband::Dequantize(int quantParam, int /*level*/) {
+void CSubband::Dequantize(int quantParam) {
 	if (m_orientation == LL) {
 		quantParam -= m_level + 1;
 	} else if (m_orientation == HH) {
@@ -181,7 +184,7 @@
 
 		// write values into buffer using partitiong scheme
 		encoder.Partition(this, w, h, xPos + yPos*m_width, m_width);
-	} else 
+	} else
 #endif
 	{
 		// write values into buffer using partitiong scheme
@@ -220,7 +223,7 @@
 
 		// read values into buffer using partitiong scheme
 		decoder.Partition(this, quantParam, w, h, (xPos - roi.left) + (yPos - roi.top)*m_dataWidth, m_dataWidth);
-	} else 
+	} else
 #endif
 	{
 		// read values into buffer using partitiong scheme
@@ -244,7 +247,7 @@
 	// band = HH, w = 30, ldTiles = 2 -> 4 tiles in a row/column
 	// --> tile widths
 	// 8 7 8 7
-	// 
+	//
 	// tile partitioning scheme
 	// 0 1 2 3
 	// 4 5 6 7

Modified: trunk/Scribus/scribus/third_party/pgf/Subband.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16771&path=/trunk/Scribus/scribus/third_party/pgf/Subband.h
==============================================================================
--- trunk/Scribus/scribus/third_party/pgf/Subband.h (original)
+++ trunk/Scribus/scribus/third_party/pgf/Subband.h Mon Aug  8 18:19:05 2011
@@ -1,26 +1,31 @@
 /*
- * The Progressive Graphics File; http://www.libpgf.org 
- * 
+ * The Progressive Graphics File; http://www.libpgf.org
+ *
  * $Date: 2006-06-04 22:05:59 +0200 (So, 04 Jun 2006) $
  * $Revision: 229 $
- * 
+ *
  * This file Copyright (C) 2006 xeraina GmbH, Switzerland
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
  * as published by the Free Software Foundation; either version 2.1
  * of the License, or (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+//////////////////////////////////////////////////////////////////////
+/// @file Subband.h
+/// @brief PGF wavelet subband class
+/// @author C. Stamm
+
 #ifndef PGF_SUBBAND_H
 #define PGF_SUBBAND_H
 
@@ -33,6 +38,7 @@
 //////////////////////////////////////////////////////////////////////
 /// PGF wavelet channel subband class.
 /// @author C. Stamm, R. Spuler
+/// @brief Wavelet channel class
 class CSubband {
 	friend class CWaveletTransform;
 
@@ -87,8 +93,7 @@
 	/// A scalar quantization (with dead-zone) is used. A large quantization value
 	/// results in strong quantization and therefore in big quality loss.
 	/// @param quantParam A quantization parameter (larger or equal to 0)
-	/// @level Level
-	void Dequantize(int quantParam, int level);
+	void Dequantize(int quantParam);
 
 	//////////////////////////////////////////////////////////////////////
 	/// Store wavelet coefficient in subband at given position.
@@ -121,7 +126,7 @@
 	/// Return width of this subband.
 	/// @return Width of this subband (in pixels)
 	int GetWidth() const				{ return m_width; }
-	
+
 	//////////////////////////////////////////////////////////////////////
 	/// Return orientation of this subband.
 	/// LL LH

Modified: trunk/Scribus/scribus/third_party/pgf/WaveletTransform.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16771&path=/trunk/Scribus/scribus/third_party/pgf/WaveletTransform.cpp
==============================================================================
--- trunk/Scribus/scribus/third_party/pgf/WaveletTransform.cpp (original)
+++ trunk/Scribus/scribus/third_party/pgf/WaveletTransform.cpp Mon Aug  8 18:19:05 2011
@@ -1,25 +1,30 @@
 /*
  * The Progressive Graphics File; http://www.libpgf.org
- * 
+ *
  * $Date: 2006-05-18 16:03:32 +0200 (Do, 18 Mai 2006) $
  * $Revision: 194 $
- * 
+ *
  * This file Copyright (C) 2006 xeraina GmbH, Switzerland
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
  * as published by the Free Software Foundation; either version 2.1
  * of the License, or (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
+
+//////////////////////////////////////////////////////////////////////
+/// @file WaveletTransform.cpp
+/// @brief PGF wavelet transform class implementation
+/// @author C. Stamm
 
 #include "WaveletTransform.h"
 
@@ -32,9 +37,9 @@
 // @param height The height of the original image (at level 0) in pixels
 // @param levels The number of levels (>= 0)
 // @param data Input data of subband LL at level 0
-CWaveletTransform::CWaveletTransform(UINT32 width, UINT32 height, int levels, DataT* data) : 
+CWaveletTransform::CWaveletTransform(UINT32 width, UINT32 height, int levels, DataT* data) :
 #ifdef __PGFROISUPPORT__
-m_ROIs(levels + 1), 
+m_ROIs(levels + 1),
 #endif
 m_nLevels(levels + 1), m_subband(0) {
 	ASSERT(m_nLevels > 0 && m_nLevels <= MaxLevel + 1);
@@ -167,7 +172,7 @@
 		// left border handling
 		src[1] -= ((src[0] + src[2] + c1) >> 1);
 		src[0] += ((src[1] + c1) >> 1);
-		
+
 		// middle part
 		for (; i < width-1; i += 2) {
 			src[i] -= ((src[i-1] + src[i+1] + c1) >> 1);
@@ -233,7 +238,7 @@
 	const UINT32 height = destBand->GetHeight();
 	UINT32 row0, row1, row2, row3, i, k, origin = 0;
 
-	// allocate memory for the results of the inverse transform 
+	// allocate memory for the results of the inverse transform
 	destBand->AllocMemory();
 	DataT* dest = destBand->GetBuffer();
 
@@ -345,7 +350,7 @@
 		if (destHeight & 1) {
 			MallatToLinear(srcLevel, &dest[row0], 0, destWidth);
 			InverseRow(&dest[row0], destWidth);
-		} 
+		}
 	}
 
 	// free memory of the current srcLevel
@@ -398,17 +403,18 @@
 	UINT32 i;
 
 	if (hiRow) {
-		#ifdef __PGFROISUPPORT__
-			UINT32 llPos, hlPos, lhPos, hhPos;
-
-			if (wquot < ll.BufferWidth()) {
-				// save current src buffer positions
-				llPos = ll.GetBuffPos(); 
-				hlPos = hl.GetBuffPos(); 
-				lhPos = lh.GetBuffPos(); 
-				hhPos = hh.GetBuffPos(); 
-			}
-		#endif
+	#ifdef __PGFROISUPPORT__
+		const bool storePos = wquot < ll.BufferWidth();
+		UINT32 llPos = 0, hlPos = 0, lhPos = 0, hhPos = 0;
+
+		if (storePos) {
+			// save current src buffer positions
+			llPos = ll.GetBuffPos();
+			hlPos = hl.GetBuffPos();
+			lhPos = lh.GetBuffPos();
+			hhPos = hh.GetBuffPos();
+		}
+	#endif
 
 		for (i=0; i < wquot; i++) {
 			*loRow++ = ll.ReadBuffer();// first access, than increment
@@ -422,26 +428,27 @@
 			*hiRow++ = lh.ReadBuffer();// first access, than increment
 		}
 
-		#ifdef __PGFROISUPPORT__
-			if (wquot < ll.BufferWidth()) {
-				// increment src buffer positions
-				ll.IncBuffRow(llPos); 
-				hl.IncBuffRow(hlPos); 
-				lh.IncBuffRow(lhPos); 
-				hh.IncBuffRow(hhPos); 
-			}
-		#endif
+	#ifdef __PGFROISUPPORT__
+		if (storePos) {
+			// increment src buffer positions
+			ll.IncBuffRow(llPos);
+			hl.IncBuffRow(hlPos);
+			lh.IncBuffRow(lhPos);
+			hh.IncBuffRow(hhPos);
+		}
+	#endif
 
 	} else {
-		#ifdef __PGFROISUPPORT__
-			UINT32 llPos, hlPos;
-
-			if (wquot < ll.BufferWidth()) {
-				// save current src buffer positions
-				llPos = ll.GetBuffPos(); 
-				hlPos = hl.GetBuffPos(); 
-			}
-		#endif
+	#ifdef __PGFROISUPPORT__
+		const bool storePos = wquot < ll.BufferWidth();
+		UINT32 llPos = 0, hlPos = 0;
+
+		if (storePos) {
+			// save current src buffer positions
+			llPos = ll.GetBuffPos();
+			hlPos = hl.GetBuffPos();
+		}
+	#endif
 
 		for (i=0; i < wquot; i++) {
 			*loRow++ = ll.ReadBuffer();// first access, than increment
@@ -449,13 +456,13 @@
 		}
 		if (wrem) *loRow++ = ll.ReadBuffer();
 
-		#ifdef __PGFROISUPPORT__
-			if (wquot < ll.BufferWidth()) {
-				// increment src buffer positions
-				ll.IncBuffRow(llPos); 
-				hl.IncBuffRow(hlPos); 
-			}
-		#endif
+	#ifdef __PGFROISUPPORT__
+		if (storePos) {
+			// increment src buffer positions
+			ll.IncBuffRow(llPos);
+			hl.IncBuffRow(hlPos);
+		}
+	#endif
 	}
 }
 
@@ -510,7 +517,7 @@
 /////////////////////////////////////////////////////////////////////
 void CROIs::CreateROIs() {
 	if (!m_ROIs) {
-		// create ROIs 
+		// create ROIs
 		m_ROIs = new PGFRect[m_nLevels];
 	}
 }
@@ -518,7 +525,7 @@
 /////////////////////////////////////////////////////////////////////
 void CROIs::CreateIndices() {
 	if (!m_indices) {
-		// create tile indices 
+		// create tile indices
 		m_indices = new PGFRect[m_nLevels];
 	}
 }

Modified: trunk/Scribus/scribus/third_party/pgf/WaveletTransform.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16771&path=/trunk/Scribus/scribus/third_party/pgf/WaveletTransform.h
==============================================================================
--- trunk/Scribus/scribus/third_party/pgf/WaveletTransform.h (original)
+++ trunk/Scribus/scribus/third_party/pgf/WaveletTransform.h Mon Aug  8 18:19:05 2011
@@ -1,25 +1,30 @@
 /*
  * The Progressive Graphics File; http://www.libpgf.org
- * 
+ *
  * $Date: 2006-05-18 16:03:32 +0200 (Do, 18 Mai 2006) $
  * $Revision: 194 $
- * 
+ *
  * This file Copyright (C) 2006 xeraina GmbH, Switzerland
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
  * as published by the Free Software Foundation; either version 2.1
  * of the License, or (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
+
+//////////////////////////////////////////////////////////////////////
+/// @file WaveletTransform.h
+/// @brief PGF wavelet transform class
+/// @author C. Stamm
 
 #ifndef PGF_WAVELETTRANSFORM_H
 #define PGF_WAVELETTRANSFORM_H
@@ -36,6 +41,7 @@
 //////////////////////////////////////////////////////////////////////
 /// PGF ROI and tile support. This is a helper class for CWaveletTransform.
 /// @author C. Stamm
+/// @brief ROI and tile support
 class CROIs {
 	friend class CWaveletTransform;
 
@@ -82,6 +88,7 @@
 //////////////////////////////////////////////////////////////////////
 /// PGF wavelet transform class.
 /// @author C. Stamm, R. Spuler
+/// @brief PGF wavelet transform
 class CWaveletTransform {
 	friend class CSubband;
 
@@ -97,7 +104,7 @@
 	//////////////////////////////////////////////////////////////////////
 	/// Destructor
 	~CWaveletTransform() { Destroy(); }
-	
+
 	//////////////////////////////////////////////////////////////////////
 	/// Compute fast forward wavelet transform of LL subband at given level and
 	/// stores result on all 4 subbands of level + 1.
@@ -121,7 +128,7 @@
 		ASSERT(level >= 0 && level < m_nLevels);
 		return &m_subband[level][orientation];
 	}
-	
+
 #ifdef __PGFROISUPPORT__
 	//////////////////////////////////////////////////////////////////////
 	/// Compute and store ROIs for each level
@@ -150,9 +157,9 @@
 #endif // __PGFROISUPPORT__
 
 private:
-	void Destroy() { delete[] m_subband; m_subband = 0; 
+	void Destroy() { delete[] m_subband; m_subband = 0;
 		#ifdef __PGFROISUPPORT__
-		m_ROIs.Destroy(); 
+		m_ROIs.Destroy();
 		#endif
 	}
 	void InitSubbands(UINT32 width, UINT32 height, DataT* data);
@@ -166,7 +173,7 @@
 #endif //__PGFROISUPPORT__
 
 	int			m_nLevels;						// number of transform levels: one more than the number of level in PGFimage
-	CSubband	(*m_subband)[NSubbands];		// quadtree of subbands: LL HL												
+	CSubband	(*m_subband)[NSubbands];		// quadtree of subbands: LL HL
 												//                       LH HH
 };
 




More information about the scribus-commit mailing list