This commit is contained in:
jdv_cp 2009-02-22 12:53:40 -08:00
parent 287916a234
commit babad3d0eb
76 changed files with 3954 additions and 0 deletions

28
CharLS.sln Normal file
View File

@ -0,0 +1,28 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual C++ Express 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CharLS", "CharLS.vcproj", "{524BE26D-FC60-4BC4-9100-128A0502FFF7}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test.vcproj", "{3E349E7B-30C2-4791-81B7-1108014291B7}"
ProjectSection(ProjectDependencies) = postProject
{524BE26D-FC60-4BC4-9100-128A0502FFF7} = {524BE26D-FC60-4BC4-9100-128A0502FFF7}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{524BE26D-FC60-4BC4-9100-128A0502FFF7}.Debug|Win32.ActiveCfg = Debug|Win32
{524BE26D-FC60-4BC4-9100-128A0502FFF7}.Debug|Win32.Build.0 = Debug|Win32
{524BE26D-FC60-4BC4-9100-128A0502FFF7}.Release|Win32.ActiveCfg = Release|Win32
{524BE26D-FC60-4BC4-9100-128A0502FFF7}.Release|Win32.Build.0 = Release|Win32
{3E349E7B-30C2-4791-81B7-1108014291B7}.Debug|Win32.ActiveCfg = Debug|Win32
{3E349E7B-30C2-4791-81B7-1108014291B7}.Debug|Win32.Build.0 = Debug|Win32
{3E349E7B-30C2-4791-81B7-1108014291B7}.Release|Win32.ActiveCfg = Release|Win32
{3E349E7B-30C2-4791-81B7-1108014291B7}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

307
CharLS.vcproj Normal file
View File

@ -0,0 +1,307 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
Name="CharLS"
ProjectGUID="{524BE26D-FC60-4BC4-9100-128A0502FFF7}"
RootNamespace="jpegls"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
UseOfMFC="2"
UseOfATL="2"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
InlineFunctionExpansion="1"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;JPEGLS_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
SmallerTypeCheck="false"
RuntimeLibrary="3"
BufferSecurityCheck="true"
DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
RuntimeTypeInfo="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
CompileAs="2"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="Winmm.lib"
OutputFile="$(OutDir)/jpegls.dll"
LinkIncremental="2"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)/jpegls.pdb"
SubSystem="2"
OptimizeForWindows98="0"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(OutDir)/jpegls.lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
UseOfMFC="0"
UseOfATL="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="2"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
OmitFramePointers="true"
EnableFiberSafeOptimizations="true"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;JPEGLS_EXPORTS"
StringPooling="true"
ExceptionHandling="1"
BasicRuntimeChecks="0"
RuntimeLibrary="0"
StructMemberAlignment="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
DisableLanguageExtensions="false"
ForceConformanceInForLoopScope="true"
RuntimeTypeInfo="true"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
CallingConvention="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="Winmm.lib"
OutputFile="$(OutDir)/jpegls.dll"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
OptimizeForWindows98="0"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(OutDir)/jpegls.lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
>
<File
RelativePath="header.cpp"
>
</File>
<File
RelativePath="jpegls.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
EnableIntrinsicFunctions="true"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
Optimization="3"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
BasicRuntimeChecks="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\test.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc"
>
<File
RelativePath="context.h"
>
</File>
<File
RelativePath=".\contextrunmode.h"
>
</File>
<File
RelativePath=".\decoderstrategy.h"
>
</File>
<File
RelativePath=".\defaulttraits.h"
>
</File>
<File
RelativePath=".\encoderstrategy.h"
>
</File>
<File
RelativePath="header.h"
>
</File>
<File
RelativePath="lookuptable.h"
>
</File>
<File
RelativePath=".\losslesstraits.h"
>
</File>
<File
RelativePath="scan.h"
>
</File>
<File
RelativePath="stdafx.h"
>
</File>
<File
RelativePath=".\streams.h"
>
</File>
<File
RelativePath="util.h"
>
</File>
</Filter>
<File
RelativePath=".\License.txt"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

27
License.txt Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2007-2009, Jan de Vaan
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of my employer, nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

97
context.h Normal file
View File

@ -0,0 +1,97 @@
//
// (C) Jan de Vaan 2007-2009, all rights reserved. See the accompanying "License.txt" for licensed use.
//
#pragma once
#define MIN_C -128
#define MAX_C 127
//
// JlsContext: a JPEG-LS context with it's current statistics.
//
struct JlsContext
{
public:
JlsContext()
{}
JlsContext(int a) :
A(a),
B(0),
C(0),
N(1)
{
}
UINT A;
int B;
int N;
int C;
inlinehint int GetErrorCorrection(int k) const
{
if (k != 0)
return 0;
return BitWiseSign(2 * B + N - 1);
}
inlinehint void UpdateVariables(int Errval, int NEAR, int NRESET)
{
ASSERT(N != 0);
B = B + Errval * (2 * NEAR + 1);
A = A + abs(Errval);
ASSERT(A < 65536 * 256);
ASSERT(abs(B) < 65536 * 256);
if (N == NRESET)
{
A = A >> 1;
B = B >> 1;
N = N >> 1;
}
N = N + 1;
if (B <= - N)
{
B = max(-N + 1, B + N);
if (C > MIN_C)
{
C--;
}
}
if (B > 0)
{
B = min(B - N, 0);
if (C < MAX_C)
{
C++;
}
}
ASSERT(N != 0);
}
inlinehint int GetGolomb() const
{
UINT Ntest = N;
UINT Atest = A;
UINT k = 0;
for(; Ntest < Atest; k++)
{
Ntest <<= 1;
ASSERT(k <= 32);
};
return k;
}
};

99
contextrunmode.h Normal file
View File

@ -0,0 +1,99 @@
//
// (C) Jan de Vaan 2007-2009, all rights reserved. See the accompanying "License.txt" for licensed use.
//
#pragma once
struct CContextRunMode
{
CContextRunMode(int a, int nRItype, int nReset) :
A(a),
N(1),
Nn(0),
_nRItype(nRItype),
_nReset((BYTE)nReset)
{
}
int A;
int _nRItype;
BYTE N;
BYTE Nn;
BYTE _nReset;
CContextRunMode()
{}
inlinehint int GetGolomb() const
{
UINT Ntest = N;
UINT TEMP = A + (N >> 1) * _nRItype;
UINT k = 0;
for(; Ntest < TEMP; k++)
{
Ntest <<= 1;
assert(k <= 32);
};
return k;
}
void UpdateVariables(int Errval, UINT EMErrval)
{
if (Errval < 0)
{
Nn = Nn + 1;
}
A = A + ((EMErrval + 1 - _nRItype) >> 1);
if (N == _nReset)
{
A = A >> 1;
N = N >> 1;
Nn = Nn >> 1;
}
N = N + 1;
}
inlinehint int ComputeErrVal(UINT temp, int k)
{
bool map = temp & 1;
UINT errvalabs = (temp + map) / 2;
if ((k != 0 || (2 * Nn >= N)) == map)
{
assert(map == ComputeMap(-int(errvalabs), k));
return -int(errvalabs);
}
assert(map == ComputeMap(errvalabs, k));
return errvalabs;
}
bool ComputeMap(int Errval, int k) const
{
if ((k == 0) && (Errval > 0) && (2 * Nn < N))
return 1;
else if ((Errval < 0) && (2 * Nn >= N))
return 1;
else if ((Errval < 0) && (k != 0))
return 1;
return 0;
}
inlinehint int ComputeMapNegativeE(int k) const
{
return k != 0 || (2 * Nn >= N );
}
};

188
decoderstrategy.h Normal file
View File

@ -0,0 +1,188 @@
//
// (C) Jan de Vaan 2007-2009, all rights reserved. See the accompanying "License.txt" for licensed use.
//
#pragma once
#include <ASSERT.h>
#include "streams.h"
class DecoderStrategy
{
public:
DecoderStrategy() :
_valcurrent(0),
_cbitValid(0),
_pbyteCompressed(0)
{}
virtual ~DecoderStrategy()
{}
virtual void SetPresets(const Presets& presets) = 0;
virtual int DecodeScan(void* pvoidOut, const Size& size, const void* pvoidIn, int cbyte, bool bCheck) = 0;
void Init(BYTE* pbyteCompressed, int cbyte)
{
_cbitValid = 0;
_valcurrent = 0;
_pbyteCompressed = pbyteCompressed;
_cbyteCompressed = cbyte;
MakeValid();
}
inlinehint void Skip(int length)
{
_cbitValid -= length;
_valcurrent = _valcurrent << length;
}
void MakeValid()
{
int cbitValid = _cbitValid;
BYTE* pbyteCompressed = _pbyteCompressed;
UINT valcurrent = 0;
while (cbitValid <= 24)
{
UINT valnew = *pbyteCompressed;
valcurrent |= valnew << (24 - cbitValid);
pbyteCompressed += 1;
cbitValid += 8;
if (valnew == 0xFF)
{
cbitValid--;
}
}
_valcurrent = _valcurrent | valcurrent;
_cbitValid = cbitValid;
_pbyteCompressed = pbyteCompressed;
}
BYTE* GetCurBytePos() const
{
int cbitValid = _cbitValid;
BYTE* pbyteCompressed = _pbyteCompressed;
for (;;)
{
int cbitLast = pbyteCompressed[-1] == 0xFF ? 7 : 8;
if (cbitValid < cbitLast )
return pbyteCompressed;
cbitValid -= cbitLast;
pbyteCompressed--;
}
}
inlinehint UINT ReadValue(int length)
{
if (_cbitValid < length)
{
MakeValid();
}
ASSERT(length != 0 && length <= _cbitValid);
UINT result = _valcurrent >> (32 - length);
Skip(length);
return result;
}
inlinehint int PeekByte()
{
if (_cbitValid < 8)
{
MakeValid();
}
return _valcurrent >> 24;
}
inlinehint bool ReadBit()
{
if (_cbitValid == 0)
{
MakeValid();
}
bool bSet = (_valcurrent & 0x80000000) != 0;
Skip(1);
return bSet;
}
inlinehint int Peek0Bits()
{
if (_cbitValid < 16)
{
MakeValid();
}
UINT valTest = _valcurrent;
for (int cbit = 0; cbit < 16; cbit++)
{
if ((valTest & 0x80000000) != 0)
return cbit;
valTest <<= 1;
}
return -1;
}
inlinehint UINT ReadHighbits()
{
int cbit = Peek0Bits();
if (cbit >= 0)
{
Skip(cbit + 1);
return cbit;
}
Skip(15);
for (UINT highbits = 15; ; highbits++)
{
if (ReadBit())
return highbits;
}
}
inlinehint UINT ReadLongValue(int length)
{
if (length <= 24)
{
return ReadValue(length);
}
return (ReadValue(length - 24) << 24) + ReadValue(24);
}
private:
// decoding
int _cbitValid;
UINT _valcurrent;
BYTE* _pbyteCompressed;
int _cbyteCompressed;
};

115
defaulttraits.h Normal file
View File

@ -0,0 +1,115 @@
//
// (C) Jan de Vaan 2007-2009, all rights reserved. See the accompanying "License.txt" for licensed use.
//
#pragma once
// Default traits that support all JPEG LS paramaters.
template <class sample, class pixel>
struct DefaultTraitsT
{
public:
// enum { ccomponent = 1, };
typedef sample SAMPLE;
typedef pixel PIXEL;
int MAXVAL;
int RANGE;
int NEAR;
int LIMIT;
int qbpp;
int bpp;
int RESET;
DefaultTraitsT(const DefaultTraitsT& src) :
MAXVAL(src.MAXVAL),
RANGE(src.RANGE),
NEAR(src.NEAR),
qbpp(src.qbpp),
bpp(src.bpp),
LIMIT(src.LIMIT),
RESET(src.RESET)
{
}
DefaultTraitsT(int max, int jls_near)
{
NEAR = jls_near;
MAXVAL = max;
RANGE = (max + 2 * jls_near )/(2 * jls_near + 1) + 1;
bpp = log2(max);
LIMIT = 2 * (bpp + max(8,bpp));
qbpp = log2(RANGE);
RESET = BASIC_RESET;
}
inlinehint int ComputeErrVal(int e) const
{
return ModRange(Quantize(e));
}
inlinehint SAMPLE ComputeReconstructedSample(int Px, int ErrVal)
{
return FixReconstructedValue(Px + DeQuantize(ErrVal));
}
inlinehint bool IsNear(int lhs, int rhs) const
{ return abs(lhs-rhs) <=NEAR; }
bool IsNear(Triplet lhs, Triplet rhs) const
{
return abs(lhs.v1-rhs.v1) <=NEAR && abs(lhs.v2-rhs.v2) <=NEAR && abs(lhs.v3-rhs.v3) <=NEAR;
}
inlinehint int CorrectPrediction(int Pxc) const
{
if ((Pxc & MAXVAL) == Pxc)
return Pxc;
return (~(Pxc >> 31)) & MAXVAL;
}
inlinehint int ModRange(int Errval) const
{
ASSERT(abs(Errval) <= RANGE);
if (Errval < 0)
Errval = Errval + RANGE;
if (Errval >= ((RANGE + 1) / 2))
Errval = Errval - RANGE;
return Errval;
}
private:
int Quantize(int Errval) const
{
if (Errval > 0)
return (Errval + NEAR) / (2 * NEAR + 1);
else
return - (NEAR - Errval) / (2 * NEAR + 1);
}
inlinehint int DeQuantize(int Errval) const
{
return Errval * (2 * NEAR + 1);
}
inlinehint SAMPLE FixReconstructedValue(int val) const
{
if (val < -NEAR)
val = val + RANGE*(2*NEAR+1);
if (val > MAXVAL + NEAR)
val = val - RANGE*(2*NEAR+1);
return SAMPLE(CorrectPrediction(val));
}
};

125
encoderstrategy.h Normal file
View File

@ -0,0 +1,125 @@
//
// (C) Jan de Vaan 2007-2009, all rights reserved. See the accompanying "License.txt" for licensed use.
//
#pragma once
#include "decoderstrategy.h"
class EncoderStrategy
{
public:
EncoderStrategy() :
valcurrent(0),
bitpos(0),
_qdecoder(0),
_bFFWritten(false),
_cbyteWritten(0)
{};
virtual ~EncoderStrategy()
{}
virtual void SetPresets(const Presets& presets) = 0;
virtual int EncodeScan(const void* pvoid, const Size& size, void* pvoidOut, int cbyte, void* pvoidCompare) = 0;
protected:
void Init(BYTE* pbyteCompressed, int cbyte)
{
bitpos = 32;
valcurrent = 0;
_pbyteCompressed = pbyteCompressed;
_cbyteCompressed = cbyte;
}
inlinehint void AppendToBitStream(UINT value, UINT length)
{
ASSERT(length < 32 && length >= 0);
ASSERT((_qdecoder == NULL) || (length == 0 && value == 0) ||( _qdecoder->ReadLongValue(length) == value));
if (length < 32)
{
UINT mask = (1 << (length)) - 1;
ASSERT((value | mask) == mask);
}
bitpos -= length;
if (bitpos >= 0)
{
valcurrent = valcurrent | (value << bitpos);
return;
}
valcurrent |= value >> -bitpos;
Flush();
ASSERT(bitpos >=0);
valcurrent |= value << bitpos;
}
inline bool hasbit(UINT i, int ibit)
{
return (i & (1 << ibit)) != 0;
}
void Flush()
{
for (int i = 0; i < 4; ++i)
{
if (_bFFWritten)
{
// insert highmost bit
*_pbyteCompressed = BYTE(valcurrent >> 25);
valcurrent = valcurrent << 7;
bitpos += 7;
_bFFWritten = false;
}
else
{
*_pbyteCompressed = BYTE(valcurrent >> 24);
valcurrent = valcurrent << 8;
bitpos += 8;
_bFFWritten = *_pbyteCompressed == 0xFF;
}
_pbyteCompressed++;
_cbyteCompressed--;
_cbyteWritten++;
}
}
int GetLength()
{
return _cbyteWritten - (bitpos -32)/8;
};
inlinehint void AppendOnesToBitStream(UINT length)
{
AppendToBitStream((1 << length) - 1, length);
}
DecoderStrategy* _qdecoder;
private:
UINT valcurrent;
// encoding
int _cbyteCompressed;
// encoding
int bitpos;
BYTE* _pbyteCompressed;
bool _bFFWritten;
int _cbyteWritten;
};

382
header.cpp Normal file
View File

@ -0,0 +1,382 @@
//
// (C) Jan de Vaan 2007-2009, all rights reserved. See the accompanying "License.txt" for licensed use.
//
#include "stdafx.h"
#include "header.h"
#include "streams.h"
#include "decoderstrategy.h"
#include "encoderstrategy.h"
//
// JpegMarkerSegment
//
class JpegMarkerSegment : public JpegSegment
{
public:
JpegMarkerSegment(BYTE marker, std::vector<BYTE> vecbyte)
{
_marker = marker;
std::swap(_vecbyte, vecbyte);
}
virtual void Write(JLSOutputStream* pheader)
{
pheader->WriteByte(0xFF);
pheader->WriteByte(_marker);
pheader->WriteWord(USHORT(_vecbyte.size() + 2));
pheader->WriteBytes(_vecbyte);
}
BYTE _marker;
std::vector<BYTE> _vecbyte;
};
//
// AppendWord()
//
void AppendWord(std::vector<BYTE>& vec, USHORT value)
{
vec.push_back(BYTE(value / 0x100));
vec.push_back(BYTE(value % 0x100));
}
//
// CreateMarkerStartOfFrame()
//
JpegSegment* CreateMarkerStartOfFrame(int ccol, int cline, int cbpp, int ccomp)
{
std::vector<BYTE> vec;
vec.push_back(static_cast<BYTE>(cbpp));
AppendWord(vec, static_cast<USHORT>(cline));
AppendWord(vec, static_cast<USHORT>(ccol));
// components
vec.push_back(static_cast<BYTE>(ccomp));
for (BYTE icomp = 0; icomp < ccomp; icomp++)
{
// rescaling
vec.push_back(icomp + 1);
vec.push_back(0x11);
//"Tq1" reserved, 0
vec.push_back(0);
}
return new JpegMarkerSegment(JPEG_SOF, vec);
};
//
// ctor()
//
JLSOutputStream::JLSOutputStream() :
_pdata(NULL),
_cbyteOffset(0),
_cbyteLength(0),
_icompLast(0)
{
}
//
// dtor()
//
JLSOutputStream::~JLSOutputStream()
{
for (UINT i = 0; i < _rgsegment.size(); ++i)
{
delete _rgsegment[i];
}
_rgsegment.empty();
}
//
// Init()
//
void JLSOutputStream::Init(int ccomp, int ccol, int cline, int cbpp)
{
_rgsegment.push_back(CreateMarkerStartOfFrame(ccomp, ccol, cline, cbpp));
}
//
// Write()
//
int JLSOutputStream::Write(BYTE* pdata, int cbyteLength, const void* /*pbyteExpected*/)
{
_pdata = pdata;
_cbyteLength = cbyteLength;
WriteByte(0xFF);
WriteByte(JPEG_SOI);
// pbyteExpected += 2;
for (UINT i = 0; i < _rgsegment.size(); ++i)
{
_rgsegment[i]->Write(this);
}
WriteByte(0xFF);
WriteByte(JPEG_EOI);
return _cbyteOffset;
}
JLSInputStream::JLSInputStream(const BYTE* pdata, int cbyteLength) :
_pdata(pdata),
_cbyteOffset(0),
_cbyteLength(cbyteLength),
_bCompare(false)
{
}
//
// Read()
//
bool JLSInputStream::Read(void* pvoid)
{
if (!ReadHeader())
return false;
return ReadPixels(pvoid);
}
//
// ReadPixels()
//
bool JLSInputStream::ReadPixels(void* pvoid)
{
// line interleave not supported yet
if (_info.ilv == ILV_LINE)
return false;
if (_info.ilv == ILV_NONE)
{
BYTE* pbyte = (BYTE*)pvoid;
for (int icomp = 0; icomp < _info.ccomp; ++icomp)
{
ReadScan(pbyte);
pbyte += _info.size.cx * _info.size.cy * ((_info.cbit + 7)/8);
}
}
else
{
ReadScan(pvoid);
}
return true;
}
//
// ReadHeader()
//
int JLSInputStream::ReadHeader()
{
if (ReadByte() != 0xFF)
return 0;
if (ReadByte() != JPEG_SOI)
return 0;
for (;;)
{
if (ReadByte() != 0xFF)
return 0;
BYTE marker = (BYTE)ReadByte();
int cbyteStart = _cbyteOffset;
int cbyteMarker = ReadWord();
switch (marker)
{
case JPEG_SOS: ReadStartOfScan(); break;
case JPEG_SOF: ReadStartOfFrame(); break;
case JPEG_COM: ReadComment(); break;
case JPEG_LSE: ReadPresetParameters(); break;
// Other tags not supported (among which DNL DRI)
default:
return 0;
}
if (marker == JPEG_SOS)
{
_cbyteOffset = cbyteStart - 2;
return _cbyteOffset;
}
_cbyteOffset = cbyteStart + cbyteMarker;
}
}
//
// ReadPresetParameters()
//
void JLSInputStream::ReadPresetParameters()
{
int type = ReadByte();
switch (type)
{
case 1:
{
_presets.MAXVAL = ReadWord();
_presets.T1 = ReadWord();
_presets.T2 = ReadWord();
_presets.T3 = ReadWord();
_presets.RESET = ReadWord();
return;
}
}
}
//
// ReadStartOfScan()
//
void JLSInputStream::ReadStartOfScan()
{
int ccomp = ReadByte();
for (int i = 0; i < ccomp; ++i)
{
ReadByte();
ReadByte();
}
_info.nnear = ReadByte();
_info.ilv = interleavemode(ReadByte());
}
//
// ReadComment()
//
void JLSInputStream::ReadComment()
{}
//
// ReadStartOfFrame()
//
void JLSInputStream::ReadStartOfFrame()
{
_info.cbit = ReadByte();
int cline = ReadWord();
int ccol = ReadWord();
_info.size = Size(cline, ccol);
_info.ccomp = ReadByte();
}
//
// ReadByte()
//
int JLSInputStream::ReadByte()
{ return _pdata[_cbyteOffset++]; }
//
// ReadWord()
//
int JLSInputStream::ReadWord()
{
int i = ReadByte() * 256;
return i + ReadByte();
}
void JLSInputStream::ReadScan(void* pvout)
{
std::auto_ptr<DecoderStrategy> qcodec(JlsCodecFactory<DecoderStrategy>().GetCodec(_info, _presets));
_cbyteOffset += qcodec->DecodeScan(pvout, _info.size, _pdata + _cbyteOffset, _cbyteLength - _cbyteOffset, _bCompare);
};
class JpegImageDataSegment: public JpegSegment
{
public:
JpegImageDataSegment(const void* pvoidRaw, Size size, int cbit, int icompStart, int ccompScan, interleavemode ilv, int accuracy) :
_cbit(cbit),
_nnear(accuracy),
_size(size),
_ccompScan(ccompScan),
_ilv(ilv),
_icompStart(icompStart),
_pvoidRaw(pvoidRaw)
{
}
void Write(JLSOutputStream* pstream)
{
EncodeScanHeader(pstream);
ScanInfo info;
info.cbit = _cbit;
info.ccomp = _ccompScan;
info.ilv = _ilv;
info.nnear = _nnear;
Presets presets;
std::auto_ptr<EncoderStrategy> qcodec(JlsCodecFactory<EncoderStrategy>().GetCodec(info, presets));
int cbyteWritten = qcodec->EncodeScan((BYTE*)_pvoidRaw, _size, pstream->GetPos(), pstream->GetLength(), NULL);
pstream->Seek(cbyteWritten);
}
void EncodeScanHeader(JLSOutputStream* pstream) const
{
BYTE ccomponent = BYTE(_ccompScan);
BYTE itable = 0;
USHORT cbyteHeader = 0x06 + 2 * ccomponent;
pstream->WriteByte(0xFF);
pstream->WriteByte(JPEG_SOS);
pstream->WriteWord(cbyteHeader);
pstream->WriteByte(ccomponent);
for (int icomponent = 0; icomponent < ccomponent; ++icomponent )
{
pstream->WriteByte(BYTE(icomponent + _icompStart));
pstream->WriteByte(itable);
}
pstream->WriteByte(BYTE(_nnear)); // NEAR
pstream->WriteByte(BYTE(_ilv));
pstream->WriteByte(0); // transform
}
const void* _pvoidRaw;
Size _size;
int _cbit;
int _ccompScan;
interleavemode _ilv;
int _icompStart;
int _nnear;
};
void JLSOutputStream::AddScan(const void* pbyteComp, Size size, int cbit, int ccomp, interleavemode ilv, int nearval)
{
_icompLast += 1;
_rgsegment.push_back(new JpegImageDataSegment(pbyteComp, size, cbit, _icompLast, ccomp, ilv, nearval));
}

44
header.h Normal file
View File

@ -0,0 +1,44 @@
//
// (C) Jan de Vaan 2007-2009, all rights reserved. See the accompanying "License.txt" for licensed use.
//
#pragma once
#include "streams.h"
#define JPEG_SOI 0xD8
#define JPEG_EOI 0xD9
#define JPEG_SOS 0xDA
#define JPEG_SOF 0xF7
#define JPEG_LSE 0xF8
#define JPEG_DNL 0xDC
#define JPEG_DRI 0xDD
#define JPEG_RSTm 0xD0
#define JPEG_COM 0xFE
class JLSOutputStream;
template<class STRATEGY>
class JlsCodecFactory
{
public:
STRATEGY* GetCodec(const ScanInfo& info, const Presets&);
private:
STRATEGY* GetCodecImpl(const ScanInfo& info);
};
//
// JpegSegment
//
class JpegSegment
{
protected:
JpegSegment() {}
public:
virtual ~JpegSegment() {}
virtual void Write(JLSOutputStream* pheader) = 0;
};

108
jpegls.cpp Normal file
View File

@ -0,0 +1,108 @@
//
// (C) Jan de Vaan 2007-2009, all rights reserved. See the accompanying "License.txt" for licensed use.
//
#include "stdafx.h"
#include "streams.h"
#include "header.h"
#include <math.h>
#include <limits>
#include <vector>
#include <STDIO.H>
#include <iostream>
#include "util.h"
#include "decoderstrategy.h"
#include "encoderstrategy.h"
#include "context.h"
#include "contextrunmode.h"
#include "lookuptable.h"
// used to determine how large runs should be encoded at a time.
const int J[32] = {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 10, 11, 12, 13, 14, 15};
const int BASIC_T1 = 3;
const int BASIC_T2 = 7;
const int BASIC_T3 = 21;
#include "losslesstraits.h"
#include "defaulttraits.h"
CTable rgtable[16];
int f_bTableMaxVal = -1;
signed char rgquant[65535 + 1 + 65535];
#include "scan.h"
template<class STRATEGY>
STRATEGY* JlsCodecFactory<STRATEGY>::GetCodec(const ScanInfo& _info, const Presets& presets)
{
STRATEGY* pstrategy = NULL;
if (presets.RESET != 0 && presets.RESET != BASIC_RESET)
{
typename DefaultTraitsT<BYTE,BYTE> traits((1 << _info.cbit) - 1, _info.nnear);
traits.MAXVAL = presets.MAXVAL;
traits.RESET = presets.RESET;
pstrategy = new JlsCodec<DefaultTraitsT<BYTE, BYTE>, STRATEGY>(traits);
}
else
{
pstrategy = GetCodecImpl(_info);
}
if (pstrategy == NULL)
return NULL;
pstrategy->SetPresets(presets);
return pstrategy;
}
template<class STRATEGY>
STRATEGY* JlsCodecFactory<STRATEGY>::GetCodecImpl(const ScanInfo& _info)
{
if (_info.nnear != 0)
{
if (_info.cbit == 8 && _info.ilv == ILV_SAMPLE)
{
typename DefaultTraitsT<BYTE,Triplet> traits((1 << _info.cbit) - 1, _info.nnear);
return new JlsCodec<DefaultTraitsT<BYTE,Triplet>, STRATEGY>(traits);
}
if (_info.cbit == 8)
{
typename DefaultTraitsT<BYTE, BYTE> traits((1 << _info.cbit) - 1, _info.nnear);
return new JlsCodec<DefaultTraitsT<BYTE, BYTE>, STRATEGY>(traits);
}
else
{
typename DefaultTraitsT<USHORT, USHORT> traits((1 << _info.cbit) - 1, _info.nnear);
return new JlsCodec<DefaultTraitsT<USHORT, USHORT>, STRATEGY>(traits);
}
}
if (_info.ilv == ILV_SAMPLE && _info.ccomp == 3 && _info.cbit == 8)
return new JlsCodec<LosslessTraitsT<Triplet,8>, STRATEGY>();
switch (_info.cbit)
{
case 7: return new JlsCodec<LosslessTraitsT<BYTE, 7>, STRATEGY>();
case 8: return new JlsCodec<LosslessTraitsT<BYTE, 8>, STRATEGY>();
case 9: return new JlsCodec<LosslessTraitsT<USHORT, 9>, STRATEGY>();
case 10: return new JlsCodec<LosslessTraitsT<USHORT,10>, STRATEGY>();
case 11: return new JlsCodec<LosslessTraitsT<USHORT,11>, STRATEGY>();
case 12: return new JlsCodec<LosslessTraitsT<USHORT,12>, STRATEGY>();
case 13: return new JlsCodec<LosslessTraitsT<USHORT,13>, STRATEGY>();
case 14: return new JlsCodec<LosslessTraitsT<USHORT,14>, STRATEGY>();
case 15: return new JlsCodec<LosslessTraitsT<USHORT,15>, STRATEGY>();
case 16: return new JlsCodec<LosslessTraitsT<USHORT,16>, STRATEGY>();
}
return NULL;
}
template class JlsCodecFactory<DecoderStrategy>;
template class JlsCodecFactory<EncoderStrategy>;

66
lookuptable.h Normal file
View File

@ -0,0 +1,66 @@
//
// (C) Jan de Vaan 2007-2009, all rights reserved. See the accompanying "License.txt" for licensed use.
//
#pragma once
struct Code
{
Code()
{
}
Code(int value, int length) :
_value(value),
_length(length)
{
}
int GetValue() const
{ return _value; }
int GetLength() const
{ return _length; }
int _value;
int _length;
};
class CTable
{
public:
enum { cbit = 8 } ;
CTable()
{
::memset(rgtype, 0, sizeof(rgtype));
}
void AddEntry(BYTE bvalue, Code c);
inlinehint const Code& Get(int value)
{ return rgtype[value]; }
private:
Code rgtype[1 << cbit];
};
//
// AddEntry
//
void CTable::AddEntry(BYTE bvalue, Code c)
{
int length = c.GetLength();
ASSERT(length <= cbit);
for (int i = 0; i < 1 << (cbit - length); ++i)
{
ASSERT(rgtype[(bvalue << (cbit - length)) + i].GetLength() == 0);
rgtype[(bvalue << (cbit - length)) + i] = c;
}
}

117
losslesstraits.h Normal file
View File

@ -0,0 +1,117 @@
//
// (C) Jan de Vaan 2007-2009, all rights reserved. See the accompanying "License.txt" for licensed use.
//
#pragma once
//
// optimized trait classes for lossless compression of 8 bit color and 8/16 bit monochrome images.
//
template <class sample, int bitsperpixel>
struct LosslessTraitsImplT
{
typedef sample SAMPLE;
enum {
NEAR = 0,
bpp = bitsperpixel,
qbpp = bitsperpixel,
RANGE = (1 << bpp),
MAXVAL= (1 << bpp) - 1,
LIMIT = 2 * (bitsperpixel + max(8,bitsperpixel)),
RESET = BASIC_RESET,
};
static inlinehint int ComputeErrVal(int d)
{ return ModRange(d); }
static inlinehint bool IsNear(int lhs, int rhs)
{ return lhs == rhs; }
static inlinehint int ModRange(int Errval)
{
return int(Errval << ((sizeof(int) * 8) - bpp)) >> ((sizeof(int) * 8) - bpp);
}
static inlinehint SAMPLE ComputeReconstructedSample(int Px, int ErrVal)
{
return SAMPLE(MAXVAL & (Px + ErrVal));
}
static inlinehint int CorrectPrediction(int Pxc)
{
if ((Pxc & MAXVAL) == Pxc)
return Pxc;
return (~(Pxc >> 31)) & MAXVAL;
}
};
template <class SAMPLE, int bpp>
struct LosslessTraitsT : public LosslessTraitsImplT<SAMPLE, bpp>
{
// enum { ccomponent = 1};
typedef SAMPLE PIXEL;
};
template<>
struct LosslessTraitsT<BYTE,8> : public LosslessTraitsImplT<BYTE, 8>
{
// enum { ccomponent = 1};
typedef SAMPLE PIXEL;
static inlinehint signed char ModRange(int Errval)
{ return (signed char)Errval; }
static inlinehint int ComputeErrVal(int d)
{ return signed char(d); }
static inlinehint BYTE ComputeReconstructedSample(int Px, int ErrVal)
{ return BYTE(Px + ErrVal); }
};
template<>
struct LosslessTraitsT<USHORT,16> : public LosslessTraitsImplT<USHORT,16>
{
// enum { ccomponent = 1};
typedef SAMPLE PIXEL;
static inlinehint short ModRange(int Errval)
{ return short(Errval); }
static inlinehint int ComputeErrVal(int d)
{ return short(d); }
static inlinehint SAMPLE ComputeReconstructedSample(int Px, int ErrVal)
{ return SAMPLE(Px + ErrVal); }
};
template<>
struct LosslessTraitsT<Triplet,8> : public LosslessTraitsImplT<BYTE,8>
{
// enum { ccomponent = 3 };
typedef Triplet PIXEL;
static inlinehint bool IsNear(int lhs, int rhs)
{ return lhs == rhs; }
static inlinehint bool IsNear(PIXEL lhs, PIXEL rhs)
{ return lhs == rhs; }
static inlinehint SAMPLE ComputeReconstructedSample(int Px, int ErrVal)
{ return SAMPLE(Px + ErrVal); }
};

851
scan.h Normal file
View File

@ -0,0 +1,851 @@
//
// (C) Jan de Vaan 2007-2009, all rights reserved. See the accompanying "License.txt" for licensed use.
//
#pragma once
#include "lookuptable.h"
//
// Apply
//
inlinehint int ApplySign(int i, int sign)
{ return (sign ^ i) - sign; }
/* Two alternatives for GetPredictedValue() (second is slightly faster due to reduced branching)
inlinehint int GetPredictedValue(int Ra, int Rb, int Rc)
{
if (Ra < Rb)
{
if (Rc < Ra)
return Rb;
if (Rc > Rb)
return Ra;
}
else
{
if (Rc < Rb)
return Ra;
if (Rc > Ra)
return Rb;
}
return Ra + Rb - Rc;
}
/*/
inlinehint int GetPredictedValue(int Ra, int Rb, int Rc)
{
// sign trick reduces the number of if statements
int sgn = BitWiseSign(Rb - Ra);
// is Ra between Rc and Rb?
if ((sgn ^ (Rc - Ra)) < 0)
return Rb;
// is Rb between Rc and Ra?
if ((sgn ^ (Rb - Rc)) < 0)
return Ra;
// default case, valid if Rc element of [Ra,Rb]
return Ra + Rb - Rc;
}
//*/
inlinehint int UnMapErrVal(int mappedError)
{
//int sign = ~((mappedError & 1) - 1);
int sign = int(mappedError << 31) >> 31;
return sign ^ (mappedError >> 1);
}
inlinehint int GetMappedErrVal(int Errval)
{
int mappedError = (Errval >> 30) ^ (2 * Errval);
return mappedError;
}
inlinehint int ComputeContextID(int Q1, int Q2, int Q3)
{ return (Q1*9 + Q2)*9 + Q3; }
//
//
//
template <class TRAITS, class STRATEGY>
class JlsCodec : public STRATEGY
{
public:
typedef typename TRAITS::PIXEL PIXEL;
typedef typename TRAITS::SAMPLE SAMPLE;
public:
JlsCodec() :
_bCompare(0),
T1(0),
T2(0),
T3(0),
RUNindex(0),
_pquant(0)
{
memset(_rghistogramK, 0, sizeof(_rghistogramK));
}
JlsCodec(const TRAITS& inTraits) :
traits(inTraits),
_bCompare(0),
T1(0),
T2(0),
T3(0),
RUNindex(0),
_pquant(0)
{
memset(_rghistogramK, 0, sizeof(_rghistogramK));
}
void SetPresets(const Presets& presets)
{
int NEAR = traits.NEAR;
int FACTOR = (min(traits.MAXVAL, 4095) + 128)/256;
int t1 = CLAMP(FACTOR * (BASIC_T1 - 2) + 2 + 3*NEAR, NEAR + 1);
int t2 = CLAMP(FACTOR * (BASIC_T2 - 3) + 3 + 5*NEAR, t1);
int t3 = CLAMP(FACTOR * (BASIC_T3 - 4) + 4 + 7*NEAR, t2);
InitParams(presets.T1 != 0 ? presets.T1 : t1,
presets.T2 != 0 ? presets.T2 : t2,
presets.T3 != 0 ? presets.T3 : t3,
presets.RESET != 0 ? presets.RESET : BASIC_RESET);
}
int CLAMP(int i, int j)
{
if (i > traits.MAXVAL || i < j)
return j;
return i;
}
signed char QuantizeGratientOrg(int Di);
inlinehint int QuantizeGratient(int Di)
{
ASSERT(QuantizeGratientOrg(Di) == *(_pquant + Di));
return *(_pquant + Di);
}
void InitTables();
void InitQuantizationLUT();
inlinehint std::pair<int, UINT> CreateEncodedValue(int k, UINT mappederval, UINT limit);
inlinehint UINT DecodeValue(int k, UINT limit, int qbpp);
inlinehint void EncodeValue(int k, UINT mappederval, UINT limit);
void IncrementRunIndex()
{ RUNindex = min(31,RUNindex + 1); }
void DecrementRunIndex()
{ RUNindex = max(0,RUNindex - 1); }
int DecodeRISample(CContextRunMode& ctx);
Triplet DecodeRIPixel(Triplet Ra, Triplet Rb);
PIXEL DecodeRIPixel(int Ra, int Rb);
int DecodeRunPixels(PIXEL Ra, PIXEL* ptype, PIXEL* ptypeUnc, int ipixel, int cpixelMac);
int DecodeRunMode(PIXEL Ra, PIXEL* ptype, PIXEL* ptypeUnc, const PIXEL* ptypePrev, int ipixel, int cpixelMac);
void EncodeRISample(CContextRunMode& ctx, int Errval);
SAMPLE EncodeRIPixel(int x, int Ra, int Rb);
Triplet EncodeRIPixel(Triplet x, Triplet Ra, Triplet Rb);
void EncodeRunPixels(int RUNcnt, bool bEndofline);
int EncodeRunMode(PIXEL* ptype, const PIXEL* ptypeUnc, const PIXEL* ptypePrev, int ipixel, int ctypeRem);
inlinehint SAMPLE DecodeRegular(int Qs, int pred);
inlinehint SAMPLE EncodeRegular(int Qs, int x, int pred);
inlinehint void CheckedAssign(SAMPLE& typeDst, SAMPLE type)
{
ASSERT(!_bCompare || traits.IsNear(typeDst, type));
typeDst = type;
}
inlinehint void CheckedAssign(Triplet& typeDst, Triplet type)
{
ASSERT(!_bCompare || traits.IsNear(typeDst, type));
typeDst = type;
}
void DoLine(SAMPLE* ptype, const SAMPLE* ptypePrev, int csample, SAMPLE* ptypeUnc, DecoderStrategy*);
void DoLine(SAMPLE* ptype, const SAMPLE* ptypePrev, int csample, const SAMPLE* ptypeUnc, EncoderStrategy*);
void DoLine(Triplet* ptype, Triplet* ptypePrev, int csample, Triplet* ptypeUnc, DecoderStrategy*);
void DoLine(Triplet* ptype, Triplet* ptypePrev, int csample, Triplet* ptypeUnc, EncoderStrategy*);
void DoScan(PIXEL* ptype, Size size, BYTE* pbyteCompressed, int cbyteCompressed);
public:
void InitDefault();
void InitParams(int t1, int t2, int t3, int nReset);
int EncodeScan(const void* pvoid, const Size& size, void* pvoidOut, int cbyte, void* pvoidCompare);
int DecodeScan(void* pvoidOut, const Size& size, const void* pvoidIn, int cbyte, bool bCompare);
protected:
TRAITS traits;
signed char* _pquant;
JlsContext _rgcontext[365];
CContextRunMode _contextRunmode[2];
int RUNindex;
int T3;
int T2;
int T1;
// debugging
int _rghistogramK[16];
bool _bCompare;
};
template<class TRAITS, class STRATEGY>
typename TRAITS::SAMPLE JlsCodec<TRAITS,STRATEGY>::DecodeRegular(int Qs, int pred)
{
int sign = BitWiseSign(Qs);
JlsContext& ctx = _rgcontext[ApplySign(Qs, sign)];
int k = ctx.GetGolomb();
int Px = traits.CorrectPrediction(pred + ApplySign(ctx.C, sign));
int ErrVal;
const Code& code = rgtable[k].Get(PeekByte());
if (code.GetLength() != 0)
{
Skip(code.GetLength());
ErrVal = code.GetValue();
ASSERT(abs(ErrVal) < 65535);
}
else
{
ErrVal = UnMapErrVal(DecodeValue(k, traits.LIMIT, traits.qbpp));
ASSERT(abs(ErrVal) < 65535);
}
ErrVal = ErrVal ^ ((traits.NEAR == 0) ? ctx.GetErrorCorrection(k) : 0);
ctx.UpdateVariables(ErrVal, traits.NEAR, traits.RESET);
return traits.ComputeReconstructedSample(Px, ApplySign(ErrVal, sign));
}
template<class TRAITS, class STRATEGY>
typename TRAITS::SAMPLE JlsCodec<TRAITS,STRATEGY>::EncodeRegular(int Qs, int x, int pred)
{
int sign = BitWiseSign(Qs);
JlsContext& ctx = _rgcontext[ApplySign(Qs, sign)];
int k = ctx.GetGolomb();
int Px = traits.CorrectPrediction(pred + ApplySign(ctx.C, sign));
int ErrVal = traits.ComputeErrVal(ApplySign(x - Px, sign));
EncodeValue(k, GetMappedErrVal(ctx.GetErrorCorrection(k | traits.NEAR) ^ ErrVal), traits.LIMIT);
ctx.UpdateVariables(ErrVal, traits.NEAR, traits.RESET);
ASSERT(traits.IsNear(traits.ComputeReconstructedSample(Px, ApplySign(ErrVal, sign)), x));
return static_cast<TRAITS::SAMPLE>(traits.ComputeReconstructedSample(Px, ApplySign(ErrVal, sign)));
}
template<class TRAITS, class STRATEGY>
void JlsCodec<TRAITS,STRATEGY>::InitTables()
{
CTable table;
for (int itable = 0; itable < 16; ++ itable)
{
rgtable[itable] = table;
}
for (int k = 0; k < CTable::cbit; k++)
{
for (short nerr = 0; ; nerr++)
{
// Q is not used when k != 0
UINT merrval = GetMappedErrVal(nerr);//, k, -1);
std::pair<int, UINT> paircode = CreateEncodedValue(k, merrval, traits.LIMIT);
if (paircode.first > CTable::cbit)
break;
Code code = Code( nerr, short(paircode.first) );
rgtable[k].AddEntry(BYTE(paircode.second), code);
}
for (short nerr = -1; ; nerr--)
{
// Q is not used when k != 0
UINT merrval = GetMappedErrVal(nerr);//, k, -1);
std::pair<int, UINT> paircode = CreateEncodedValue(k, merrval, traits.LIMIT);
if (paircode.first > CTable::cbit)
break;
Code code = Code(nerr, short(paircode.first));
rgtable[k].AddEntry(BYTE(paircode.second), code);
}
}
}
template<class TRAITS, class STRATEGY>
inlinehint UINT JlsCodec<TRAITS,STRATEGY>::DecodeValue(int k, UINT limit, int qbpp)
{
UINT highbits = ReadHighbits();
if (highbits >= limit - (qbpp + 1))
return ReadValue(qbpp) + 1;
if (k == 0)
return highbits;
return (highbits << k) + ReadValue(k);
}
template<class TRAITS, class STRATEGY>
inlinehint void JlsCodec<TRAITS,STRATEGY>::EncodeValue(int k, UINT mappederval, UINT limit)
{
UINT highbits = mappederval >> k;
if (highbits < limit - traits.qbpp - 1)
{
if (highbits + 1 > 31)
{
AppendToBitStream(0, highbits / 2);
highbits = highbits - highbits / 2;
}
AppendToBitStream(1, highbits + 1);
AppendToBitStream((mappederval & ((1 << k) - 1)), k);
return;
}
if (limit - traits.qbpp > 31)
{
AppendToBitStream(0, 31);
AppendToBitStream(1, limit - traits.qbpp - 31);
}
else
{
AppendToBitStream(1, limit - traits.qbpp);
}
AppendToBitStream((mappederval - 1) & ((1 << traits.qbpp) - 1), traits.qbpp);
}
template<class TRAITS, class STRATEGY>
inlinehint std::pair<int, UINT> JlsCodec<TRAITS,STRATEGY>::CreateEncodedValue(int k, UINT mappederval, UINT limit)
{
UINT highbits = mappederval >> k;
if (highbits < limit - traits.qbpp - 1)
{
return std::make_pair(highbits + k + 1, (1 << k) | (mappederval & ((1 << k) - 1)));
}
else
{
return std::make_pair(limit, (1 << traits.qbpp) |(mappederval - 1) & ((1 << traits.qbpp) - 1));
}
}
template<class TRAITS, class STRATEGY>
void JlsCodec<TRAITS,STRATEGY>::InitQuantizationLUT()
{
_pquant = rgquant + 65535;
signed char* pquant = rgquant + 65535;
for (int i = -65535; i < 65535; ++i)
{
*(pquant + i) = QuantizeGratientOrg(i);
}
}
template<class TRAITS, class STRATEGY>
signed char JlsCodec<TRAITS,STRATEGY>::QuantizeGratientOrg(int Di)
{
if (Di <= -T3) return -4;
if (Di <= -T2) return -3;
if (Di <= -T1) return -2;
if (Di < -traits.NEAR) return -1;
if (Di <= traits.NEAR) return 0;
if (Di < T1) return 1;
if (Di < T2) return 2;
if (Di < T3) return 3;
return 4;
}
template<class TRAITS, class STRATEGY>
void JlsCodec<TRAITS,STRATEGY>::EncodeRunPixels(int RUNcnt, bool bEndofline)
{
while (RUNcnt >= (1 << J[RUNindex]))
{
AppendOnesToBitStream(1);
RUNcnt = RUNcnt - (1 << J[RUNindex]);
IncrementRunIndex();
}
if (bEndofline)
{
if (RUNcnt != 0)
{
AppendOnesToBitStream(1);
}
}
else
{
AppendToBitStream(RUNcnt, J[RUNindex] + 1); // leading 0 + actual remaining length
}
}
template<class TRAITS, class STRATEGY>
int JlsCodec<TRAITS,STRATEGY>::DecodeRunPixels(PIXEL Ra, PIXEL* ptype, PIXEL* ptypeUnc, int ipixel, int cpixelMac)
{
while (ReadBit())
{
int cpixel = min(1 << J[RUNindex], cpixelMac - ipixel);
for (int i = 0; i < cpixel; ++i)
{
ptype[ipixel] = Ra;
CheckedAssign(ptypeUnc[ipixel], ptype[ipixel]);
ipixel++;
ASSERT(ipixel <= cpixelMac);
}
if (cpixel == (1 << J[RUNindex]))
{
IncrementRunIndex();
}
if (ipixel == cpixelMac)
return ipixel;
}
// incomplete run
UINT cpixelRun = (J[RUNindex] > 0) ? ReadValue(J[RUNindex]) : 0;
for (UINT i = 0; i < cpixelRun; ++i)
{
ptype[ipixel] = Ra;
CheckedAssign(ptypeUnc[ipixel], ptype[ipixel]);
ipixel++;
}
return ipixel;
}
template<class TRAITS, class STRATEGY>
int JlsCodec<TRAITS,STRATEGY>::DecodeRISample(CContextRunMode& ctx)
{
int k = ctx.GetGolomb();
UINT EMErrval = DecodeValue(k, traits.LIMIT - J[RUNindex]-1, traits.qbpp);
int Errval = ctx.ComputeErrVal(EMErrval + ctx._nRItype, k);
ctx.UpdateVariables(Errval, EMErrval);
return Errval;
}
template<class TRAITS, class STRATEGY>
void JlsCodec<TRAITS,STRATEGY>::EncodeRISample(CContextRunMode& ctx, int Errval)
{
int k = ctx.GetGolomb();
bool map = ctx.ComputeMap(Errval, k);
UINT EMErrval = 2 * abs(Errval) - ctx._nRItype - map;
ASSERT(Errval == ctx.ComputeErrVal(EMErrval + ctx._nRItype, k));
EncodeValue(k, EMErrval, traits.LIMIT-J[RUNindex]-1);
ctx.UpdateVariables(Errval, EMErrval);
}
template<class TRAITS, class STRATEGY>
Triplet JlsCodec<TRAITS,STRATEGY>::DecodeRIPixel(Triplet Ra, Triplet Rb)
{
int Errval1 = DecodeRISample(_contextRunmode[0]);
int Errval2 = DecodeRISample(_contextRunmode[0]);
int Errval3 = DecodeRISample(_contextRunmode[0]);
//*
return Triplet(traits.ComputeReconstructedSample(Rb.v1, Errval1 * Sign(Rb.v1 - Ra.v1)),
traits.ComputeReconstructedSample(Rb.v2, Errval2 * Sign(Rb.v2 - Ra.v2)),
traits.ComputeReconstructedSample(Rb.v3, Errval3 * Sign(Rb.v3 - Ra.v3)));
/*/
return Triplet(Rb.v1 + Errval1 * Sign(Rb.v1 - Ra.v1),
Rb.v2 + Errval2 * Sign(Rb.v2 - Ra.v2),
Rb.v3 + Errval3 * Sign(Rb.v3 - Ra.v3));
//*/
}
template<class TRAITS, class STRATEGY>
Triplet JlsCodec<TRAITS,STRATEGY>::EncodeRIPixel(Triplet x, Triplet Ra, Triplet Rb)
{
const int RItype = 0;
int errval1 = traits.ComputeErrVal(Sign(Rb.v1 - Ra.v1) * (x.v1 - Rb.v1));
EncodeRISample(_contextRunmode[RItype], errval1);
int errval2 = traits.ComputeErrVal(Sign(Rb.v2 - Ra.v2) * (x.v2 - Rb.v2));
EncodeRISample(_contextRunmode[RItype], errval2);
int errval3 = traits.ComputeErrVal(Sign(Rb.v3 - Ra.v3) * (x.v3 - Rb.v3));
EncodeRISample(_contextRunmode[RItype], errval3);
return x;
}
template<class TRAITS, class STRATEGY>
typename TRAITS::PIXEL JlsCodec<TRAITS,STRATEGY>::DecodeRIPixel(int Ra, int Rb)
{
if (abs(Ra - Rb) <= traits.NEAR)
{
int ErrVal = DecodeRISample(_contextRunmode[1]);
return static_cast<SAMPLE>(traits.ComputeReconstructedSample(Ra, ErrVal));
}
else
{
int ErrVal = DecodeRISample(_contextRunmode[0]);
return static_cast<SAMPLE>(traits.ComputeReconstructedSample(Rb, ErrVal * Sign(Rb - Ra)));
}
}
template<class TRAITS, class STRATEGY>
typename TRAITS::SAMPLE JlsCodec<TRAITS,STRATEGY>::EncodeRIPixel(int x, int Ra, int Rb)
{
if (abs(Ra - Rb) <= traits.NEAR)
{
int ErrVal = traits.ComputeErrVal(x - Ra);
EncodeRISample(_contextRunmode[1], ErrVal);
return static_cast<TRAITS::SAMPLE>(traits.ComputeReconstructedSample(Ra, ErrVal));
}
else
{
int ErrVal = traits.ComputeErrVal((x - Rb) * Sign(Rb - Ra));
EncodeRISample(_contextRunmode[0], ErrVal);
return static_cast<TRAITS::SAMPLE>(traits.ComputeReconstructedSample(Rb, ErrVal * Sign(Rb - Ra)));
}
}
template<class TRAITS, class STRATEGY>
int JlsCodec<TRAITS,STRATEGY>::EncodeRunMode(PIXEL* ptype, const PIXEL* ptypeUnc, const PIXEL* ptypePrev, int ipixel, int ctypeRem)
{
ptype += ipixel;
ptypeUnc += ipixel;
ptypePrev += ipixel;
ctypeRem -= ipixel;
PIXEL Ra = ptype[-1];
int RUNcnt = 0;
while (traits.IsNear(ptypeUnc[RUNcnt],Ra))
{
ptype[RUNcnt] = Ra;
RUNcnt++;
if (RUNcnt == ctypeRem)
break;
}
EncodeRunPixels(RUNcnt, RUNcnt == ctypeRem);
if (RUNcnt == ctypeRem)
return ipixel + RUNcnt;
ptype[RUNcnt] = EncodeRIPixel(ptypeUnc[RUNcnt], Ra, ptypePrev[RUNcnt]);
ASSERT(traits.IsNear(ptype[RUNcnt], ptypeUnc[RUNcnt]));
DecrementRunIndex();
return ipixel + RUNcnt + 1;
}
template<class TRAITS, class STRATEGY>
int JlsCodec<TRAITS,STRATEGY>::DecodeRunMode(PIXEL Ra, PIXEL* ptype, PIXEL* ptypeUnc, const PIXEL* ptypePrev, int ipixel, int cpixelMac)
{
ipixel = DecodeRunPixels(Ra, ptype, ptypeUnc, ipixel, cpixelMac);
if (ipixel == cpixelMac)
return ipixel;
// run interruption
PIXEL Rb = ptypePrev[ipixel];
ptype[ipixel] = DecodeRIPixel(Ra, Rb);
CheckedAssign(ptypeUnc[ipixel], ptype[ipixel]);
DecrementRunIndex();
return ipixel + 1;
}
template<class TRAITS, class STRATEGY>
void JlsCodec<TRAITS,STRATEGY>::DoLine(typename TRAITS::SAMPLE* ptype, const typename TRAITS::SAMPLE* ptypePrev, int csample, typename TRAITS::SAMPLE* ptypeUnc, DecoderStrategy*)
{
int ipixel = 0;
int Rb = ptypePrev[ipixel-1];
int Rd = ptypePrev[ipixel];
while(ipixel < csample)
{
int Ra = ptype[ipixel -1];
int Rc = Rb;
Rb = Rd;
Rd = ptypePrev[ipixel + 1];
int Qs = ComputeContextID(QuantizeGratient(Rd - Rb), QuantizeGratient(Rb - Rc), QuantizeGratient(Rc - Ra));
if (Qs == 0)
{
ipixel = DecodeRunMode((SAMPLE)Ra, ptype, ptypeUnc, ptypePrev, ipixel, csample);
Rb = ptypePrev[ipixel-1];
Rd = ptypePrev[ipixel];
}
else
{
ptype[ipixel] = DecodeRegular(Qs, GetPredictedValue(Ra, Rb, Rc));
CheckedAssign(ptypeUnc[ipixel], ptype[ipixel]);
ipixel++;
}
}
}
template<class TRAITS, class STRATEGY>
void JlsCodec<TRAITS,STRATEGY>::DoLine(typename TRAITS::SAMPLE* ptype, const typename TRAITS::SAMPLE* ptypePrev, int csample, const typename TRAITS::SAMPLE* ptypeUnc, EncoderStrategy*)
{
int ipixel = 0;
int Rb = ptypePrev[ipixel-1];
int Rd = ptypePrev[ipixel];
while(ipixel < csample)
{
int Ra = ptype[ipixel -1];
int Rc = Rb;
Rb = Rd;
Rd = ptypePrev[ipixel + 1];
int Qs = ComputeContextID(QuantizeGratient(Rd - Rb), QuantizeGratient(Rb - Rc), QuantizeGratient(Rc - Ra));
if (Qs == 0)
{
ipixel = EncodeRunMode(ptype, ptypeUnc, ptypePrev, ipixel, csample);
Rb = ptypePrev[ipixel-1];
Rd = ptypePrev[ipixel];
}
else
{
ptype[ipixel] = EncodeRegular(Qs, ptypeUnc[ipixel], GetPredictedValue(Ra, Rb, Rc));
ipixel++;
}
}
}
template<class TRAITS, class STRATEGY>
void JlsCodec<TRAITS,STRATEGY>::DoLine(Triplet* ptype, Triplet* ptypePrev, int csample, Triplet* ptypeUnc, EncoderStrategy*)
{
int ipixel = 0;
while(ipixel < csample)
{
Triplet Ra = ptype[ipixel -1];
Triplet Rc = ptypePrev[ipixel-1];
Triplet Rb = ptypePrev[ipixel];
Triplet Rd = ptypePrev[ipixel + 1];
int Qs1 = ComputeContextID(QuantizeGratient(Rd.v1 - Rb.v1), QuantizeGratient(Rb.v1 - Rc.v1), QuantizeGratient(Rc.v1 - Ra.v1));
int Qs2 = ComputeContextID(QuantizeGratient(Rd.v2 - Rb.v2), QuantizeGratient(Rb.v2 - Rc.v2), QuantizeGratient(Rc.v2 - Ra.v2));
int Qs3 = ComputeContextID(QuantizeGratient(Rd.v3 - Rb.v3), QuantizeGratient(Rb.v3 - Rc.v3), QuantizeGratient(Rc.v3 - Ra.v3));
if (Qs1 == 0 && Qs2 == 0 && Qs3 == 0)
{
ipixel = EncodeRunMode(ptype, ptypeUnc, ptypePrev, ipixel, csample);
}
else
{
Triplet Rx;
Rx.v1 = EncodeRegular(Qs1, ptypeUnc[ipixel].v1, GetPredictedValue(Ra.v1, Rb.v1, Rc.v1));
Rx.v2 = EncodeRegular(Qs2, ptypeUnc[ipixel].v2, GetPredictedValue(Ra.v2, Rb.v2, Rc.v2));
Rx.v3 = EncodeRegular(Qs3, ptypeUnc[ipixel].v3, GetPredictedValue(Ra.v3, Rb.v3, Rc.v3));
ptype[ipixel] = Rx;
ipixel++;
}
}
};
template<class TRAITS, class STRATEGY>
void JlsCodec<TRAITS,STRATEGY>::DoLine(Triplet* ptype, Triplet* ptypePrev, int csample, Triplet* ptypeUnc, DecoderStrategy*)
{
int ipixel = 0;
while(ipixel < csample)
{
Triplet Ra = ptype[ipixel -1];
Triplet Rc = ptypePrev[ipixel-1];
Triplet Rb = ptypePrev[ipixel];
Triplet Rd = ptypePrev[ipixel + 1];
int Qs1 = ComputeContextID(QuantizeGratient(Rd.v1 - Rb.v1), QuantizeGratient(Rb.v1 - Rc.v1), QuantizeGratient(Rc.v1 - Ra.v1));
int Qs2 = ComputeContextID(QuantizeGratient(Rd.v2 - Rb.v2), QuantizeGratient(Rb.v2 - Rc.v2), QuantizeGratient(Rc.v2 - Ra.v2));
int Qs3 = ComputeContextID(QuantizeGratient(Rd.v3 - Rb.v3), QuantizeGratient(Rb.v3 - Rc.v3), QuantizeGratient(Rc.v3 - Ra.v3));
if (Qs1 == 0 && Qs2 == 0 && Qs3 == 0)
{
ipixel = DecodeRunMode(Ra, ptype, ptypeUnc, ptypePrev, ipixel, csample);
}
else
{
BYTE value1 = DecodeRegular(Qs1, GetPredictedValue(Ra.v1, Rb.v1, Rc.v1));
BYTE value2 = DecodeRegular(Qs2, GetPredictedValue(Ra.v2, Rb.v2, Rc.v2));
BYTE value3 = DecodeRegular(Qs3, GetPredictedValue(Ra.v3, Rb.v3, Rc.v3));
ptype[ipixel] = Triplet(value1, value2, value3);
CheckedAssign(ptypeUnc[ipixel], ptype[ipixel]);
ipixel++;
}
}
}
template<class TRAITS, class STRATEGY>
void JlsCodec<TRAITS,STRATEGY>::DoScan(PIXEL* ptype, Size size, BYTE* pbyteCompressed, int cbyteCompressed)
{
Init(pbyteCompressed, cbyteCompressed);
std::vector<PIXEL> vectmp;
vectmp.resize(2 * ( size.cx + 4));
PIXEL* ptypePrev = &vectmp[1];
PIXEL* ptypeCur = &vectmp[size.cx + 4 + 1];
for (int iline = 0; iline < size.cy; ++iline)
{
ptypePrev[size.cx] = ptypePrev[size.cx - 1];
ptypeCur[-1] = ptypePrev[0];
DoLine(ptypeCur, ptypePrev, size.cx, ptype + iline * size.cx, (STRATEGY*)(NULL));
std::swap(ptypePrev, ptypeCur);
}
}
template<class TRAITS, class STRATEGY>
int JlsCodec<TRAITS,STRATEGY>::EncodeScan(const void* pvoid, const Size& size, void* pvoidOut, int cbyte, void* pvoidCompare)
{
const PIXEL* ptype = static_cast<const PIXEL*>(pvoid);
BYTE* pbyteCompressed = static_cast<BYTE*>(pvoidOut);
if (pvoidCompare != NULL)
{
DecoderStrategy* pdecoder = new JlsCodec<TRAITS,DecoderStrategy>(traits);
BYTE* pbyteCompare = (BYTE*)pvoidCompare;
pdecoder->Init(pbyteCompare, cbyte);
EncoderStrategy::_qdecoder = pdecoder;
}
DoScan(const_cast<PIXEL*>(ptype), size, pbyteCompressed, cbyte);
Flush();
return GetLength();
}
template<class TRAITS, class STRATEGY>
int JlsCodec<TRAITS,STRATEGY>::DecodeScan(void* pvoidOut, const Size& size, const void* pvoidIn, int cbyte, bool bCompare)
{
PIXEL* ptypeOut = static_cast<PIXEL*>(pvoidOut);
BYTE* pbyteCompressed = const_cast<BYTE*>(static_cast<const BYTE*>(pvoidIn));
_bCompare = bCompare;
BYTE rgbyte[20];
int cbyteRead = 0;
::memcpy(rgbyte, pbyteCompressed, 4);
cbyteRead += 4;
int cbyteScanheader = rgbyte[3] - 2;
::memcpy(rgbyte, pbyteCompressed, cbyteScanheader);
cbyteRead += cbyteScanheader;
DoScan(const_cast<PIXEL*>(ptypeOut), size, pbyteCompressed + cbyteRead, cbyte);
return GetCurBytePos() - pbyteCompressed;
}
template<class TRAITS, class STRATEGY>
void JlsCodec<TRAITS,STRATEGY>::InitParams(int t1, int t2, int t3, int nReset)
{
T1 = t1;
T2 = t2;
T3 = t3;
//if (f_bTableMaxVal != traits.MAXVAL)
{
f_bTableMaxVal = traits.MAXVAL;
InitQuantizationLUT();
InitTables();
}
JlsContext ctxDefault = JlsContext(max(2, (traits.RANGE + 32)/64));
for (UINT Q = 0; Q < sizeof(_rgcontext) / sizeof(_rgcontext[0]); ++Q)
{
_rgcontext[Q] = ctxDefault;
}
_contextRunmode[0] = CContextRunMode(max(2, (traits.RANGE + 32)/64), 0, nReset);
_contextRunmode[1] = CContextRunMode(max(2, (traits.RANGE + 32)/64), 1, nReset);
RUNindex = 0;
}

6
stdafx.cpp Normal file
View File

@ -0,0 +1,6 @@
//
// (C) Jan de Vaan 2007-2009, all rights reserved. See the accompanying "License.txt" for licensed use.
//
#include "stdafx.h"

27
stdafx.h Normal file
View File

@ -0,0 +1,27 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
typedef unsigned int UINT;
typedef unsigned char BYTE;
typedef unsigned short USHORT;
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifdef _DEBUG
#include <assert.h>
#define ASSERT(t) assert(t)
#else
#define ASSERT(t) ;
#endif

146
streams.h Normal file
View File

@ -0,0 +1,146 @@
//
// (C) Jan de Vaan 2007-2009, all rights reserved. See the accompanying "License.txt" for licensed use.
//
#pragma once
#include <vector>
#include "util.h"
struct ScanInfo
{
ScanInfo() :
cbit(0),
nnear(0),
ccomp(0),
ilv(ILV_NONE),
size(0,0)
{
}
int cbit;
int nnear;
int ccomp;
interleavemode ilv;
Size size;
};
class JpegSegment;
//
// JLSOutputStream: minimal implementation to write JPEG header streams
//
class JLSOutputStream
{
friend class JpegMarkerSegment;
friend class JpegImageDataSegment;
public:
JLSOutputStream();
virtual ~JLSOutputStream();
void Init(int ccomp, int ccol, int cline, int cbpp);
void AddScan(const void* pbyteComp, Size size, int cbit, int ccomp, interleavemode ilv, int nearval);
int GetBytesWritten()
{ return _cbyteOffset; }
int GetLength()
{ return _cbyteLength - _cbyteOffset; }
int Write(BYTE* pdata, int cbyteLength, const void* pbyteExpected);
private:
BYTE* GetPos() const
{ return _pdata + _cbyteOffset; }
void WriteByte(BYTE val)
{ _pdata[_cbyteOffset++] = val; }
void WriteBytes(const std::vector<BYTE>& rgbyte)
{
for (UINT i = 0; i < rgbyte.size(); ++i)
{
WriteByte(rgbyte[i]);
}
}
void WriteWord(USHORT val)
{
WriteByte(BYTE(val / 0x100));
WriteByte(BYTE(val % 0x100));
}
void Seek(int cbyte)
{ _cbyteOffset += cbyte; }
private:
BYTE* _pdata;
int _cbyteOffset;
int _cbyteLength;
int _icompLast;
std::vector<JpegSegment*> _rgsegment;
};
struct Presets
{
public:
Presets() :
MAXVAL(0),
T1(0),
T2(0),
T3(0),
RESET(0)
{
}
int MAXVAL;
int T1;
int T2;
int T3;
int RESET;
};
//
// JLSInputStream: minimal implementation to read JPEG header streams
//
class JLSInputStream
{
public:
JLSInputStream(const BYTE* pdata, int cbyteLength);
int GetBytesRead()
{ return _cbyteOffset; }
const ScanInfo& GetMetadata() const
{ return _info; }
bool Read(void* pvoid);
int ReadHeader();
void EnableCompare(bool bCompare)
{ _bCompare = bCompare; }
private:
bool ReadPixels(void* pvoid);
void ReadScan(void*);
void ReadStartOfScan();
void ReadPresetParameters();
void ReadComment();
void ReadStartOfFrame();
int ReadByte();
int ReadWord();
private:
const BYTE* _pdata;
int _cbyteOffset;
int _cbyteLength;
bool _bCompare;
Presets _presets;
ScanInfo _info;
};

406
test.cpp Normal file
View File

@ -0,0 +1,406 @@
//
// (C) Jan de Vaan 2007-2009, all rights reserved. See the accompanying "License.txt" for licensed use.
//
#include "stdafx.h"
#include "stdio.h"
#include <vector>
#include <iostream>
#include "header.h"
#include "streams.h"
#include "defaulttraits.h"
#include "losslesstraits.h"
#pragma warning (disable: 4996)
UINT timeGetTime() { return 0; }
int ReadJLSHeader(void* pdata, ScanInfo* pmetadata, int cbyte)
{
JLSInputStream reader((BYTE*)pdata, cbyte);
reader.ReadHeader();
*pmetadata = reader.GetMetadata();
return reader.GetBytesRead();
}
int Decode(void* pvoid, int cbyte, const BYTE* pbytecompressed, int cbytecompr, const void* pbyteExpected = NULL)
{
JLSInputStream reader(pbytecompressed, cbytecompr);
if (pbyteExpected != NULL)
{
::memcpy(pvoid, pbyteExpected, cbyte);
reader.EnableCompare(true);
}
if (!reader.Read(pvoid))
return -1;
return reader.GetBytesRead();
}
int Encode(const void* pbyte, Size size, int cbit, int ccomp, interleavemode ilv, BYTE* pbytecompressed, int cbytecompr, int nearval, const void* pbyteExpected = NULL)
{
JLSOutputStream stream;
stream.Init(size.cx, size.cy, cbit, ccomp);
if (ilv == ILV_NONE)
{
int cbyteComp = size.cx*size.cy*((cbit +7)/8);
for (int icomp = 0; icomp < ccomp; ++icomp)
{
const BYTE* pbyteComp = static_cast<const BYTE*>(pbyte) + icomp*cbyteComp;
stream.AddScan(pbyteComp, size, cbit, 1, ILV_NONE, nearval);
}
}
else
{
stream.AddScan(pbyte, size, cbit, ccomp, ilv, nearval);
}
stream.Write(pbytecompressed, cbytecompr, pbyteExpected);
return stream.GetBytesWritten();
}
// int double SZC int* void*
typedef const char* SZC;
template <class TYPE>
struct validprintfchar;
void WriteFile(SZC szcName, void* pvoidData, int cbyte)
{
FILE* pfile = fopen(szcName, "wb");
fwrite(pvoidData, 1, cbyte, pfile);
fclose(pfile);
}
void ReadFile(SZC strName, std::vector<BYTE>* pvec, int ioffs = 0)
{
FILE* pfile = fopen(strName, "rb");
fseek(pfile, 0, SEEK_END);
int cbyteFile = ftell(pfile);
fseek(pfile, ioffs, SEEK_SET);
pvec->resize(cbyteFile-ioffs);
fread(&(*pvec)[0],1, pvec->size(), pfile);
fclose(pfile);
}
void SwapBytes(std::vector<BYTE>* rgbyte)
{
for (UINT i = 0; i < rgbyte->size(); i += 2)
{
std::swap((*rgbyte)[i], (*rgbyte)[i + 1]);
}
}
void Test(const char* strName, const BYTE* rgbyteRaw, Size size, int cbit, int ccomp)
{
std::vector<BYTE> pbyteCompressed;
pbyteCompressed.resize(size.cx *size.cy * 4);
std::vector<BYTE> rgbyteOut;
rgbyteOut.resize(size.cx * size.cy * ((cbit + 7) / 8));
UINT dwstart = timeGetTime();
size_t cbyteCompressed = Encode(rgbyteRaw, size, cbit, ccomp, ccomp == 3 ? ILV_SAMPLE : ILV_NONE, &pbyteCompressed[0], int(pbyteCompressed.size()), 0);
//CString strDst = strName;
//strDst = strDst + ".jls";
//WriteFile(strDst.GetString(), &pbyteCompressed[0], cbyteCompressed);
UINT dwtimeEncodeComplete = timeGetTime();
Decode(&rgbyteOut[0], rgbyteOut.size(), &pbyteCompressed[0], int(cbyteCompressed), rgbyteRaw);
UINT dwtimeDecodeComplete = timeGetTime();
double dblfactor = 1.0 * rgbyteOut.size() / cbyteCompressed;
std::cout << "RoundTrip test for: " << strName << "\n\r";
printf("Encode: %lu Decode: %lu Ratio: %f \n\r", dwtimeEncodeComplete - dwstart, dwtimeDecodeComplete - dwtimeEncodeComplete, dblfactor);
BYTE* pbyteOut = &rgbyteOut[0];
for (UINT i = 0; i < rgbyteOut.size(); ++i)
{
if (rgbyteRaw[i] != pbyteOut[i])
{
ASSERT(false);
break;
}
}
}
void TestJls(std::vector<BYTE>& rgbyteRaw, Size size, int cbit, int ccomp, interleavemode ilv, const BYTE* rgbyteFile, int cbyteCompressed, bool bNear)
{
if (cbit > 8 && cbit <= 16)
{
SwapBytes(&rgbyteRaw);
}
std::vector<BYTE> rgbyteTest;
rgbyteTest.resize(2 *cbyteCompressed );
UINT cbyte = Encode(&rgbyteRaw[0], size, cbit, ccomp, ilv, &rgbyteTest[0], int(rgbyteTest.size()), bNear ? 3 : 0, rgbyteFile);
WriteFile("test.jls", &rgbyteTest[0], cbyte);
JLSInputStream reader(rgbyteFile, cbyteCompressed);
std::vector<BYTE> rgbyteUnc;
rgbyteUnc.resize(size.cx * size.cy * ((cbit + 7) / 8) * ccomp);
Decode(&rgbyteUnc[0], rgbyteUnc.size(), rgbyteFile, cbyteCompressed, &rgbyteRaw[0]);
WriteFile("test.raw", &rgbyteUnc[0], rgbyteUnc.size());
}
void TestNear(char* strNameEncoded, Size size, int cbit)
{
std::vector<BYTE> rgbyteFile;
ReadFile(strNameEncoded, &rgbyteFile);
std::vector<BYTE> rgbyteUnc;
rgbyteUnc.resize(size.cx * size.cy * ((cbit + 7) / 8));
Decode(&rgbyteUnc[0], rgbyteUnc.size(), &rgbyteFile[0], rgbyteFile.size());
}
void Triplet2Planar(std::vector<BYTE>& rgbyte, Size size)
{
std::vector<BYTE> rgbytePlanar(rgbyte.size());
int cbytePlane = size.cx * size.cy;
for (int ipixel = 0; ipixel < cbytePlane; ipixel++)
{
rgbytePlanar[ipixel] = rgbyte[ipixel * 3 + 0];
rgbytePlanar[ipixel + 1*cbytePlane] = rgbyte[ipixel * 3 + 1];
rgbytePlanar[ipixel + 2*cbytePlane] = rgbyte[ipixel * 3 + 2];
}
std::swap(rgbyte, rgbytePlanar);
}
void DecompressFile(SZC strNameEncoded, SZC strNameRaw, int ioffs)
{
std::cout << "Conformance test:" << strNameEncoded << "\n\r";
std::vector<BYTE> rgbyteFile;
ReadFile(strNameEncoded, &rgbyteFile);
std::vector<BYTE> rgbyteRaw;
ReadFile(strNameRaw, &rgbyteRaw, ioffs);
ScanInfo metadata;
int cbyteHeader = ReadJLSHeader(&rgbyteFile[0], &metadata, rgbyteFile.size());
if (cbyteHeader == 0)
{
ASSERT(false);
return;
}
if (metadata.ilv == ILV_NONE && metadata.ccomp == 3)
{
Triplet2Planar(rgbyteRaw, metadata.size);
}
TestJls(rgbyteRaw, metadata.size, metadata.cbit, metadata.ccomp, metadata.ilv, &rgbyteFile[0], rgbyteFile.size(), metadata.nnear != 0);
}
void TestFile(SZC strName, int ioffs, Size size2, int cbit, int ccomp)
{
std::vector<BYTE> rgbyteNoise;
ReadFile(strName, &rgbyteNoise, ioffs);
Test(strName, &rgbyteNoise[0], size2, cbit, ccomp);
};
const BYTE rgbyte[] = { 0, 0, 90, 74,
68, 50, 43, 205,
64, 145, 145, 145,
100, 145, 145, 145};
const BYTE rgbyteComp[] = { 0xFF, 0xD8, 0xFF, 0xF7, 0x00, 0x0B, 0x08, 0x00, 0x04, 0x00, 0x04, 0x01, 0x01, 0x11, 0x00, 0xFF, 0xDA, 0x00, 0x08, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0xC0, 0x00, 0x00, 0x6C, 0x80, 0x20, 0x8E,
0x01, 0xC0, 0x00, 0x00, 0x57, 0x40, 0x00, 0x00, 0x6E, 0xE6, 0x00, 0x00, 0x01, 0xBC, 0x18, 0x00,
0x00, 0x05, 0xD8, 0x00, 0x00, 0x91, 0x60, 0xFF, 0xD9};
void TestAnnexH3()
{
Size size = Size(4,4);
std::vector<BYTE> vecRaw(16);
memcpy(&vecRaw[0], rgbyte, 16);
TestJls(vecRaw, size, 8, 1, ILV_NONE, rgbyteComp, sizeof(rgbyteComp), false);
}
void TestConformanceLosslessMode()
{
// Test 1
DecompressFile("..\\test\\conformance\\t8c0e0.jls", "..\\test\\conformance\\test8.ppm",15);
// Test 2
// Test 3
DecompressFile("..\\test\\conformance\\t8c2e0.jls", "..\\test\\conformance\\test8.ppm", 15);
// Test 4
DecompressFile("..\\test\\conformance\\t8c0e3.jls", "..\\test\\conformance\\test8.ppm",15);
// Test 5
// Test 6
DecompressFile("..\\test\\conformance\\t8c2e3.jls", "..\\test\\conformance\\test8.ppm",15);
// Test 7
// Test 8
// Test 9
DecompressFile("..\\test\\conformance\\t8nde0.jls", "..\\test\\conformance\\test8bs2.pgm",15);
// Test 10
DecompressFile("..\\test\\conformance\\t8nde3.jls", "..\\test\\conformance\\test8bs2.pgm",15);
// Test 11
DecompressFile("..\\test\\conformance\\t16e0.jls", "..\\test\\conformance\\test16.pgm",16);
// Test 12
DecompressFile("..\\test\\conformance\\t16e3.jls", "..\\test\\conformance\\test16.pgm",16);
// additional, Lena compressed with other codec (UBC?), vfy with CharLS
DecompressFile("..\\test\\lena8b.jls", "..\\test\\lena8b.raw",0);
}
void TestNoiseImage()
{
srand(21344);
Size size2 = Size(1024, 1024);
std::vector<BYTE> rgbyteNoise;
rgbyteNoise.resize( size2.cx * size2.cy);
for (int iline = 0; iline<size2.cy; ++iline)
{
for (int icol= 0; icol<size2.cx; ++icol)
{
BYTE val = BYTE(rand());
rgbyteNoise[iline*size2.cx + icol] = BYTE(val & 0x7F);// < iline ? val : 0;
}
}
Test("noise", &rgbyteNoise[0], size2, 7, 1);
}
void TestPerformance()
{
Size size1024 = Size(1024, 1024);
Size size512 = Size(512, 512);
TestFile("..\\test\\mr2_unc", 1728, size1024, 16, 1);
TestFile("..\\test\\0015.raw", 0, size1024, 8, 1);
TestFile("..\\test\\lena8b.raw", 0, size512, 8, 1);
}
void TestTraits16bit()
{
DefaultTraitsT<USHORT,USHORT> traits1 = DefaultTraitsT<USHORT,USHORT>(4095,0);
LosslessTraitsT<USHORT,12> traits2 = LosslessTraitsT<USHORT,12>();
ASSERT(traits1.LIMIT == traits2.LIMIT);
ASSERT(traits1.MAXVAL == traits2.MAXVAL);
ASSERT(traits1.RESET == traits2.RESET);
ASSERT(traits1.bpp == traits2.bpp);
ASSERT(traits1.qbpp == traits2.qbpp);
for (int i = -4096; i < 4096; ++i)
{
ASSERT(traits1.ModRange(i) == traits2.ModRange(i));
ASSERT(traits1.ComputeErrVal(i) == traits2.ComputeErrVal(i));
}
for (int i = -8095; i < 8095; ++i)
{
ASSERT(traits1.CorrectPrediction(i) == traits2.CorrectPrediction(i));
ASSERT(traits1.IsNear(i,2) == traits2.IsNear(i,2));
}
}
void TestTraits8bit()
{
DefaultTraitsT<BYTE,BYTE> traits1 = DefaultTraitsT<BYTE,BYTE>(255,0);
LosslessTraitsT<BYTE,8> traits2 = LosslessTraitsT<BYTE,8>();
ASSERT(traits1.LIMIT == traits2.LIMIT);
ASSERT(traits1.MAXVAL == traits2.MAXVAL);
ASSERT(traits1.RESET == traits2.RESET);
ASSERT(traits1.bpp == traits2.bpp);
ASSERT(traits1.qbpp == traits2.qbpp);
for (int i = -255; i < 255; ++i)
{
ASSERT(traits1.ModRange(i) == traits2.ModRange(i));
ASSERT(traits1.ComputeErrVal(i) == traits2.ComputeErrVal(i));
}
for (int i = -255; i < 512; ++i)
{
ASSERT(traits1.CorrectPrediction(i) == traits2.CorrectPrediction(i));
ASSERT(traits1.IsNear(i,2) == traits2.IsNear(i,2));
}
}
extern "C"
{
void __declspec(dllexport) __cdecl Test()
{
TestTraits16bit();
TestTraits8bit();
TestConformanceLosslessMode();
TestPerformance();
TestNoiseImage();
TestAnnexH3();
}
}

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

1
test/..svnbridge/MR2_UNC Normal file
View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

BIN
test/0015.raw Normal file

Binary file not shown.

BIN
test/MR2_UNC Normal file

Binary file not shown.

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>

View File

@ -0,0 +1,90 @@
JPEG-LS TEST IMAGES
===================
The images included in this package constitute the data set used for
implementing the JPEG-LS conformance test as described in Section 8
and Annex E of the JPEG-LS standard document (ITU-T Rec. T.87|ISO/IEC 14495-1).
Test images:
------------
(See explanation of PPM and PGM formats below)
TEST8.PPM - 8-bit color test image (photo+graphics+text+random data).
TEST8R.PGM - "red" component of TEST8
TEST8G.PGM - "green" component of TEST8
TEST8B.PGM - "blue" component of TEST8
TEST8GR4.PGM - "green" component of TEST8, subsampled 4X in the vertical
direction
TEST8BS2.PGM - "blue" component of TEST8, subsampled 2X in both directions
TEST16.PGM - 16-bit test gray-scale image (actually 12-bit)
Compressed images:
------------------
T8CxEy.JLS x=0,1,2 y=0,3
Image TEST8 compressed in color mode x with near-lossless error y
(y=0 means lossless).
T16Ey.JLS y=0,3
Image TEST16 compressed with near-lossless error y.
T8SSE0.JLS
T8SSE3.JLS
Image TEST8 compressed in line-interleaved mode, with near-lossless
error 0 and 3 (resp.), and with color components subsampled
as follows:
R: not subsampled (256 cols x 256 rows)
G: subsampled 4x in the vertical direction (256 cols x 64 rows)
B: subsampled 2x in both directions (128 cols x 128 rows)
T8NDE0.JLS
T8NDE3.JLS
Image TEST8 compressed in line-interleaved mode, with near-lossless
error 0 and 3 (resp.), and with NON-DEFAULT parameters T1=T2=T3=9,
RESET=31.
The compressed images are provided to help testers/developers debug their
JPEG-LS implementations. The test images contain a mixture of data that will
exercise many paths in the compression/decompression algorithms. There is
no guarantee, however, that every path of the algorithm is tested.
THE TEST IMAGES SHOULD NOT BE USED TO BENCHMARK COMPRESSION CAPABILITY.
THEY ARE DESIGNED TO BE "HARD" ON THE JPEG-LS COMPRESSOR. JPEG-LS
MAY DO WORSE THAN YOUR FAVORITE COMPRESSOR ON THE TEST IMAGES.
All compressed images have standard JPEG-LS headers (which follow the
standard JPEG marker syntax). All compressed images were produced using
default parameters, except for T8NDE0.JLS and T8NDE3.JLS as noted above.
PPM and PGM INPUT IMAGE FORMATS
-------------------------------
Uncompressed test images images are in either PGM (grayscale) or
PPM (3-color) format. This is of course NOT part of the JPEG-LS
standard.
These formats have an ASCII header consisting of 3 lines of the
following form
* PGM (single component):
P5
cols rows
maxval
* PPM (3 components)
P6
cols rows
maxval
For PGM, the header is followed by cols*rows samples in binary
format, where cols and rows are the number of columns and rows,
respectively. A test image "cmpnd2g.pgm" is included in the
archive. Samples have 8 bits if maxval < 256, or 16 bits if
256 <= maxval < 65536.
For PPM, the header is followed by cols*rows TRIPLETS of symbols in
binary format. Each symbol in a triplet represents a color component
value (viewers usually interpret PPM triplets as RGB).

BIN
test/conformance/T16E0.JLS Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

BIN
test/conformance/T16E3.JLS Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
test/conformance/T16E3.pgm Normal file

Binary file not shown.

BIN
test/conformance/T8C0E0.JLS Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

BIN
test/conformance/T8C0E3.JLS Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
test/conformance/T8C1E0.JLS Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

BIN
test/conformance/T8C1E3.JLS Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
test/conformance/T8C2E0.JLS Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

BIN
test/conformance/T8C2E3.JLS Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

BIN
test/conformance/T8NDE0.JLS Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
test/conformance/T8NDE3.JLS Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

BIN
test/conformance/T8SSE0.JLS Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

BIN
test/conformance/T8SSE3.JLS Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
test/conformance/TEST16.PGM Normal file

Binary file not shown.

BIN
test/conformance/TEST8.PPM Normal file

Binary file not shown.

BIN
test/conformance/TEST8B.PGM Normal file

Binary file not shown.

Binary file not shown.

BIN
test/conformance/TEST8G.PGM Normal file

Binary file not shown.

Binary file not shown.

BIN
test/conformance/TEST8R.PGM Normal file

Binary file not shown.

BIN
test/lena8b.jls Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

340
test/lena8b.raw Normal file

File diff suppressed because one or more lines are too long

BIN
test/mr2_unc.jls Normal file

Binary file not shown.

8
test/stdafx.cpp Normal file
View File

@ -0,0 +1,8 @@
// stdafx.cpp : source file that includes just the standard includes
// test.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file

12
test/stdafx.h Normal file
View File

@ -0,0 +1,12 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <stdio.h>
#include <tchar.h>
// TODO: reference additional headers your program requires here

21
test/test.cpp Normal file
View File

@ -0,0 +1,21 @@
// test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
extern "C"
{
void __declspec(dllexport) Test();
}
int _tmain(int argc, _TCHAR* argv[])
{
Test();
char c;
std::cin >> c;
return 0;
}

BIN
test/test.jls Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 B

BIN
test/test.raw Normal file

Binary file not shown.

234
test/test.vcproj Normal file
View File

@ -0,0 +1,234 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
Name="test"
ProjectGUID="{3E349E7B-30C2-4791-81B7-1108014291B7}"
RootNamespace="test"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="..\$(ConfigurationName)"
IntermediateDirectory="Debug"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="2"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/test.exe"
LinkIncremental="2"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)/test.pdb"
SubSystem="1"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="..\$(ConfigurationName)"
IntermediateDirectory="Release"
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="2"
OmitFramePointers="true"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="2"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/test.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="e:\src\jpegls\$(ConfigurationName)"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
>
<File
RelativePath="stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="test.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc"
>
<File
RelativePath="stdafx.h"
>
</File>
</Filter>
<File
RelativePath="lena8b.jls"
>
</File>
<File
RelativePath="conformance\T16E0.JLS"
>
</File>
<File
RelativePath="conformance\TEST16.PGM"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

85
util.h Normal file
View File

@ -0,0 +1,85 @@
//
// (C) Jan de Vaan 2007-2009, all rights reserved. See the accompanying "License.txt" for licensed use.
//
#pragma once
#pragma pack (push)
#pragma pack (1)
#undef NEAR
#ifdef _DEBUG
#define inlinehint inline
#else
#define inlinehint __forceinline
#endif
enum interleavemode
{
ILV_NONE = 0,
ILV_LINE = 1,
ILV_SAMPLE = 2,
};
const int BASIC_RESET = 64;
inline int log2(UINT n)
{
int x = 0;
while (n > (1U << x))
{
++x;
}
return x;
}
struct Size
{
Size(int width, int height) :
cx(width),
cy(height)
{}
int cx;
int cy;
};
inlinehint int Sign(int n)
{ return (n >> 31) | 1;}
inlinehint int BitWiseSign(int i)
{ return (i >> 31); }
struct Triplet
{
Triplet() :
v1(0),
v2(0),
v3(0)
{};
Triplet(int x1, int x2, int x3) :
v1((BYTE)x1),
v2((BYTE)x2),
v3((BYTE)x3)
{};
BYTE v1;
BYTE v2;
BYTE v3;
};
#pragma pack (pop)
inline bool operator==(const Triplet& lhs, const Triplet& rhs)
{ return lhs.v1 == rhs.v1 && lhs.v2 == rhs.v2 && lhs.v3 == rhs.v3; }
inline bool operator!=(const Triplet& lhs, const Triplet& rhs)
{ return !(lhs == rhs); }