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