Skip to content
Browse files

Committed all changes.

  • Loading branch information...
1 parent d0396ad commit 5ba2bca88820a0aaecc7eb4d15635a3331a4d96b @thorfdbg committed Sep 23, 2012
View
10 codestream/Makefile
@@ -1,5 +1,5 @@
##
-## $Id: Makefile,v 1.27 2012-07-29 17:00:39 thor Exp $
+## $Id: Makefile,v 1.34 2012-09-23 12:58:39 thor Exp $
##
## Makefile for the jpeg transcoder project,
## THOR Software, May 20, 2012, Thomas Richter
@@ -9,12 +9,10 @@
##
FILES = encoder decoder tables image entropyparser rectanglerequest \
- sequentialscan differentialscan \
- acsequentialscan acdifferentialsequentialscan \
- losslessscan differentiallosslessscan \
- aclosslessscan acdifferentiallosslessscan \
+ sequentialscan acsequentialscan \
+ predictivescan losslessscan aclosslessscan \
refinementscan acrefinementscan \
- residualscan residualhuffmanscan \
+ hiddenrefinementscan \
jpeglsscan singlecomponentlsscan lineinterleavedlsscan \
sampleinterleavedlsscan vesascan
View
8 coding/qmcoder.cpp
@@ -47,7 +47,7 @@ the committee itself.
* The Art-Deco (MQ) decoder and encoder as specified by the jpeg2000
* standard, FDIS, Annex C
*
- * $Id: qmcoder.cpp,v 1.15 2012-07-25 14:06:55 thor Exp $
+ * $Id: qmcoder.cpp,v 1.18 2012-09-09 21:36:13 thor Exp $
*
*/
@@ -275,9 +275,9 @@ void QMCoder::ByteIn(void)
if (b == 0xff) {
// Might be a marker - or not.
m_pIO->LastUnDo();
- if (m_pIO->PeekMarker() == 0xff00) {
+ if (m_pIO->PeekWord() == 0xff00) {
// What is expected, a byte-stuffed 0x00
- m_pIO->Get();m_pIO->Get();
+ m_pIO->GetWord();
m_ulC |= 0xff00; //+ would also work.
} else {
// Since the encoder drops 0x00 bytes, we need to fit
@@ -296,7 +296,7 @@ void QMCoder::ByteIn(void)
bool QMCoder::Get(class QMContext &ctxt)
{
ULONG q = Qe_Value[ctxt.m_ucIndex];
- bool d;
+ bool d; // true on lps
m_ulA -= q;
if ((m_ulC >> 16) < m_ulA) {
View
4 dct/Makefile
@@ -1,5 +1,5 @@
##
-## $Id: Makefile,v 1.6 2012-07-24 19:36:45 thor Exp $
+## $Id: Makefile,v 1.7 2012-09-15 17:27:27 thor Exp $
##
## Makefile for the jpeg transcoder project,
## THOR Software, May 20, 2012, Thomas Richter
@@ -8,7 +8,7 @@
## directory.
##
-FILES = dct idct fdct sermsdct hadamard
+FILES = dct idct sermsdct hadamard
DIRNAME = dct
SUPER = ../
View
13 interface/jpeg.cpp
@@ -51,7 +51,7 @@ the committee itself.
** for the 10918 (JPEG) codec. Except for the tagitem and hook methods,
** no other headers should be publically accessible.
**
-** $Id: jpeg.cpp,v 1.5 2012-07-17 21:33:33 thor Exp $
+** $Id: jpeg.cpp,v 1.6 2012-09-16 17:28:40 thor Exp $
**
*/
@@ -269,6 +269,17 @@ void JPEG::ReadInternal(struct JPG_TagItem *tags)
m_pScan = m_pFrame->StartParseScan(m_pIOStream);
if (m_pScan && (stopflags & JPGFLAG_DECODER_STOP_SCAN))
return;
+ if (m_pScan == NULL) {
+ if (!m_pFrame->ParseTrailer(m_pIOStream)) {
+ // Frame done, advance to the next frame.
+ m_pFrame = NULL;
+ if (!m_pImage->ParseTrailer(m_pIOStream)) {
+ // Image done, stop decoding, image is now loaded.
+ m_bDecoding = false;
+ return;
+ }
+ }
+ }
}
if (m_pScan) {
View
8 interface/parameters.hpp
@@ -48,7 +48,7 @@ the committee itself.
* client application to define all the parameters the jpeg library
* needs.
*
- * $Id: parameters.hpp,v 1.22 2012-07-29 17:00:39 thor Exp $
+ * $Id: parameters.hpp,v 1.25 2012-09-15 10:11:41 thor Exp $
*
* These parameters are specified by the user upon invocation of
* the library.
@@ -133,7 +133,6 @@ the committee itself.
//
// Binary-or this to use an optimized huffman process.
#define JPGFLAG_OPTIMIZE_HUFFMAN 128
-
//
// Definition of the 'quality' factor of JPEG if finetuning of the quantization
// parameters is not desirable. Defines a quality factor from 1 to 100
@@ -223,6 +222,11 @@ the committee itself.
// performance but improvides the visual performance of the image.
#define JPGTAG_IMAGE_ENABLE_NOISESHAPING (JPGTAG_IMAGE_BASE + 0x11)
//
+// Define the number of hidden DCT bits. These bits of the quantized
+// DCT coefficients are encoded in a side-channel not visible to the
+// traditional JPEG decoder but they help to improve the accuracy.
+#define JPGTAG_IMAGE_HIDDEN_DCTBITS (JPGTAG_IMAGE_BASE + 0x12)
+//
// Parameters defining the HDR mapping procedure. This defines up to four tone mapping curves
// one per component (the code could do more, but the interface is currently limited)
// Each tag is a pointer to 256 UWORDs each defining the HDR level for a given LDR level.
View
6 io/bitstream.hpp
@@ -47,7 +47,7 @@ the committee itself.
** This class allows to read individual bits from a stream of bytes.
** This class implements the bytestuffing as required.
**
-** $Id: bitstream.hpp,v 1.17 2012-07-19 14:13:38 thor Exp $
+** $Id: bitstream.hpp,v 1.18 2012-09-09 15:53:51 thor Exp $
**
*/
@@ -87,7 +87,7 @@ class BitStream : public JObject {
if (dt == 0xff) {
io->LastUnDo();
if (bitstuffing) {
- if (io->PeekMarker() < 0xff80) {
+ if (io->PeekWord() < 0xff80) {
// Bitstuffing.
io->Get();
m_ucB = dt;
@@ -101,7 +101,7 @@ class BitStream : public JObject {
dt = 0;
}
} else {
- if (io->PeekMarker() == 0xff00) {
+ if (io->PeekWord() == 0xff00) {
io->GetWord(); // Bytestuffing
} else {
// A marker. Do not advance over the marker, but
View
19 io/bytestream.cpp
@@ -47,7 +47,7 @@ the committee itself.
* Base class for all IO support functions, the abstract ByteStream
* class.
*
- * $Id: bytestream.cpp,v 1.2 2012-06-02 10:27:14 thor Exp $
+ * $Id: bytestream.cpp,v 1.3 2012-09-09 15:53:51 thor Exp $
*
*/
@@ -161,24 +161,15 @@ LONG ByteStream::SkipToMarker(UWORD marker1,UWORD marker2,
// check for the available marker now.
LastUnDo();
// And now seek for the marker.
- byte = PeekMarker();
+ byte = PeekWord();
if ((byte == marker1) || (byte == marker2) ||
(byte == marker3) || (byte == marker4) ||
(byte == marker5))
return byte;
//
- // Check whether this is an SOP. If so, skip its contents as
- // we are definitely not looking for marker segments within
- // SOP. This handles the most common case transparently.
- if (byte == 0xff91) {
- GetWord(); // pull the marker
- GetWord(); // pull segment size
- GetWord(); // pull counter
- } else {
- // otherwise, not the marker we seek for. Skip, and don't forget
- // to pull the 0xff we put back.
- Get();
- }
+ // otherwise, not the marker we seek for. Skip, and don't forget
+ // to pull the 0xff we put back.
+ Get();
}
}
}
View
8 io/bytestream.hpp
@@ -47,7 +47,7 @@ the committee itself.
* Base class for all IO support functions, the abstract ByteStream
* class.
*
- * $Id: bytestream.hpp,v 1.2 2012-06-02 10:27:14 thor Exp $
+ * $Id: bytestream.hpp,v 1.3 2012-09-09 15:53:51 thor Exp $
*
*/
@@ -83,7 +83,7 @@ also a file/byte counter. What the corresponding sub classes have
to do is just to implement methods for reading and writing complete
buffers, and to deliver status information.
-One special method, PeekMarker(), allows to read the next marker
+One special method, PeekWord(), allows to read the next marker
(two bytes) without advancing the file pointer. This is required
for some of the higher magic of the error resiliance features.
* */
@@ -160,10 +160,10 @@ class ByteStream : public JKeeper {
m_uqCounter = 0;
}
//
- // Peek the next marker in the stream, deliver the marker without
+ // Peek the next word in the stream, deliver the marker without
// advancing the file pointer. Deliver EOF in case we run into
// the end of the stream.
- virtual LONG PeekMarker(void) = 0;
+ virtual LONG PeekWord(void) = 0;
//
// Skip over bytes, ignore their contribution. The offset must
// be positive (or zero).
View
6 io/iostream.cpp
@@ -49,7 +49,7 @@ the committee itself.
** the back-end class to perform the real job getting bytes in and
** out of the library.
**
-** $Id: iostream.cpp,v 1.2 2012-06-02 10:27:14 thor Exp $
+** $Id: iostream.cpp,v 1.3 2012-09-09 15:53:51 thor Exp $
**
*/
@@ -535,12 +535,12 @@ void IOStream::Seek(QUAD newpos,LONG mode)
}
///
-/// IOStream::PeekMarker
+/// IOStream::PeekWord
// Peek the next marker in the stream, deliver the marker without
// advancing the file pointer. Deliver EOF in case we run into
// the end of the stream. This stream requires a specific implementation
// of the primitive.
-LONG IOStream::PeekMarker(void)
+LONG IOStream::PeekWord(void)
{
LONG byte1,byte2;
//
View
6 io/iostream.hpp
@@ -49,7 +49,7 @@ the committee itself.
** the back-end class to perform the real job getting bytes in and
** out of the library.
**
-** $Id: iostream.hpp,v 1.2 2012-06-02 10:27:14 thor Exp $
+** $Id: iostream.hpp,v 1.3 2012-09-09 15:53:51 thor Exp $
**
*/
@@ -145,11 +145,11 @@ class IOStream : public RandomAccessStream {
virtual void Flush(void);
virtual LONG Query(void);
//
- // Peek the next marker in the stream, deliver the marker without
+ // Peek the next word in the stream, deliver the marker without
// advancing the file pointer. Deliver JPG_EOF in case we run into
// the end of the stream. This stream requires a specific implementation
// of the primitive.
- virtual LONG PeekMarker(void);
+ virtual LONG PeekWord(void);
//
// SkipBytes skips bytes by either seeking over or, if that should turn
// out to be impossible, by continuously pulling nonsense out of the
View
6 io/memorystream.cpp
@@ -47,7 +47,7 @@ the committee itself.
* An implementation of the ByteStream class that reads/writes bytes
* to a "ram disk".
*
- * $Id: memorystream.cpp,v 1.5 2012-06-02 10:27:14 thor Exp $
+ * $Id: memorystream.cpp,v 1.6 2012-09-09 15:53:51 thor Exp $
*
*/
@@ -405,9 +405,9 @@ void MemoryStream::Clean(void)
}
///
-/// MemoryStream::PeekMarker
+/// MemoryStream::PeekWord
// Get the next two bytes without removing them from the stream.
-LONG MemoryStream::PeekMarker(void)
+LONG MemoryStream::PeekWord(void)
{
const UBYTE *ptr = m_pucBufPtr;
const UBYTE *end = m_pucBufEnd;
View
4 io/memorystream.hpp
@@ -47,7 +47,7 @@ the committee itself.
* An implementation of the ByteStream class that reads/writes bytes
* to a "ram disk".
*
- * $Id: memorystream.hpp,v 1.5 2012-06-02 10:27:14 thor Exp $
+ * $Id: memorystream.hpp,v 1.6 2012-09-09 15:53:51 thor Exp $
*
*/
@@ -156,7 +156,7 @@ class MemoryStream : public ByteStream {
ULONG Push(class ByteStream *dest,ULONG total);
//
// Get the next two bytes without removing them from the stream.
- virtual LONG PeekMarker(void);
+ virtual LONG PeekWord(void);
//
// Push contents of a different stream into a memory stream, i.e. write
// into the memory stream buffer by using bytes from another bytestream.
View
6 io/randomaccessstream.cpp
@@ -48,7 +48,7 @@ the committee itself.
** A random access IO stream that allows forwards and backwards
** seeking. This is an abstraction of the known "IOHook".
**
-** $Id: randomaccessstream.cpp,v 1.2 2012-06-02 10:27:14 thor Exp $
+** $Id: randomaccessstream.cpp,v 1.3 2012-09-09 15:53:51 thor Exp $
**
*/
@@ -57,10 +57,10 @@ the committee itself.
///
/// RandomAccessStream::PeekMarker
-// Peek the next marker in the stream, deliver the marker without
+// Peek the next word in the stream, deliver the marker without
// advancing the file pointer. Deliver EOF in case we run into
// the end of the stream.
-LONG RandomAccessStream::PeekMarker(void)
+LONG RandomAccessStream::PeekWord(void)
{
LONG byte1,byte2;
//
View
6 io/randomaccessstream.hpp
@@ -48,7 +48,7 @@ the committee itself.
** A random access IO stream that allows forwards and backwards
** seeking. This is an abstraction of the known "IOHook".
**
-** $Id: randomaccessstream.hpp,v 1.2 2012-06-02 10:27:14 thor Exp $
+** $Id: randomaccessstream.hpp,v 1.3 2012-09-09 15:53:51 thor Exp $
**
*/
@@ -99,12 +99,12 @@ class RandomAccessStream : public ByteStream {
virtual void Flush(void) = 0;
virtual LONG Query(void) = 0;
//
- // Peek the next marker in the stream, deliver the marker without
+ // Peek the next word in the stream, deliver the marker without
// advancing the file pointer. Deliver EOF in case we run into
// the end of the stream. This is already implemented here
// since its working does not depend on the specific implementation
// on top.
- virtual LONG PeekMarker(void);
+ virtual LONG PeekWord(void);
//
// SkipBytes skips bytes by either seeking over or, if that should turn
// out to be impossible, by continuously pulling nonsense out of the
View
6 io/staticstream.hpp
@@ -46,7 +46,7 @@ the committee itself.
/*
** An implementation of the ByteStream that reads from or writes to
** a static buffer allocated outside of this class.
-** $Id: staticstream.hpp,v 1.2 2012-06-02 10:27:14 thor Exp $
+** $Id: staticstream.hpp,v 1.3 2012-09-09 15:53:51 thor Exp $
**
*/
@@ -98,10 +98,10 @@ class StaticStream : public ByteStream {
return 0; // always success
}
//
- // Peek the next marker in the stream, deliver the marker without
+ // Peek the next word in the stream, deliver the marker without
// advancing the file pointer. Deliver EOF in case we run into
// the end of the stream.
- virtual LONG PeekMarker(void)
+ virtual LONG PeekWord(void)
{
if (m_pucBufPtr + 1 < m_pucBufEnd) {
return (m_pucBufPtr[0] << 8) | m_pucBufPtr[1];
View
4 marker/Makefile
@@ -1,5 +1,5 @@
##
-## $Id: Makefile,v 1.13 2012-07-19 18:59:12 thor Exp $
+## $Id: Makefile,v 1.14 2012-09-14 18:22:20 thor Exp $
##
## Makefile for the jpeg transcoder project,
## THOR Software, May 20, 2012, Thomas Richter
@@ -12,7 +12,7 @@ FILES = quantization huffmantable frame component scan \
adobemarker jfifmarker exifmarker \
residualmarker losslessmarker tonemappingmarker \
actable restartintervalmarker scantypes \
- thresholds lscolortrafo
+ thresholds lscolortrafo residualspecsmarker
DIRNAME = marker
SUPER = ../
View
7 marker/adobemarker.cpp
@@ -48,7 +48,7 @@ the committee itself.
** in APP14. Used here to indicate the color space and to avoid a color
** transformation.
**
-** $Id: adobemarker.cpp,v 1.3 2012-06-02 10:27:14 thor Exp $
+** $Id: adobemarker.cpp,v 1.4 2012-09-11 14:32:14 thor Exp $
**
*/
@@ -101,7 +101,6 @@ void AdobeMarker::WriteMarker(class ByteStream *io)
void AdobeMarker::ParseMarker(class ByteStream *io,UWORD len)
{
UWORD version;
- UWORD flags1,flags2;
LONG color;
if (len != 2 + 5 + 2 + 2 + 2 + 1)
@@ -111,8 +110,8 @@ void AdobeMarker::ParseMarker(class ByteStream *io,UWORD len)
if (version != 100) // Includes EOF
JPG_THROW(MALFORMED_STREAM,"AdobeMarker::ParseMarker","Adobe marker version unrecognized");
- flags1 = io->GetWord();
- flags2 = io->GetWord(); // ignored.
+ io->GetWord();
+ io->GetWord(); // ignored.
color = io->Get();
View
242 marker/frame.cpp
@@ -47,7 +47,7 @@ the committee itself.
**
** This class represents a single frame and the frame dimensions.
**
-** $Id: frame.cpp,v 1.75 2012-07-26 19:17:35 thor Exp $
+** $Id: frame.cpp,v 1.82 2012-09-23 14:10:12 thor Exp $
**
*/
@@ -59,6 +59,7 @@ the committee itself.
#include "codestream/tables.hpp"
#include "marker/scan.hpp"
#include "marker/residualmarker.hpp"
+#include "marker/residualspecsmarker.hpp"
#include "control/bitmapctrl.hpp"
#include "control/lineadapter.hpp"
#include "control/blockbitmaprequester.hpp"
@@ -75,7 +76,9 @@ Frame::Frame(class Tables *tables,ScanType t)
: JKeeper(tables->EnvironOf()), m_pNext(NULL), m_pTables(tables),
m_pScan(NULL), m_pLast(NULL), m_pCurrent(NULL), m_pImage(NULL),
m_pBlockHelper(NULL), m_Type(t), m_ucPrecision(0), m_ucDepth(0), m_ppComponent(NULL),
- m_bWriteDNL(false), m_bBuildResidual(false), m_bCreatedResidual(false)
+ m_bWriteDNL(false),
+ m_bBuildResidual(false), m_bCreatedResidual(false),
+ m_bBuildRefinement(false), m_bCreatedRefinement(false)
{
}
///
@@ -322,16 +325,24 @@ class Component *Frame::DefineComponent(UBYTE idx,UBYTE subx,UBYTE suby)
}
///
+/// Frame::HiddenPrecisionOf
+// Return the precision including the hidden bits.
+UBYTE Frame::HiddenPrecisionOf(void) const
+{
+ return m_ucPrecision + m_pTables->HiddenDCTBitsOf();
+}
+///
+
/// Frame::PointPreShiftOf
// Return the point preshift, the adjustment of the
// input samples by a shift that moves them into the
// limits of JPEG.
UBYTE Frame::PointPreShiftOf(void) const
{
if (m_pTables) {
- class ResidualMarker *resmarker;
+ class ResidualSpecsMarker *resmarker;
- if ((resmarker = m_pTables->ResidualDataOf())) {
+ if ((resmarker = m_pTables->ResidualSpecsOf())) {
return resmarker->PointPreShiftOf();
}
}
@@ -550,7 +561,7 @@ class Scan *Frame::InstallDefaultParameters(ULONG width,ULONG height,UBYTE depth
}
//
// Create a residual scan?
- if (m_pTables->ResidualDataOf()) {
+ if (m_pTables->UseResiduals()) {
switch(m_Type) {
case Lossless:
case ACLossless:
@@ -571,10 +582,60 @@ class Scan *Frame::InstallDefaultParameters(ULONG width,ULONG height,UBYTE depth
break;
default:
// Make the first scan a residual scan.
- class Scan *scan = new(m_pEnviron) class Scan(this);
- scan->TagOn(m_pScan);
- m_pScan = scan;
- scan->MakeResidualScan();
+ {
+ UBYTE component = m_ucDepth;
+ class Scan *scan;
+ do {
+ component--;
+ scan = new(m_pEnviron) class Scan(this);
+ scan->TagOn(m_pScan);
+ m_pScan = scan;
+ scan->MakeResidualScan(ComponentOf(component));
+ } while(component);
+ }
+ break;
+ }
+ }
+ if (m_pTables->UseRefinements()) {
+ switch(m_Type) {
+ case Lossless:
+ case ACLossless:
+ case JPEG_LS:
+ JPG_THROW(INVALID_PARAMETER,"Frame::InstallDefaultScanParameters",
+ "the lossless scans do not support hidden refinement scans");
+ break;
+ case DifferentialSequential:
+ case DifferentialProgressive:
+ case DifferentialLossless:
+ case ACDifferentialSequential:
+ case ACDifferentialProgressive:
+ case ACDifferentialLossless:
+ // Hmm. At this time, simply disallow. There is probably a way how to fit this into
+ // the highest hierarchical level, but not now.
+ JPG_THROW(NOT_IMPLEMENTED,"Frame::InstallDefaultScanParameters",
+ "the hierarchical mode does not yet allow hidden refinement coding");
+ break;
+ default:
+ // Create hidden refinement scans.
+ {
+ UBYTE hiddenbits;
+ UBYTE component;
+ class Scan *scan;
+ for(hiddenbits = 0;hiddenbits < m_pTables->HiddenDCTBitsOf();hiddenbits++) {
+ component = m_ucDepth;
+ do {
+ component--;
+ scan = new(m_pEnviron) class Scan(this);
+ scan->TagOn(m_pScan);
+ m_pScan = scan;
+ scan->MakeHiddenRefinementACScan(hiddenbits,ComponentOf(component));
+ } while(component);
+ scan = new(m_pEnviron) class Scan(this);
+ scan->TagOn(m_pScan);
+ m_pScan = scan;
+ scan->MakeHiddenRefinementDCScan(hiddenbits);
+ }
+ }
break;
}
}
@@ -587,18 +648,11 @@ class Scan *Frame::InstallDefaultParameters(ULONG width,ULONG height,UBYTE depth
class Scan *Frame::StartParseScan(class ByteStream *io)
{
class Scan *scan;
- LONG data;
if (m_pImage == NULL)
JPG_THROW(OBJECT_DOESNT_EXIST,"Frame::StartParseScan",
"frame is currently not available for parsing");
- // If there is a residual marker, and this is the final scan,
- // build it now. There are then no tables anymore.
- if (!m_bBuildResidual) {
- m_pTables->ParseTables(io);
- }
-
scan = new(m_pEnviron) class Scan(this);
if (m_pScan == NULL) {
@@ -614,48 +668,82 @@ class Scan *Frame::StartParseScan(class ByteStream *io)
//
// If there is a residual marker, and this is the final scan,
// build it now.
- if (m_bBuildResidual && !m_bCreatedResidual) {
+ if (m_bBuildRefinement && !m_bCreatedRefinement) {
+ assert(m_pTables->RefinementDataOf());
+ class ByteStream *stream = m_pTables->RefinementDataOf()->StreamOf();
+ //
+ // De-activate unless re-activated on the next scan/trailer.
+ m_pTables->ParseTables(stream);
+ m_bBuildRefinement = false;
+ if (ScanForScanHeader(stream)) {
+ scan->StartParseHiddenRefinementScan(m_pImage);
+ return scan;
+ }
+ } else if (m_bBuildResidual && !m_bCreatedResidual) {
+ assert(m_pTables->ResidualDataOf());
+ class ByteStream *stream = m_pTables->ResidualDataOf()->StreamOf();
class BlockBitmapRequester *bb = dynamic_cast<class BlockBitmapRequester *>(m_pImage);
- assert(m_pImage && bb && m_pTables->ResidualDataOf());
- if (m_pBlockHelper == NULL)
+ assert(stream && bb);
+ //
+ // De-activate unless re-activated on the next scan/trailer.
+ m_pTables->ParseTables(stream);
+ if (m_pBlockHelper == NULL)
m_pBlockHelper = new(m_pEnviron) class ResidualBlockHelper(this);
bb->SetBlockHelper(m_pBlockHelper);
- scan->MakeResidualScan();
- //
- // Only one residual, do not come again.
- m_bCreatedResidual = true;
+
+ m_bBuildResidual = false;
+ if (ScanForScanHeader(stream)) {
+ scan->StartParseResidualScan(m_pImage);
+ return scan;
+ }
} else {
- data = io->GetWord();
- if (data != 0xffda) {
- JPG_WARN(MALFORMED_STREAM,"Frame::StartScan","Start of Scan SOS marker missing");
- if (data == ByteStream::EOF)
- return NULL;
- // Advance to the next marker if there is something next.
- //
- do {
- io->LastUnDo();
- do {
- data = io->Get();
- } while(data != 0xff && data != ByteStream::EOF);
- //
- if (data == ByteStream::EOF)
- return NULL; // unparsed.
- io->LastUnDo();
- //
- // If this is SOS, we recovered. Maybe.
- data = io->GetWord();
- if (data == ByteStream::EOF)
- return NULL; // unparsed
- // Check for the proper marker.
- } while(data != 0xffda);
+ // Regular scan.
+ m_pTables->ParseTables(io);
+ //
+ if (ScanForScanHeader(io)) {
+ scan->ParseMarker(io);
+ scan->StartParseScan(io,m_pImage);
+ return scan;
}
+ }
+
+ return NULL;
+}
+///
+
+/// Frame::ScanForScanHeader
+// Start parsing a hidden scan, let it be either the residual or the refinement
+// scan.
+bool Frame::ScanForScanHeader(class ByteStream *stream)
+{
+ LONG data;
+
+
+ //
+ data = stream->GetWord();
+ if (data != 0xffda) {
+ JPG_WARN(MALFORMED_STREAM,"Frame::StartParseHiddenScan","Start of Scan SOS marker missing");
+ // Advance to the next marker if there is something next.
//
- // Create a buffer for the image.
- scan->ParseMarker(io);
+ do {
+ stream->LastUnDo();
+ do {
+ data = stream->Get();
+ } while(data != 0xff && data != ByteStream::EOF);
+ //
+ if (data == ByteStream::EOF)
+ break; // Try from the main stream
+ stream->LastUnDo();
+ //
+ // If this is SOS, we recovered. Maybe.
+ data = stream->GetWord();
+ if (data == ByteStream::EOF)
+ break;
+ // Check for the proper marker.
+ } while(data != 0xffda);
}
- scan->StartParseScan(io,m_pImage);
- return scan;
+ return (data == 0xffda)?(true):(false);
}
///
@@ -726,7 +814,7 @@ void Frame::WriteFrameType(class ByteStream *io) const
bool Frame::ParseTrailer(class ByteStream *io)
{
do {
- LONG marker = io->PeekMarker();
+ LONG marker = io->PeekWord();
switch(marker) {
case 0xffc0:
@@ -752,18 +840,54 @@ bool Frame::ParseTrailer(class ByteStream *io)
// All differential frame starts: The frame ends here.
// If we have a residual scan that is not yet parsed off,
// create it now and parse it last so it sees the original
- // data.
- if (m_pTables->ResidualDataOf() && !m_bCreatedResidual) {
+ // data.
+ if (m_pTables->RefinementDataOf() && !m_bCreatedRefinement) {
assert(m_pImage);
if (dynamic_cast<class BlockBitmapRequester *>(m_pImage)) {
- m_bBuildResidual = true;
- //
- // Come here again when the residual is parsed off
- return true;
+ LONG data;
+ do {
+ data = m_pTables->RefinementDataOf()->StreamOf()->PeekWord();
+ if (data == 0xffff) {
+ m_pTables->RefinementDataOf()->StreamOf()->Get(); // Filler byte
+ }
+ } while(data == 0xffff);
+ if (data != ByteStream::EOF && data != 0xffd9) {
+ m_bBuildRefinement = true;
+ //
+ // Come here again when the refinement is parsed off.
+ return true;
+ } else {
+ // Do not come again, refinement is there already.
+ m_bCreatedRefinement = true;
+ }
+ }
+ }
+ if (m_pTables->ResidualDataOf() && !m_bCreatedResidual) {
+ assert(m_pImage);
+ if (dynamic_cast<class BlockBitmapRequester *>(m_pImage)) {
+ LONG data;
+ do {
+ data = m_pTables->ResidualDataOf()->StreamOf()->PeekWord();
+ if (data == 0xffff) {
+ m_pTables->ResidualDataOf()->StreamOf()->Get(); // Filler byte
+ }
+ } while(data == 0xffff);
+ if (data != ByteStream::EOF && data != 0xffd9) {
+ m_bBuildResidual = true;
+ //
+ // Come here again when the residual is parsed off.
+ return true;
+ } else {
+ // Do not come again, refinement is there already.
+ m_bCreatedResidual = true;
+ }
}
}
- //
return false;
+ case 0xffff:
+ // A filler byte. Remove the filler, try again.
+ io->Get();
+ break;
case 0xffd0:
case 0xffd1:
case 0xffd2:
@@ -823,6 +947,8 @@ class LineAdapter *Frame::BuildLineAdapter(void)
case ACProgressive:
case ACDifferentialSequential:
case ACDifferentialProgressive:
+ case Residual:
+ case ACResidual:
return new(m_pEnviron) class BlockLineAdapter(this); // all block based.
case Lossless:
case ACLossless:
View
13 marker/frame.hpp
@@ -47,7 +47,7 @@ the committee itself.
**
** This class represents a single frame and the frame dimensions.
**
-** $Id: frame.hpp,v 1.43 2012-06-12 15:04:30 thor Exp $
+** $Id: frame.hpp,v 1.46 2012-09-23 12:58:39 thor Exp $
**
*/
@@ -131,6 +131,10 @@ class Frame : public JKeeper {
// Has the residual scan already been created?
bool m_bCreatedResidual;
//
+ // The same logic for hidden DCT refinement scans.
+ bool m_bBuildRefinement;
+ bool m_bCreatedRefinement;
+ //
// Compute the largest common denominator of a and b.
static int gcd(int a,int b)
{
@@ -151,6 +155,10 @@ class Frame : public JKeeper {
// Compute the MCU sizes of the components from the subsampling values
void ComputeMCUSizes(void);
//
+ // Start parsing a scan. Returns true if the scan start is found and there is another hidden
+ // scan. Returns false otherwise.
+ bool ScanForScanHeader(class ByteStream *stream);
+ //
public:
// This requires a type identifier.
Frame(class Tables *tables,ScanType t);
@@ -210,6 +218,9 @@ class Frame : public JKeeper {
return m_ucPrecision;
}
//
+ // Return the precision including the hidden bits.
+ UBYTE HiddenPrecisionOf(void) const;
+ //
// Return the point preshift, the adjustment of the
// input samples by a shift that moves them into the
// limits of JPEG.
View
7 marker/jfifmarker.cpp
@@ -47,7 +47,7 @@ the committee itself.
** This class represents the JFIF, placed in APP0.
** This is only used to indicate a JFIF file and is otherwise unused.
**
-** $Id: jfifmarker.cpp,v 1.1 2012-06-10 21:46:05 thor Exp $
+** $Id: jfifmarker.cpp,v 1.2 2012-09-11 14:32:14 thor Exp $
**
*/
@@ -107,14 +107,13 @@ void JFIFMarker::WriteMarker(class ByteStream *io)
// the exception.
void JFIFMarker::ParseMarker(class ByteStream *io,UWORD len)
{
- UBYTE version,revision;
UBYTE unit;
if (len < 2 + 5 + 2 + 1 + 2 + 2 + 1 + 1)
JPG_THROW(MALFORMED_STREAM,"JFIFMarker::ParseMarker","misformed JFIF marker");
- version = io->Get();
- revision = io->Get();
+ io->Get(); // version
+ io->Get(); // revision
//
// Currently ignore.
View
4 marker/quantization.cpp
@@ -46,7 +46,7 @@ the committee itself.
/*
** This class represents the quantization tables.
**
-** $Id: quantization.cpp,v 1.17 2012-07-29 17:00:39 thor Exp $
+** $Id: quantization.cpp,v 1.18 2012-09-23 19:27:16 thor Exp $
**
*/
@@ -218,7 +218,7 @@ void Quantization::InitDefaultTables(UBYTE quality,UBYTE hdrquality,bool colortr
if (delta > 32767)
delta = 32767;
if (i == 3 && delta > 1) // The range of the chroma components was extended by one extra bit.
- delta >>= 1;
+ delta <<= 1;
m_pDelta[i][j] = delta;
}
} else {
View
92 marker/residualmarker.cpp
@@ -48,7 +48,7 @@ the committee itself.
** information to make JPEG lossless or to support high-bitrange
** without loosing compatibility.
**
-** $Id: residualmarker.cpp,v 1.9 2012-07-26 19:17:35 thor Exp $
+** $Id: residualmarker.cpp,v 1.12 2012-09-23 12:58:39 thor Exp $
**
*/
@@ -59,9 +59,9 @@ the committee itself.
///
/// ResidualMarker::ResidualMarker
-ResidualMarker::ResidualMarker(class Environ *env)
- : JKeeper(env), m_pBuffer(NULL), m_pReadBack(NULL),
- m_ucQuantization(0), m_ucPreshift(0), m_ucToneEnable(0)
+ResidualMarker::ResidualMarker(class Environ *env,MarkerType type)
+ : JKeeper(env), m_pBuffer(NULL), m_pReadBack(NULL),
+ m_Type(type)
{
}
///
@@ -81,40 +81,14 @@ ResidualMarker::~ResidualMarker(void)
// the exception.
void ResidualMarker::ParseMarker(class ByteStream *io,UWORD len)
{
- UWORD extra = 0;
- if (len < 2 + 4 + 1 + 2 + 1) // Marker length, identifier, plus error
- JPG_THROW(MALFORMED_STREAM,"ResidualMarker::ParseMarker","APP9 residual information marker size too short");
-
- m_ucPreshift = io->Get();
- m_ucQuantization = io->Get();
-
- m_ucToneEnable = m_ucPreshift >> 4;
- m_ucPreshift &= 0x0f;
-
- if (m_ucToneEnable & 0x01)
- extra++;
- if (m_ucToneEnable & 0x02)
- extra++;
- if (m_ucToneEnable & 0x04)
- extra++;
- if (m_ucToneEnable & 0x08)
- extra++;
- if (len < extra)
- JPG_THROW(MALFORMED_STREAM,"ResidualMarker::ParseMarker","APP9 residual information marker size too short");
-
- if (m_ucToneEnable & 0x01)
- m_ucToneMapping[0] = io->Get();
- if (m_ucToneEnable & 0x02)
- m_ucToneMapping[1] = io->Get();
- if (m_ucToneEnable & 0x04)
- m_ucToneMapping[2] = io->Get();
- if (m_ucToneEnable & 0x08)
- m_ucToneMapping[3] = io->Get();
+ if (len < 2 + 4 + 2) // Marker length, identifier, plus error
+ JPG_THROW(MALFORMED_STREAM,"ResidualMarker::ParseMarker",
+ "APP9 residual data marker size too short");
if (m_pBuffer == NULL)
m_pBuffer = new(m_pEnviron) class MemoryStream(m_pEnviron);
- len -= 2 + 4 + 1 + 2 + 1 + extra;
+ len -= 2 + 4 + 2;
m_pBuffer->Append(io,len);
}
///
@@ -133,8 +107,7 @@ class ByteStream *ResidualMarker::StreamOf(void)
///
/// ResidualMarker::WriteMarker
-// Write the marker, where the raw data comes buffered from the
-// indicated memory stream.
+// Write the marker as hidden refinement scan marker.
void ResidualMarker::WriteMarker(class ByteStream *target,class MemoryStream *src)
{
class MemoryStream readback(m_pEnviron,src,JPGFLAG_OFFSET_BEGINNING);
@@ -143,15 +116,7 @@ void ResidualMarker::WriteMarker(class ByteStream *target,class MemoryStream *sr
while(bytes) {
ULONG write = bytes;
- UWORD extradata = 2 + 4 + 1 + 2 + 1;
- if (m_ucToneEnable & 0x01)
- extradata++;
- if (m_ucToneEnable & 0x02)
- extradata++;
- if (m_ucToneEnable & 0x04)
- extradata++;
- if (m_ucToneEnable & 0x08)
- extradata++;
+ UWORD extradata = 2 + 4 + 2;
if (write > ULONG(MAX_UWORD - extradata)) {
write = MAX_UWORD - extradata;
@@ -161,32 +126,23 @@ void ResidualMarker::WriteMarker(class ByteStream *target,class MemoryStream *sr
// Write the ID
target->Put('J');
target->Put('P');
- target->Put('R');
- target->Put('E');
- target->Put('S');
- target->Put('I');
- target->Put(m_ucPreshift | (m_ucToneEnable << 4));
- target->Put(m_ucQuantization);
-
- if (m_ucToneEnable & 0x01)
- target->Put(m_ucToneMapping[0]);
- if (m_ucToneEnable & 0x02)
- target->Put(m_ucToneMapping[1]);
- if (m_ucToneEnable & 0x04)
- target->Put(m_ucToneMapping[2]);
- if (m_ucToneEnable & 0x08)
- target->Put(m_ucToneMapping[3]);
+ switch(m_Type) {
+ case Refinement:
+ target->Put('F');
+ target->Put('I');
+ target->Put('N');
+ target->Put('E');
+ break;
+ case Residual:
+ target->Put('R');
+ target->Put('E');
+ target->Put('S');
+ target->Put('I');
+ break;
+ }
readback.Push(target,write);
bytes -= write;
}
}
///
-
-/// ResidualMarker::InstallPreshift
-// Install parameters - here only the maximum coding error.
-void ResidualMarker::InstallPreshift(UBYTE preshift)
-{
- m_ucPreshift = preshift;
-}
-///
View
136 marker/residualmarker.hpp
@@ -48,7 +48,7 @@ the committee itself.
** information to make JPEG lossless or to support high-bitrange
** without loosing compatibility.
**
-** $Id: residualmarker.hpp,v 1.10 2012-07-29 17:00:39 thor Exp $
+** $Id: residualmarker.hpp,v 1.13 2012-09-23 12:58:39 thor Exp $
**
*/
@@ -66,38 +66,31 @@ class ByteStream;
///
/// class ResidualMarker
-// This class collects color space information conforming to the
-// Residual APP9 marker.
+// This marker carries the residual information itself.
class ResidualMarker : public JKeeper {
//
+public:
+ // Marker types.
+ enum MarkerType {
+ Residual,
+ Refinement
+ };
+ //
+private:
//
// Memory stream containing the residual data.
class MemoryStream *m_pBuffer;
//
// The readback for the above buffer.
class MemoryStream *m_pReadBack;
//
- // Quantization parameter for the extensions marker.
- // Bit 7 is the enable bit (separate quantization),
- // Bits 5,4: Chroma table, bits 0,1: Luma table.
- UBYTE m_ucQuantization;
- //
- // The preshift value for HD coding. Zero for no preshift.
- // This allows coding of >8 or != 12bpp images with traditional
- // JPEG by pushing the LSBs into this marker.
- UBYTE m_ucPreshift;
- //
- // The following flags define which tone mapping curve is enabled.
- // If disabled, preshifting is used.
- UBYTE m_ucToneEnable;
- //
- // The tone mapping curves: This gives for each component X the tone mapping
- // table index.
- UBYTE m_ucToneMapping[4];
+ MarkerType m_Type;
//
public:
- //
- ResidualMarker(class Environ *env);
+ //
+ // Create a residual marker. Depending on the second argument, this
+ // is either a refinement marker (true) or a residual marker (false).
+ ResidualMarker(class Environ *env,MarkerType type);
//
~ResidualMarker(void);
//
@@ -110,104 +103,7 @@ class ResidualMarker : public JKeeper {
// Return the buffered data as a parseable bytestream.
class ByteStream *StreamOf(void);
//
- // Return the point preshift, an additional upshift on reconstruction
- // that allows coding of high dynamic range images by traditional
- // JPEG.
- UBYTE PointPreShiftOf(void) const
- {
- return m_ucPreshift;
- }
- //
- // Return an indicator whether tone mapping is enabled for the i'th
- // component.
- bool isToneMapped(UBYTE comp) const
- {
- assert(comp < 4);
-
- return (m_ucToneEnable & (1 << comp))?true:false;
- }
- //
- // Return the index of the tone mapping curve for the i'th component
- // if there is one. (Check first!)
- UBYTE ToneMappingTableOf(UBYTE comp) const
- {
- assert(comp < 4);
- assert(m_ucToneEnable & (1 << comp));
-
- return m_ucToneMapping[comp];
- }
- //
- // Install parameters - here only the maximum coding error.
- void InstallPreshift(UBYTE preshift);
- //
- // Install the tone mapping for component X to use the table Y.
- void InstallToneMapping(UBYTE comp,UBYTE table)
- {
- assert(comp < 4);
-
- m_ucToneEnable |= (1 << comp);
- m_ucToneMapping[comp] = table;
- }
- //
- // Install the quantization parameters for luma and chroma
- // for the extensions layer. The arguments are the quantization
- // tables for both luma and chroma.
- void InstallQuantization(UBYTE luma,UBYTE chroma)
- {
- m_ucQuantization &= ~0x33;
- m_ucQuantization = 0x80 | (luma) | (chroma << 4);
- }
- //
- // Install the hadamard transformation parameter.
- void InstallHadamardTrafo(bool enable)
- {
- m_ucQuantization &= ~0x08;
- if (enable)
- m_ucQuantization |= 0x08;
- }
- //
- // Install the noise shaping option.
- void InstallNoiseShaping(bool enable)
- {
- m_ucQuantization &= ~0x04;
- if (enable)
- m_ucQuantization |= 0x04;
- }
- //
- // Return the chroma quantization matrix index or MAX_UBYTE if it
- // is not defined.
- UBYTE ChromaQuantizationMatrix(void) const
- {
- if (m_ucQuantization & 0x80) {
- return (m_ucQuantization >> 4) & 0x03;
- }
- return MAX_UBYTE;
- }
- //
- // Return the luma quantization matrix index or MAX_UBYTE if it is
- // not defined.
- UBYTE LumaQuantizationMatrix(void) const
- {
- if (m_ucQuantization & 0x80) {
- return m_ucQuantization & 0x03;
- }
- return MAX_UBYTE;
- }
- //
- // Return an indicator whether the Hadamard transformation shall be run.
- bool isHadamardEnabled(void) const
- {
- return (m_ucQuantization & 0x08)?true:false;
- }
- //
- // Return an indicator whether noise shaping is enabled.
- bool isNoiseShapingEnabled(void) const
- {
- return (m_ucQuantization & 0x04)?true:false;
- }
- //
- // Get the quantization
- // Write the marker, where the raw data comes buffered from the
+ // Write the marker as residual marker, where the raw data comes buffered from the
// indicated memory stream.
void WriteMarker(class ByteStream *io,class MemoryStream *src);
};
View
315 marker/scan.cpp
@@ -47,29 +47,25 @@ the committee itself.
**
** Represents all data in a single scan, and hence is the SOS marker.
**
-** $Id: scan.cpp,v 1.65 2012-08-17 08:22:56 thor Exp $
+** $Id: scan.cpp,v 1.75 2012-09-23 14:10:12 thor Exp $
**
*/
/// Includes
#include "marker/scan.hpp"
+#include "marker/residualmarker.hpp"
#include "io/bytestream.hpp"
#include "marker/frame.hpp"
#include "marker/component.hpp"
#include "codestream/tables.hpp"
#include "codestream/entropyparser.hpp"
#include "codestream/sequentialscan.hpp"
#include "codestream/acsequentialscan.hpp"
-#include "codestream/acdifferentialsequentialscan.hpp"
-#include "codestream/residualscan.hpp"
-#include "codestream/residualhuffmanscan.hpp"
#include "codestream/losslessscan.hpp"
-#include "codestream/differentiallosslessscan.hpp"
-#include "codestream/acdifferentiallosslessscan.hpp"
#include "codestream/aclosslessscan.hpp"
#include "codestream/refinementscan.hpp"
#include "codestream/acrefinementscan.hpp"
-#include "codestream/differentialscan.hpp"
+#include "codestream/hiddenrefinementscan.hpp"
#include "codestream/singlecomponentlsscan.hpp"
#include "codestream/lineinterleavedlsscan.hpp"
#include "codestream/sampleinterleavedlsscan.hpp"
@@ -153,9 +149,22 @@ void Scan::WriteMarker(class ByteStream *io)
}
///
+
/// Scan::ParseMarker
+// Parse the marker contents. The scan type comes from
+// the frame type.
void Scan::ParseMarker(class ByteStream *io)
{
+ // Just forward to the generic method.
+ Scan::ParseMarker(io,m_pFrame->ScanTypeOf());
+}
+///
+
+/// Scan::ParseMarker
+// Parse the marker contents where the scan type
+// comes from an additional parameter.
+void Scan::ParseMarker(class ByteStream *io,ScanType type)
+{
LONG len = io->GetWord();
LONG data;
int i;
@@ -223,13 +232,14 @@ void Scan::ParseMarker(class ByteStream *io)
if (data == ByteStream::EOF)
JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","SOS marker run out of data");
- m_ucHighBit = data >> 4;
- m_ucLowBit = data & 0x0f;
+ m_ucHighBit = data >> 4;
+ m_ucLowBit = data & 0x0f;
+ m_ucHiddenBits = m_pFrame->TablesOf()->HiddenDCTBitsOf();
if (m_ucHighBit > 13)
JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","SOS high bit approximation is out of range, must be < 13");
- switch(m_pFrame->ScanTypeOf()) {
+ switch(type) {
case Progressive:
case ACProgressive:
case DifferentialProgressive:
@@ -244,6 +254,14 @@ void Scan::ParseMarker(class ByteStream *io)
if (m_ucScanStart && m_ucCount != 1)
JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","AC scans in progressive mode must only contain a single component");
break;
+ case Residual:
+ case ACResidual:
+ if (m_ucHighBit && m_ucHighBit != m_ucLowBit + 1)
+ JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker",
+ "SOS high bit is invalid, successive approximation must refine by one bit per scan");
+ if (m_ucScanStop < m_ucScanStart)
+ JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","end of scan is lower than start of scan");
+ break;
case Baseline:
case Sequential:
case ACSequential:
@@ -317,51 +335,55 @@ void Scan::CreateParser(void)
case Sequential:
m_pParser = new(m_pEnviron) class SequentialScan(m_pFrame,this,
m_ucScanStart,m_ucScanStop,
- m_ucLowBit);
+ m_ucLowBit + m_ucHiddenBits,0);
break;
case DifferentialSequential:
- m_pParser = new(m_pEnviron) class DifferentialScan(m_pFrame,this,
- m_ucScanStart,m_ucScanStop,
- m_ucLowBit);
+ m_pParser = new(m_pEnviron) class SequentialScan(m_pFrame,this,
+ m_ucScanStart,m_ucScanStop,
+ m_ucLowBit + m_ucHiddenBits,0,true);
break;
case Lossless:
- m_pParser = new(m_pEnviron) class LosslessScan(m_pFrame,this,m_ucScanStart,m_ucLowBit);
+ m_pParser = new(m_pEnviron) class LosslessScan(m_pFrame,this,m_ucScanStart,
+ m_ucLowBit + m_ucHiddenBits);
break;
case DifferentialLossless:
- m_pParser = new(m_pEnviron) class DifferentialLosslessScan(m_pFrame,this,m_ucLowBit);
+ m_pParser = new(m_pEnviron) class LosslessScan(m_pFrame,this,0,
+ m_ucLowBit + m_ucHiddenBits,true);
break;
case ACLossless:
- m_pParser = new(m_pEnviron) class ACLosslessScan(m_pFrame,this,m_ucScanStart,m_ucLowBit);
+ m_pParser = new(m_pEnviron) class ACLosslessScan(m_pFrame,this,m_ucScanStart,
+ m_ucLowBit + m_ucHiddenBits);
break;
case ACDifferentialLossless:
- m_pParser = new(m_pEnviron) class ACDifferentialLosslessScan(m_pFrame,this,m_ucLowBit);
+ m_pParser = new(m_pEnviron) class ACLosslessScan(m_pFrame,this,0,
+ m_ucLowBit + m_ucHiddenBits,true);
break;
case ACSequential:
m_pParser = new(m_pEnviron) class ACSequentialScan(m_pFrame,this,
m_ucScanStart,m_ucScanStop,
- m_ucLowBit);
+ m_ucLowBit + m_ucHiddenBits,0);
break;
case ACDifferentialSequential:
- m_pParser = new(m_pEnviron) class ACDifferentialSequentialScan(m_pFrame,this,
- m_ucScanStart,m_ucScanStop,
- m_ucLowBit);
+ m_pParser = new(m_pEnviron) class ACSequentialScan(m_pFrame,this,
+ m_ucScanStart,m_ucScanStop,
+ m_ucLowBit + m_ucHiddenBits,0,true);
break;
case Progressive:
if (m_ucHighBit == 0) { // The first scan is parsed off by the regular parser.
m_pParser = new(m_pEnviron) class SequentialScan(m_pFrame,this,
m_ucScanStart,m_ucScanStop,
- m_ucLowBit);
+ m_ucLowBit,0);
} else {
m_pParser = new(m_pEnviron) class RefinementScan(m_pFrame,this,
m_ucScanStart,m_ucScanStop,
- m_ucLowBit,m_ucHighBit);
+ m_ucLowBit + m_ucHiddenBits,m_ucHighBit);
}
break;
case DifferentialProgressive:
if (m_ucHighBit == 0) { // The first scan is parsed off by the regular parser.
- m_pParser = new(m_pEnviron) class DifferentialScan(m_pFrame,this,
- m_ucScanStart,m_ucScanStop,
- m_ucLowBit);
+ m_pParser = new(m_pEnviron) class SequentialScan(m_pFrame,this,
+ m_ucScanStart,m_ucScanStop,
+ m_ucLowBit + m_ucHiddenBits,true);
} else {
// Even though the specs do not mention this, it makes perfect sense that the
// refinement scan is a regular refinement scan without modification.
@@ -374,11 +396,11 @@ void Scan::CreateParser(void)
if (m_ucHighBit == 0) { // The first scan is parsed off by the regular parser.
m_pParser = new(m_pEnviron) class ACSequentialScan(m_pFrame,this,
m_ucScanStart,m_ucScanStop,
- m_ucLowBit);
+ m_ucLowBit + m_ucHiddenBits,0);
} else {
m_pParser = new(m_pEnviron) class ACRefinementScan(m_pFrame,this,
m_ucScanStart,m_ucScanStop,
- m_ucLowBit,m_ucHighBit);
+ m_ucLowBit + m_ucHiddenBits,m_ucHighBit);
}
break;
case JPEG_LS:
@@ -388,26 +410,27 @@ void Scan::CreateParser(void)
m_pParser = new(m_pEnviron) class SingleComponentLSScan(m_pFrame,this,
m_ucScanStart, // NEAR
m_ucMappingTable,
- m_ucLowBit); // Point transformation
+ m_ucLowBit + m_ucHiddenBits);
+ // Point transformation
break;
case 1:
m_pParser = new(m_pEnviron) class LineInterleavedLSScan(m_pFrame,this,
m_ucScanStart,
m_ucMappingTable,
- m_ucLowBit);
+ m_ucLowBit + m_ucHiddenBits);
break;
case 2:
m_pParser = new(m_pEnviron) class SampleInterleavedLSScan(m_pFrame,this,
m_ucScanStart,
m_ucMappingTable,
- m_ucLowBit);
+ m_ucLowBit + m_ucHiddenBits);
break;
case 3:
m_pParser = new(m_pEnviron) class VesaScan(m_pFrame,this,
m_ucScanStart,
m_ucMappingTable,
- m_ucLowBit);
- break;
+ m_ucLowBit + m_ucHiddenBits);
+ break;
}
break;
default:
@@ -435,6 +458,7 @@ void Scan::InstallDefaults(UBYTE depth,const struct JPG_TagItem *tags)
case Progressive:
case DifferentialSequential:
case DifferentialProgressive:
+ case Residual:
ishuffman = true;
break;
case Lossless:
@@ -446,6 +470,7 @@ void Scan::InstallDefaults(UBYTE depth,const struct JPG_TagItem *tags)
case ACProgressive:
case ACDifferentialSequential:
case ACDifferentialProgressive:
+ case ACResidual:
break;
case ACLossless:
case ACDifferentialLossless:
@@ -507,6 +532,8 @@ void Scan::InstallDefaults(UBYTE depth,const struct JPG_TagItem *tags)
case ACSequential:
case DifferentialSequential:
case ACDifferentialSequential:
+ case Residual:
+ case ACResidual:
// Install default start and stop of scan for a sequential run.
m_ucScanStart = 0;
m_ucScanStop = 63;
@@ -544,6 +571,7 @@ void Scan::InstallDefaults(UBYTE depth,const struct JPG_TagItem *tags)
m_ucComponent[1] = tags->GetTagData(JPGTAG_SCAN_COMPONENT1,1);
m_ucComponent[2] = tags->GetTagData(JPGTAG_SCAN_COMPONENT2,2);
m_ucComponent[3] = tags->GetTagData(JPGTAG_SCAN_COMPONENT3,3);
+ m_ucHiddenBits = m_pFrame->TablesOf()->HiddenDCTBitsOf();
//
// Install and check the scan parameters for the progressive scan.
switch(type) {
@@ -613,27 +641,39 @@ void Scan::InstallDefaults(UBYTE depth,const struct JPG_TagItem *tags)
/// Scan::MakeResidualScan
// Make this scan not a default scan, but a residual scan with the
// given maximal error.
-void Scan::MakeResidualScan(void)
+void Scan::MakeResidualScan(class Component *comp)
{
assert(m_pParser == NULL);
- m_ucCount = m_pFrame->DepthOf();
- memset(m_ucComponent,0,sizeof(m_ucComponent)); // not required.
+ m_ucCount = 1;
+ m_ucComponent[0] = comp->IDOf();
+ m_ucScanStart = 0;
+ m_ucScanStop = 63;
+ m_ucHighBit = m_ucLowBit = 0;
+ m_ucHiddenBits = 0;
switch(m_pFrame->ScanTypeOf()) {
case Baseline:
case Sequential:
case Progressive:
case Lossless:
- m_pParser = new(m_pEnviron) class ResidualHuffmanScan(m_pFrame,this);
+ m_ucDCTable[0] = m_ucACTable[0] = 0;
+ m_pHuffman = new(m_pEnviron) HuffmanTable(m_pEnviron);
+ m_pParser = new(m_pEnviron) ResidualHuffmanScan(m_pFrame,this,
+ m_pFrame->TablesOf()->ResidualDataOf(),
+ 0,63,0,0,true,true);
break;
case ACSequential:
case ACProgressive:
case ACLossless:
- m_pParser = new(m_pEnviron) class ResidualScan(m_pFrame,this);
+ m_ucACTable[0] = m_ucDCTable[0] = 0;
+ m_pConditioner = new(m_pEnviron) ACTable(m_pEnviron);
+ m_pParser = new(m_pEnviron) ResidualACScan(m_pFrame,this,
+ m_pFrame->TablesOf()->ResidualDataOf(),
+ 0,63,0,0,true,true);
break;
case JPEG_LS:
- JPG_THROW(INVALID_PARAMETER,"Scan::MakeResidualScan",
+ JPG_THROW(INVALID_PARAMETER,"Scan::MakeResidualACScan",
"JPEG LS does not support residual coding");
break;
default:
@@ -644,6 +684,199 @@ void Scan::MakeResidualScan(void)
}
///
+/// Scan::MakeHiddenRefinementACScan
+// Make this scan a hidden refinement scan starting at the indicated
+// bit position in the indicated component label.
+void Scan::MakeHiddenRefinementACScan(UBYTE bitposition,class Component *comp)
+{
+ bool colortrafo = (m_pFrame->DepthOf() > 1)?(m_pFrame->TablesOf()->UseColortrafo()):(false);
+
+ assert(m_pParser == NULL);
+
+ m_ucCount = 1;
+ m_ucComponent[0] = comp->IDOf();
+ m_ucScanStart = 1;
+ m_ucScanStop = 63;
+ m_ucLowBit = bitposition;
+ m_ucHighBit = bitposition+1;
+ m_ucHiddenBits = 0; // not here anymore.
+
+
+ switch(m_pFrame->ScanTypeOf()) {
+ case Baseline:
+ case Sequential:
+ case Progressive:
+ if (colortrafo) {
+ m_ucACTable[0] = (comp->IndexOf() == 0)?(0):(1); // Luma uses a separate table.
+ } else {
+ m_ucACTable[0] = 0;
+ }
+ m_ucDCTable[0] = m_ucACTable[0]; // Actually, not even used...
+ m_pHuffman = new(m_pEnviron) HuffmanTable(m_pEnviron);
+ m_pParser = new(m_pEnviron) HiddenRefinementScan(m_pFrame,this,
+ m_pFrame->TablesOf()->RefinementDataOf(),
+ 1,63,
+ bitposition,bitposition+1,
+ false,false);
+ break;
+ case ACSequential:
+ case ACProgressive:
+ m_ucACTable[0] = 0;
+ m_ucDCTable[0] = 0;
+ m_pConditioner = new(m_pEnviron) ACTable(m_pEnviron);
+ m_pParser = new(m_pEnviron) HiddenACRefinementScan(m_pFrame,this,
+ m_pFrame->TablesOf()->RefinementDataOf(),
+ 1,63,
+ bitposition,bitposition+1,
+ false,false);
+ break;
+ default:
+ JPG_THROW(INVALID_PARAMETER,"Scan::MakeHiddenRefinementACScan",
+ "frame type does not support hidden refinement scans");
+ break;
+ }
+}
+///
+
+/// Scan::MakeHiddenRefinementDCScan
+// Make this scan a hidden refinement scan starting at the indicated
+// bit position.
+void Scan::MakeHiddenRefinementDCScan(UBYTE bitposition)
+{
+ UBYTE i;
+ bool colortrafo = (m_pFrame->DepthOf() > 1)?(m_pFrame->TablesOf()->UseColortrafo()):(false);
+
+ assert(m_pParser == NULL);
+
+ if (m_pFrame->DepthOf() > 4)
+ JPG_THROW(INVALID_PARAMETER,"Scan::MakeHiddenRefinementDCScan",
+ "hidden refinement scans are confined to four components at most");
+
+ m_ucCount = m_pFrame->DepthOf();
+ for(i = 0;i < m_ucCount;i++) {
+ m_ucComponent[i] = m_pFrame->ComponentOf(i)->IDOf();
+ m_ucDCTable[i] = 0;
+ m_ucACTable[i] = 0; // Fixed later.
+ }
+
+ m_ucScanStart = 0;
+ m_ucScanStop = 0; // This is a DC scan
+ m_ucLowBit = bitposition;
+ m_ucHighBit = bitposition+1;
+ m_ucHiddenBits = 0; // not here anymore.
+
+ switch(m_pFrame->ScanTypeOf()) {
+ case Baseline:
+ case Sequential:
+ case Progressive:
+ if (colortrafo) {
+ m_ucDCTable[1] = m_ucDCTable[2] = m_ucDCTable[3] = 1; // Chroma uses a separate table.
+ }
+ for(i = 0;i < m_ucCount;i++) {
+ m_ucACTable[i] = m_ucDCTable[i];
+ }
+ m_pHuffman = new(m_pEnviron) HuffmanTable(m_pEnviron);
+ m_pParser = new(m_pEnviron) HiddenRefinementScan(m_pFrame,this,
+ m_pFrame->TablesOf()->RefinementDataOf(),
+ 0,0,
+ bitposition,bitposition+1,
+ false,false);
+ break;
+ case ACSequential:
+ case ACProgressive:
+ m_pConditioner = new(m_pEnviron) ACTable(m_pEnviron);
+ m_pParser = new(m_pEnviron) HiddenACRefinementScan(m_pFrame,this,
+ m_pFrame->TablesOf()->RefinementDataOf(),
+ 0,0,
+ bitposition,bitposition+1,
+ false,false);
+ break;
+ default:
+ JPG_THROW(INVALID_PARAMETER,"Scan::HiddenRefinementACScan",
+ "frame type does not support hidden refinement scans");
+ break;
+ }
+}
+///
+
+/// Scan::StartParseHiddenRefinementScan
+// Parse off a hidden refinement scan from the given position.
+void Scan::StartParseHiddenRefinementScan(class BufferCtrl *ctrl)
+{
+ class ResidualMarker *marker = m_pFrame->TablesOf()->RefinementDataOf();
+ class ByteStream *io = marker->StreamOf();
+
+ if (m_pParser == NULL) {
+ ScanType type = m_pFrame->ScanTypeOf();
+ //
+ switch(type) {
+ case Baseline:
+ case Sequential:
+ case Progressive:
+ ParseMarker(io,Progressive);
+ m_pParser = new(m_pEnviron) HiddenRefinementScan(m_pFrame,this,marker,
+ m_ucScanStart,m_ucScanStop,
+ m_ucLowBit,m_ucHighBit,
+ false,false);
+ break;
+ case ACSequential:
+ case ACProgressive:
+ ParseMarker(io,ACProgressive);
+ m_pParser = new(m_pEnviron) HiddenACRefinementScan(m_pFrame,this,marker,
+ m_ucScanStart,m_ucScanStop,
+ m_ucLowBit,m_ucHighBit,
+ false,false);
+ break;
+ default:
+ JPG_THROW(NOT_IMPLEMENTED,"Scan::StartParseHiddenRefinementScan",
+ "sorry, the coding mode in the codestream is currently not supported");
+ }
+ }
+
+ ctrl->PrepareForDecoding();
+ m_pParser->StartParseScan(io,ctrl);
+}
+///
+
+/// Scan::StartParseResidualScan
+// Parse off a hidden refinement scan from the given position.
+void Scan::StartParseResidualScan(class BufferCtrl *ctrl)
+{
+ class ResidualMarker *marker = m_pFrame->TablesOf()->ResidualDataOf();
+ class ByteStream *io = marker->StreamOf();
+
+ if (m_pParser == NULL) {
+ ScanType type = m_pFrame->ScanTypeOf();
+ //
+ switch(type) {
+ case Baseline:
+ case Sequential:
+ case Progressive:
+ ParseMarker(io,Residual);
+ m_pParser = new(m_pEnviron) ResidualHuffmanScan(m_pFrame,this,marker,
+ m_ucScanStart,m_ucScanStop,
+ m_ucLowBit,m_ucHighBit,
+ true,true);
+ break;
+ case ACSequential:
+ case ACProgressive:
+ ParseMarker(io,ACResidual);
+ m_pParser = new(m_pEnviron) ResidualACScan(m_pFrame,this,marker,
+ m_ucScanStart,m_ucScanStop,
+ m_ucLowBit,m_ucHighBit,
+ true,true);
+ break;
+ default:
+ JPG_THROW(NOT_IMPLEMENTED,"Scan::StartParseHiddenRefinementScan",
+ "sorry, the coding mode in the codestream is currently not supported");
+ }
+ }
+
+ ctrl->PrepareForDecoding();
+ m_pParser->StartParseScan(io,ctrl);
+}
+///
+
/// Scan::StartParseScan
// Fill in the decoding tables required.
void Scan::StartParseScan(class ByteStream *io,class BufferCtrl *ctrl)
@@ -731,7 +964,7 @@ void Scan::WriteFrameType(class ByteStream *io)
void Scan::Flush(void)
{
if (m_pParser)
- m_pParser->Flush();
+ m_pParser->Flush(true);
}
///
View
47 marker/scan.hpp
@@ -47,7 +47,7 @@ the committee itself.
**
** Represents all data in a single scan, and hence is the SOS marker.
**
-** $Id: scan.hpp,v 1.43 2012-07-26 19:17:35 thor Exp $
+** $Id: scan.hpp,v 1.49 2012-09-23 14:10:13 thor Exp $
**
*/
@@ -134,6 +134,9 @@ class Scan : public JKeeper {
// Also the point transformation.
UBYTE m_ucLowBit;
//
+ // Number of hidden bits not included in the low bit count.
+ UBYTE m_ucHiddenBits;
+ //
// Mapping table selector for JPEG_LS
UBYTE m_ucMappingTable[4];
//
@@ -199,9 +202,14 @@ class Scan : public JKeeper {
// file.
void WriteFrameType(class ByteStream *io);
//
- // Parse the marker contents.
+ // Parse the marker contents. The scan type comes from
+ // the frame type.
void ParseMarker(class ByteStream *io);
//
+ // Parse the marker contents where the scan type
+ // comes from an additional parameter.
+ void ParseMarker(class ByteStream *io,ScanType type);
+ //
// Write the marker to the stream. Note that this should
// be called indirectly by the implementing interface of
// the entropy parser and not called here from toplevel.
@@ -211,8 +219,23 @@ class Scan : public JKeeper {
// containing the given number of components.
void InstallDefaults(UBYTE depth,const struct JPG_TagItem *tags);
//
- // Make this scan not a default scan, but a residual scan.
- void MakeResidualScan(void);
+ // Make this scan not a default scan, but a residual scan. This
+ // creates the AC part of the scan (actually, the scan for the remaining positions)
+ void MakeResidualScan(class Component *comp);
+ //
+ // Make this scan a hidden refinement scan starting at the indicated
+ // bit position in the indicated component label.
+ void MakeHiddenRefinementACScan(UBYTE bitposition,class Component *comp);
+ //
+ // Make this scan a hidden refinement scan starting at the indicated
+ // bit position for the DC part. This is interleaved.
+ void MakeHiddenRefinementDCScan(UBYTE bitposition);
+ //
+ // Parse off a hidden refinement scan from the given position.
+ void StartParseHiddenRefinementScan(class BufferCtrl *ctrl);
+ //
+ // Parse off a residual scan from the given position.
+ void StartParseResidualScan(class BufferCtrl *ctrl);
//
// Fill in the decoding tables required.
void StartParseScan(class ByteStream *io,class BufferCtrl *ctrl);
@@ -259,6 +282,22 @@ class Scan : public JKeeper {
//
// The same for the AC band.
class ACTemplate *ACConditionerOf(UBYTE idx) const;
+ //
+ // Return the DC table of the conditioner.
+ UBYTE DCTableIndexOf(UBYTE idx) const
+ {
+ assert(idx < 4);
+
+ return m_ucDCTable[idx];
+ }
+ //
+ // Return the AC table of the conditioner.
+ UBYTE ACTableIndexOf(UBYTE idx) const
+ {
+ assert(idx < 4);
+
+ return m_ucACTable[idx];
+ }
};
///
View
4 marker/scantypes.hpp
@@ -48,7 +48,7 @@ the committee itself.
** Represents the scan including the scan header for the
** arithmetic coding procedure.
**
-** $Id: scantypes.hpp,v 1.4 2012-07-14 21:48:03 thor Exp $
+** $Id: scantypes.hpp,v 1.5 2012-09-23 14:10:13 thor Exp $
**
*/
@@ -70,6 +70,8 @@ enum ScanType {
ACDifferentialSequential,
ACDifferentialProgressive,
ACDifferentialLossless,
+ Residual, // New scan types
+ ACResidual,
JPEG_LS // not part of 10918, but handled here as well.
};
View
70 marker/tonemappingmarker.cpp
@@ -47,7 +47,7 @@ the committee itself.
** This class represents the APP9 marker carrying the tone mapping curve
** required to restore the HDR data from the LDR approximation.
**
-** $Id: tonemappingmarker.cpp,v 1.2 2012-07-14 13:30:28 thor Exp $
+** $Id: tonemappingmarker.cpp,v 1.4 2012-09-15 21:45:51 thor Exp $
**
*/
@@ -70,7 +70,7 @@ ToneMappingMarker::ToneMappingMarker(class Environ *env)
ToneMappingMarker::~ToneMappingMarker(void)
{
if (m_pusMapping)
- m_pEnviron->FreeMem(m_pusMapping,256 * sizeof(UWORD));
+ m_pEnviron->FreeMem(m_pusMapping,(1 << m_ucInternalDepth) * sizeof(UWORD));
if (m_pusInverseMapping)
m_pEnviron->FreeMem(m_pusInverseMapping,(1 << m_ucDepth) * sizeof(UWORD));
@@ -81,9 +81,10 @@ ToneMappingMarker::~ToneMappingMarker(void)
// Build the encoding tone mapper from the inverse mapping.
void ToneMappingMarker::BuildInverseMapping(void)
{
- UBYTE j,lastj,lastanchor;
+ UWORD j,lastj,lastanchor;
UWORD last,current,mid;
- UWORD outmax = (1 << m_ucDepth) - 1;
+ UWORD outmax = (1 << m_ucDepth) - 1;
+ UWORD inmax = (1 << m_ucInternalDepth) - 1;
bool lastfilled;
// Check the luts
@@ -98,10 +99,10 @@ void ToneMappingMarker::BuildInverseMapping(void)
memset(m_pusInverseMapping,0,(1 << m_ucDepth) * sizeof(UWORD));
//
// Loop over positive coefficients.
- lastj = 255;
- lastanchor = 255;
+ lastj = inmax;
+ lastanchor = inmax;
lastfilled = false;
- j = 255;
+ j = inmax;
last = m_pusMapping[j];
//
// Try some guesswork whether we should extend this to fullrange.
@@ -211,7 +212,8 @@ void ToneMappingMarker::BuildInverseMapping(void)
// the exception.
void ToneMappingMarker::ParseMarker(class ByteStream *io,UWORD len)
{
- UBYTE i,dt;
+ UBYTE dt;
+ UWORD i;
assert(m_pusMapping == NULL);
@@ -223,21 +225,33 @@ void ToneMappingMarker::ParseMarker(class ByteStream *io,UWORD len)
m_ucDepth = (dt & 0x0f) + 8;
len -= 2 + 2 + 4 + 1;
- if (len != 256 * 2)
- JPG_THROW(MALFORMED_STREAM,"ToneMappingMarker::ParseMarker","APP9 tone mapping information marker size invalid");
+ if (len < 256 * 2)
+ JPG_THROW(MALFORMED_STREAM,"ToneMappingMarker::ParseMarker",
+ "APP9 tone mapping information marker size invalid");
+
+ for(m_ucInternalDepth = 0;m_ucInternalDepth <= 14;m_ucInternalDepth++) {
+ if (len == 2 << m_ucInternalDepth)
+ break; // Found the right depth
+ }
- m_pusMapping = (UWORD *)m_pEnviron->AllocMem(256 * sizeof(UWORD));
+ //
+ // Must be a power of two.
+ if (m_ucInternalDepth > 14)
+ JPG_THROW(MALFORMED_STREAM,"ToneMappingMarker::ParseMarker",
+ "APP9 tone mapping information marker size invalid");
- i = 0;
- do {
+ m_pusMapping = (UWORD *)m_pEnviron->AllocMem((1 << m_ucInternalDepth) * sizeof(UWORD));
+
+ for(i = 0;i < (1 << m_ucInternalDepth);i++) {
m_pusMapping[i] = io->GetWord();
- } while(++i);
+ }
}
///
/// ToneMappingMarker::InstallDefaultParameters
// Install parameters - here the bpp value and the tone mapping curve.
-void ToneMappingMarker::InstallDefaultParameters(UBYTE idx,UBYTE bpp,const UWORD *curve)
+void ToneMappingMarker::InstallDefaultParameters(UBYTE idx,UBYTE bpp,UBYTE hidden,
+ const UWORD *curve)
{
assert(m_pusMapping == NULL);
@@ -248,21 +262,30 @@ void ToneMappingMarker::InstallDefaultParameters(UBYTE idx,UBYTE bpp,const UWORD
JPG_THROW(INVALID_PARAMETER,"ToneMappingMarker::InstallDefaultParameters",
"tone mapping identifier is out of range, must be between 0 and 15");
- m_ucIndex = idx;
- m_ucDepth = bpp;
- m_pusMapping = (UWORD *)m_pEnviron->AllocMem(256 * sizeof(UWORD));
+ m_ucIndex = idx;
+ m_ucDepth = bpp;
+ m_ucInternalDepth = 8 + hidden;
+
+ // Size limitation of the marker: We can spend at most 15 bits in total.
+ if (m_ucInternalDepth > 14)
+ JPG_THROW(OVERFLOW_PARAMETER,"ToneMappingMarker::InstallDefaultParameters",
+ "the total number of bits available for the internal sample representation "
+ "must not exceed 14");
+
+ m_pusMapping = (UWORD *)m_pEnviron->AllocMem((1UL << m_ucInternalDepth) * sizeof(UWORD));
- memcpy(m_pusMapping,curve,256 * sizeof(UWORD));
+ memcpy(m_pusMapping,curve,(1UL << m_ucInternalDepth) * sizeof(UWORD));
}
///
/// ToneMappingMarker::WriteMarker
void ToneMappingMarker::WriteMarker(class ByteStream *target)
{
- UBYTE i;
+ UWORD i;
assert(m_pusMapping);
- target->PutWord(2 + 2 + 4 + 1 + 256 * 2);
+ // Check above ensured that this cannot exceed 64K
+ target->PutWord(2 + 2 + 4 + 1 + (1UL << m_ucInternalDepth) * 2);
// Write the ID
target->Put('J');
target->Put('P');
@@ -272,10 +295,9 @@ void ToneMappingMarker::WriteMarker(class ByteStream *target)
target->Put('E');
target->Put((m_ucIndex << 4) | (m_ucDepth - 8));
- i = 0;
- do {
+ for(i = 0;i < (1 << m_ucInternalDepth);i++) {
target->PutWord(m_pusMapping[i]);
- } while(++i);
+ }
}
///
View
23 marker/tonemappingmarker.hpp
@@ -47,7 +47,7 @@ the committee itself.
** This class represents the APP9 marker carrying the tone mapping curve
** required to restore the HDR data from the LDR approximation.
**
-** $Id: tonemappingmarker.hpp,v 1.1 2012-07-14 12:07:35 thor Exp $
+** $Id: tonemappingmarker.hpp,v 1.3 2012-09-21 14:45:40 thor Exp $
**
*/
@@ -74,9 +74,14 @@ class ToneMappingMarker : public JKeeper {
// curve by refering to this index.
UBYTE m_ucIndex;
//
- // The output bpp value of this tone mapping. Input is 8bpp always.
+ // The output bpp value of this tone mapping.
UBYTE m_ucDepth;
//
+ // The input bpp value of this tone mapping curve - this is the
+ // number of bits spend internally in the JPEG representation before
+ // cutting off the hidden bits.
+ UBYTE m_ucInternalDepth;
+ //
// The tone mapping for decoding, i.e. generates output data (>8 bit) from
// the 8bpp input data.
UWORD *m_pusMapping;
@@ -119,6 +124,18 @@ class ToneMappingMarker : public JKeeper {
return m_ucIndex;
}
//
+ // Return the number of internal bits spend for the table.
+ UBYTE InternalBitsOf(void) const
+ {
+ return m_ucInternalDepth;
+ }
+ //
+ // Return the external bit depth depth.
+ UBYTE ExternalBitsOf(void) const
+ {
+ return m_ucDepth;
+ }
+ //
// Return the (decoding) tone mapping curve.
const UWORD *ToneMappingCurveOf(void) const
{
@@ -136,7 +153,7 @@ class ToneMappingMarker : public JKeeper {
}
//
// Install parameters - here the bpp value and the tone mapping curve.
- void InstallDefaultParameters(UBYTE idx,UBYTE bpp,const UWORD *curve);
+ void InstallDefaultParameters(UBYTE idx,UBYTE bpp,UBYTE hiddenbits,const UWORD *curve);
//
// Write the marker.
void WriteMarker(class ByteStream *io);

0 comments on commit 5ba2bca

Please sign in to comment.
Something went wrong with that request. Please try again.