[med-svn] [charls] 08/10: Imported Upstream version 1.1.0+dfsg
Andreas Tille
tille at debian.org
Thu May 19 15:45:52 UTC 2016
This is an automated email from the git hooks/post-receive script.
tille pushed a commit to branch master
in repository charls.
commit f8227066f801c57418625a5308b4c4ff2415b964
Author: Andreas Tille <tille at debian.org>
Date: Thu May 19 17:37:26 2016 +0200
Imported Upstream version 1.1.0+dfsg
---
.gitignore | 24 +
.travis.yml | 28 +
CMakeLists.txt | 68 ++-
CharLS.sln | 49 --
CharLS.vcproj | 545 -------------------
CharLS_VS2015.sln | 54 ++
README.md | 30 ++
appveyor.yml | 14 +
check.cmd | 3 +
decoderstrategy.h | 285 ----------
header.cpp | 627 ----------------------
header.h | 62 ---
interface.cpp | 206 -------
interface.h | 48 --
plainc/plainc.c | 19 +-
plainc/plainc.vcproj | 186 -------
processline.h | 225 --------
publictypes.h | 76 ---
src/JpegStreamWriter.cd | 44 ++
License.txt => src/License.txt | 0
charls.def => src/charls.def | 17 +-
src/charls.rc | Bin 0 -> 3150 bytes
colortransform.h => src/colortransform.h | 3 +
config.h => src/config.h | 10 +-
context.h => src/context.h | 45 +-
contextrunmode.h => src/contextrunmode.h | 16 +-
src/decoderstrategy.h | 325 +++++++++++
defaulttraits.h => src/defaulttraits.h | 17 +-
encoderstrategy.h => src/encoderstrategy.h | 107 ++--
src/header.cpp | 388 ++++++++++++++
src/header.h | 70 +++
src/interface.cpp | 234 ++++++++
src/interface.h | 66 +++
src/jpegimagedatasegment.h | 28 +
jpegls.cpp => src/jpegls.cpp | 3 +-
src/jpegmarker.h | 75 +++
src/jpegmarkersegment.cpp | 120 +++++
src/jpegmarkersegment.h | 40 ++
src/jpegsegment.h | 22 +
src/jpegstreamwriter.cpp | 107 ++++
src/jpegstreamwriter.h | 114 ++++
lookuptable.h => src/lookuptable.h | 0
losslesstraits.h => src/losslesstraits.h | 0
src/processline.h | 346 ++++++++++++
src/publictypes.h | 137 +++++
scan.h => src/scan.h | 217 ++++----
util.h => src/util.h | 11 +-
stdafx.cpp | 0
streams.h | 156 ------
test/CMakeLists.txt | 8 +-
test/bitstreamdamage.cpp | 246 +++++----
test/compliance.cpp | 476 ++++++++---------
test/config.h | 56 +-
test/dicomsamples.cpp | 156 +++---
test/main.cpp | 831 ++++++++++++++++++++---------
test/performance.cpp | 180 +++----
test/test.vcproj | 415 --------------
test/time.cpp | 77 ++-
test/time.h | 20 +-
test/util.cpp | 302 ++++++-----
test/util.h | 40 +-
unittest/JpegStreamWriterTest.cpp | 29 +
unittest/jpegmarkersegmenttest.cpp | 47 ++
unittest/stdafx.cpp | 8 +
unittest/stdafx.h | 13 +
unittest/targetver.h | 8 +
66 files changed, 4026 insertions(+), 4153 deletions(-)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..871b1b2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,24 @@
+# GIT ignore file for CharLS
+
+obj/
+bin/
+Win32/
+x64/
+[Dd]ebug/
+[Rr]elease/
+[Cc]hecked/
+
+# Ignore files created by Visual Studio
+*.suo
+*.user
+*.ipch
+*.opensdf
+*.sdf
+*.opendb
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..98f7040
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,28 @@
+language: cpp
+
+compiler:
+ - gcc
+ - clang
+
+install:
+- if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi
+- if [ "$CXX" = "clang++" ]; then export CXX="clang++-3.7" CC="clang-3.7"; fi
+
+addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-precise-3.7
+ packages:
+ - gcc-4.8
+ - g++-4.8
+ - clang-3.7
+
+sudo: false
+
+before_script:
+ - mkdir debug
+ - cd debug
+ - cmake -DCMAKE_BUILD_TYPE=Debug ..
+
+script: make
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8304f0d..b11ff66 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,23 +1,61 @@
-project(charls)
cmake_minimum_required(VERSION 2.6)
+project(charls)
-
-# When user specify build type do not override settings:
-IF(NOT CMAKE_BUILD_TYPE)
# The following compiler option are only meant for GCC:
-IF(CMAKE_COMPILER_IS_GNUCC)
-# the following is optimization micrmanagement that made better code for x86
-# SET(CMAKE_CXX_FLAGS "-D NDEBUG -O3 -Wall -Wextra -pedantic -fvisibility=hidden -fomit-frame-pointer -momit-leaf-frame-pointer -fweb -ftracer" )
-SET(CMAKE_CXX_FLAGS "-D NDEBUG -O3" )
-ENDIF(CMAKE_COMPILER_IS_GNUCC)
-ENDIF(NOT CMAKE_BUILD_TYPE)
+if (CMAKE_COMPILER_IS_GNUCC)
+ # the following is optimization micromanagement that made better code for x86
+ # SET(CMAKE_CXX_FLAGS "-D NDEBUG -O3 -Wall -Wextra -pedantic -fvisibility=hidden -fomit-frame-pointer -momit-leaf-frame-pointer -fweb -ftracer" )
+
+ # Define GNU C++ defines for both Debug and Release
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++03 -Wall -Wextra")
+
+ # Define specific Debug settings.
+ set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g")
+
+ # Define specific Release settings.
+ set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -D NDEBUG -O3")
+ENDIF ()
+
+if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+ # Define clang C++ defines for both Debug and Release
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++03 -Wall -Wextra")
+
+ # Define specific Debug settings.
+ set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g")
+
+ # Define specific Release settings.
+ set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -D NDEBUG -O3")
+endif()
+
+option (BUILD_SHARED_LIBS "Build CharLS with shared libraries." OFF)
+option (BUILD_TESTING "Build tests" ON)
-OPTION(charls_BUILD_SHARED_LIBS "Build CharLS with shared libraries." OFF)
-SET(BUILD_SHARED_LIBS ${charls_BUILD_SHARED_LIBS})
+if (WIN32)
+ if (BUILD_SHARED_LIBS)
+ add_definitions(-D CHARLS_DLL)
+ else()
+ add_definitions(-D CHARLS_STATIC)
+ endif()
+endif()
-add_library(CharLS header.cpp interface.cpp jpegls.cpp )
+set (charls_HEADERS
+src/context.h src/defaulttraits.h src/jpegimagedatasegment.h src/jpegsegment.h src/lookuptable.h src/publictypes.h
+src/colortransform.h src/contextrunmode.h src/encoderstrategy.h src/jpegmarker.h src/losslesstraits.h src/scan.h
+src/config.h src/decoderstrategy.h src/header.h src/jpegmarkersegment.h src/jpegstreamwriter.h src/processline.h src/util.h)
+add_library(CharLS src/interface.cpp src/jpegls.cpp src/jpegmarkersegment.cpp src/header.cpp src/jpegstreamwriter.cpp)
+set (CHARLS_LIB_MAJOR_VERSION 1)
+set (CHARLS_LIB_MINOR_VERSION 0)
+set_target_properties( CharLS PROPERTIES
+ VERSION ${CHARLS_LIB_MAJOR_VERSION}.${CHARLS_LIB_MINOR_VERSION}
+ SOVERSION ${CHARLS_LIB_MAJOR_VERSION})
-add_executable(charlstest test/main.cpp test/time.cpp test/util.cpp test/bitstreamdamage.cpp test/compliance.cpp test/performance.cpp test/dicomsamples.cpp)
-target_link_libraries (charlstest CharLS)
+install (TARGETS CharLS RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib${LIB_SUFFIX}
+ ARCHIVE DESTINATION lib${LIB_SUFFIX})
+install (FILES ${charls_HEADERS} DESTINATION include/CharLS)
+if (BUILD_TESTING)
+ add_executable(charlstest test/main.cpp test/time.cpp test/util.cpp test/bitstreamdamage.cpp test/compliance.cpp test/performance.cpp test/dicomsamples.cpp)
+ target_link_libraries (charlstest CharLS)
+endif ()
\ No newline at end of file
diff --git a/CharLS.sln b/CharLS.sln
deleted file mode 100644
index 588a61a..0000000
--- a/CharLS.sln
+++ /dev/null
@@ -1,49 +0,0 @@
-Microsoft Visual Studio Solution File, Format Version 10.00
-# Visual Studio 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
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "plainc", "plainc\plainc.vcproj", "{1FB6C79F-9A01-41A4-9278-F666DEF6D4C6}"
- ProjectSection(ProjectDependencies) = postProject
- {524BE26D-FC60-4BC4-9100-128A0502FFF7} = {524BE26D-FC60-4BC4-9100-128A0502FFF7}
- EndProjectSection
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Win32 = Debug|Win32
- Debug|x64 = Debug|x64
- Release|Win32 = Release|Win32
- Release|x64 = Release|x64
- 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}.Debug|x64.ActiveCfg = Debug|x64
- {524BE26D-FC60-4BC4-9100-128A0502FFF7}.Debug|x64.Build.0 = Debug|x64
- {524BE26D-FC60-4BC4-9100-128A0502FFF7}.Release|Win32.ActiveCfg = Release|Win32
- {524BE26D-FC60-4BC4-9100-128A0502FFF7}.Release|Win32.Build.0 = Release|Win32
- {524BE26D-FC60-4BC4-9100-128A0502FFF7}.Release|x64.ActiveCfg = Release|x64
- {524BE26D-FC60-4BC4-9100-128A0502FFF7}.Release|x64.Build.0 = Release|x64
- {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}.Debug|x64.ActiveCfg = Debug|x64
- {3E349E7B-30C2-4791-81B7-1108014291B7}.Debug|x64.Build.0 = Debug|x64
- {3E349E7B-30C2-4791-81B7-1108014291B7}.Release|Win32.ActiveCfg = Release|Win32
- {3E349E7B-30C2-4791-81B7-1108014291B7}.Release|Win32.Build.0 = Release|Win32
- {3E349E7B-30C2-4791-81B7-1108014291B7}.Release|x64.ActiveCfg = Release|x64
- {3E349E7B-30C2-4791-81B7-1108014291B7}.Release|x64.Build.0 = Release|x64
- {1FB6C79F-9A01-41A4-9278-F666DEF6D4C6}.Debug|Win32.ActiveCfg = Debug|Win32
- {1FB6C79F-9A01-41A4-9278-F666DEF6D4C6}.Debug|Win32.Build.0 = Debug|Win32
- {1FB6C79F-9A01-41A4-9278-F666DEF6D4C6}.Debug|x64.ActiveCfg = Debug|Win32
- {1FB6C79F-9A01-41A4-9278-F666DEF6D4C6}.Release|Win32.ActiveCfg = Release|Win32
- {1FB6C79F-9A01-41A4-9278-F666DEF6D4C6}.Release|Win32.Build.0 = Release|Win32
- {1FB6C79F-9A01-41A4-9278-F666DEF6D4C6}.Release|x64.ActiveCfg = Release|Win32
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
diff --git a/CharLS.vcproj b/CharLS.vcproj
deleted file mode 100644
index b707bb6..0000000
--- a/CharLS.vcproj
+++ /dev/null
@@ -1,545 +0,0 @@
-<?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"
- />
- <Platform
- Name="x64"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="Debug"
- IntermediateDirectory="Debug"
- ConfigurationType="2"
- InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
- UseOfMFC="0"
- UseOfATL="0"
- 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;_WINDOWS;_USRDLL;JPEGLS_EXPORTS"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- SmallerTypeCheck="false"
- RuntimeLibrary="3"
- BufferSecurityCheck="true"
- DisableLanguageExtensions="true"
- 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"
- OutputFile="$(OutDir)/charls.dll"
- LinkIncremental="2"
- ModuleDefinitionFile="charls.def"
- GenerateDebugInformation="true"
- ProgramDatabaseFile="$(OutDir)/jpegls.pdb"
- SubSystem="1"
- OptimizeForWindows98="0"
- RandomizedBaseAddress="1"
- DataExecutionPrevention="0"
- ImportLibrary="$(OutDir)/CharLS.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="0"
- CharacterSet="2"
- WholeProgramOptimization="1"
- >
- <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="true"
- EnableFunctionLevelLinking="false"
- EnableEnhancedInstructionSet="0"
- DisableLanguageExtensions="true"
- ForceConformanceInForLoopScope="true"
- RuntimeTypeInfo="true"
- UsePrecompiledHeader="0"
- WarningLevel="4"
- Detect64BitPortabilityProblems="false"
- DebugInformationFormat="3"
- CallingConvention="0"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- OutputFile="$(OutDir)/charls.dll"
- LinkIncremental="1"
- ModuleDefinitionFile="charls.def"
- GenerateDebugInformation="true"
- SubSystem="2"
- OptimizeReferences="2"
- EnableCOMDATFolding="2"
- OptimizeForWindows98="0"
- RandomizedBaseAddress="1"
- DataExecutionPrevention="0"
- ImportLibrary="$(OutDir)/CharLS.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="Debug|x64"
- OutputDirectory="$(PlatformName)\$(ConfigurationName)"
- IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
- ConfigurationType="2"
- InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
- UseOfMFC="0"
- UseOfATL="0"
- CharacterSet="2"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- TargetEnvironment="3"
- />
- <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="true"
- 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"
- OutputFile="$(OutDir)/charls.dll"
- LinkIncremental="2"
- ModuleDefinitionFile="charls.def"
- GenerateDebugInformation="true"
- ProgramDatabaseFile="$(OutDir)/jpegls.pdb"
- SubSystem="2"
- OptimizeForWindows98="0"
- RandomizedBaseAddress="1"
- DataExecutionPrevention="0"
- ImportLibrary="$(OutDir)/CharLS.lib"
- TargetMachine="17"
- />
- <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|x64"
- OutputDirectory="$(PlatformName)\$(ConfigurationName)"
- IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
- ConfigurationType="2"
- InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
- UseOfMFC="0"
- UseOfATL="0"
- CharacterSet="2"
- WholeProgramOptimization="0"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- TargetEnvironment="3"
- />
- <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="true"
- ForceConformanceInForLoopScope="true"
- RuntimeTypeInfo="true"
- UsePrecompiledHeader="0"
- WarningLevel="4"
- Detect64BitPortabilityProblems="false"
- DebugInformationFormat="3"
- CallingConvention="0"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- OutputFile="$(OutDir)/charls.dll"
- LinkIncremental="1"
- ModuleDefinitionFile="charls.def"
- GenerateDebugInformation="true"
- SubSystem="2"
- OptimizeReferences="2"
- EnableCOMDATFolding="2"
- OptimizeForWindows98="0"
- RandomizedBaseAddress="1"
- DataExecutionPrevention="0"
- ImportLibrary="$(OutDir)/CharLS.lib"
- TargetMachine="17"
- />
- <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=".\charls.def"
- >
- </File>
- <File
- RelativePath="header.cpp"
- >
- </File>
- <File
- RelativePath=".\interface.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>
- <FileConfiguration
- Name="Debug|x64"
- >
- <Tool
- Name="VCCLCompilerTool"
- EnableIntrinsicFunctions="true"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|x64"
- >
- <Tool
- Name="VCCLCompilerTool"
- Optimization="3"
- EnableIntrinsicFunctions="true"
- FavorSizeOrSpeed="1"
- BasicRuntimeChecks="0"
- BufferSecurityCheck="false"
- EnableFunctionLevelLinking="false"
- />
- </FileConfiguration>
- </File>
- </Filter>
- <Filter
- Name="Header Files"
- Filter="h;hpp;hxx;hm;inl;inc"
- >
- <File
- RelativePath=".\colortransform.h"
- >
- </File>
- <File
- RelativePath=".\config.h"
- >
- </File>
- <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=".\interface.h"
- >
- </File>
- <File
- RelativePath="lookuptable.h"
- >
- </File>
- <File
- RelativePath=".\losslesstraits.h"
- >
- </File>
- <File
- RelativePath=".\processline.h"
- >
- </File>
- <File
- RelativePath=".\publictypes.h"
- >
- </File>
- <File
- RelativePath="scan.h"
- >
- </File>
- <File
- RelativePath=".\streams.h"
- >
- </File>
- <File
- RelativePath="util.h"
- >
- </File>
- </Filter>
- <File
- RelativePath=".\CMakeLists.txt"
- >
- </File>
- <File
- RelativePath=".\License.txt"
- >
- </File>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
diff --git a/CharLS_VS2015.sln b/CharLS_VS2015.sln
new file mode 100644
index 0000000..62410d5
--- /dev/null
+++ b/CharLS_VS2015.sln
@@ -0,0 +1,54 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.24720.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Native", "Native", "{1C1CF63C-A53A-449F-90D3-63321015FD65}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CharLS_VS2015", "src\CharLS_VS2015.vcxproj", "{FF506D97-CF63-4268-97B8-6195E13A0114}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CharLSTest_VS2015", "test\CharLSTest_VS2015.vcxproj", "{3E349E7B-30C2-4791-81B7-1108014291B7}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Checked|Win32 = Checked|Win32
+ Checked|x64 = Checked|x64
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {FF506D97-CF63-4268-97B8-6195E13A0114}.Checked|Win32.ActiveCfg = Checked|Win32
+ {FF506D97-CF63-4268-97B8-6195E13A0114}.Checked|Win32.Build.0 = Checked|Win32
+ {FF506D97-CF63-4268-97B8-6195E13A0114}.Checked|x64.ActiveCfg = Checked|x64
+ {FF506D97-CF63-4268-97B8-6195E13A0114}.Checked|x64.Build.0 = Checked|x64
+ {FF506D97-CF63-4268-97B8-6195E13A0114}.Debug|Win32.ActiveCfg = Debug|Win32
+ {FF506D97-CF63-4268-97B8-6195E13A0114}.Debug|Win32.Build.0 = Debug|Win32
+ {FF506D97-CF63-4268-97B8-6195E13A0114}.Debug|x64.ActiveCfg = Debug|x64
+ {FF506D97-CF63-4268-97B8-6195E13A0114}.Debug|x64.Build.0 = Debug|x64
+ {FF506D97-CF63-4268-97B8-6195E13A0114}.Release|Win32.ActiveCfg = Release|Win32
+ {FF506D97-CF63-4268-97B8-6195E13A0114}.Release|Win32.Build.0 = Release|Win32
+ {FF506D97-CF63-4268-97B8-6195E13A0114}.Release|x64.ActiveCfg = Release|x64
+ {FF506D97-CF63-4268-97B8-6195E13A0114}.Release|x64.Build.0 = Release|x64
+ {3E349E7B-30C2-4791-81B7-1108014291B7}.Checked|Win32.ActiveCfg = Checked|Win32
+ {3E349E7B-30C2-4791-81B7-1108014291B7}.Checked|Win32.Build.0 = Checked|Win32
+ {3E349E7B-30C2-4791-81B7-1108014291B7}.Checked|x64.ActiveCfg = Checked|x64
+ {3E349E7B-30C2-4791-81B7-1108014291B7}.Checked|x64.Build.0 = Checked|x64
+ {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}.Debug|x64.ActiveCfg = Debug|x64
+ {3E349E7B-30C2-4791-81B7-1108014291B7}.Debug|x64.Build.0 = Debug|x64
+ {3E349E7B-30C2-4791-81B7-1108014291B7}.Release|Win32.ActiveCfg = Release|Win32
+ {3E349E7B-30C2-4791-81B7-1108014291B7}.Release|Win32.Build.0 = Release|Win32
+ {3E349E7B-30C2-4791-81B7-1108014291B7}.Release|x64.ActiveCfg = Release|x64
+ {3E349E7B-30C2-4791-81B7-1108014291B7}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {FF506D97-CF63-4268-97B8-6195E13A0114} = {1C1CF63C-A53A-449F-90D3-63321015FD65}
+ {3E349E7B-30C2-4791-81B7-1108014291B7} = {1C1CF63C-A53A-449F-90D3-63321015FD65}
+ EndGlobalSection
+EndGlobal
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..4ebb974
--- /dev/null
+++ b/README.md
@@ -0,0 +1,30 @@
+[![Build Status](https://travis-ci.org/team-charls/charls.svg?branch=1.x-master)](https://travis-ci.org/team-charls/charls)
+#CharLS, a JPEG-LS library
+
+##Project Description
+An optimized implementation of the JPEG-LS standard for lossless
+and near-lossless image compression. JPEG-LS is a low-complexity
+standard that matches JPEG 2000 compression ratios.
+In terms of speed, CharLS outperforms open source and
+commercial JPEG LS implementations.
+
+###Features
+* High performance C++ implementation with a C interface to ensure maximum interopability.
+* Supports Windows, Linux and Solaris in 32 bit and 64 bit.
+* Includes a wrapper class for .NET
+
+##About JPEG-LS
+JPEG-LS (ISO-14495-1/ITU-T.87) is a standard derived from the Hewlett Packard LOCO algorithm. JPEG LS has low complexity (meaning fast compression) and high compression ratios, similar to JPEG 2000. JPEG-LS is more similar to the old Lossless JPEG than to JPEG 2000, but interestingly the two different techniques result in vastly different performance characteristics.
+[Wikipedia on lossless JPEG and JPEG-LS](en.wikipedia.org/wiki/Lossless_JPEG)
+[Benchmarks JPEG-LS-Performance](charls.codeplex.com/wikipage?title=JPEG-LS-Performance&referringTitle=Home)
+
+##Building CHARLS
+
+###Primary development
+
+Primary development is done on Windows with Visual Studio 2015.
+Optimized projects and solution files are available for this environment.
+
+All other platforms are supported by cmake. CMake is a cross platform
+ open source build system that generate project\make files for a large
+set of environments.
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000..b74b500
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,14 @@
+version: 1.00.{build}
+os: Visual Studio 2015
+configuration:
+- Debug
+- Release
+- Checked
+platform:
+- Win32
+- x64
+before_build:
+- set PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH%
+build:
+ project: CharLS_VS2015.sln
+ verbosity: minimal
\ No newline at end of file
diff --git a/check.cmd b/check.cmd
new file mode 100644
index 0000000..16fd94f
--- /dev/null
+++ b/check.cmd
@@ -0,0 +1,3 @@
+# -I "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include"
+
+"C:\Program Files\Cppcheck\cppcheck.exe" --enable=all --inconclusive --platform=win32A -D_WIN32 -D_M_X64 -D_M_AMD64 -D__cplusplus -D_MSC_VER=1900 --verbose --report-progress src
\ No newline at end of file
diff --git a/decoderstrategy.h b/decoderstrategy.h
deleted file mode 100644
index 0481782..0000000
--- a/decoderstrategy.h
+++ /dev/null
@@ -1,285 +0,0 @@
-//
-// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
-//
-
-#ifndef CHARLS_DECODERSTATEGY
-#define CHARLS_DECODERSTATEGY
-
-#include "streams.h"
-#include "processline.h"
-#include "config.h"
-#include "util.h"
-
-// Implements encoding to stream of bits. In encoding mode JpegLsCodec inherits from EncoderStrategy
-
-
-
-class DecoderStrategy
-{
-public:
- DecoderStrategy(const JlsParameters& info) :
- _info(info),
- _processLine(0),
- _readCache(0),
- _validBits(0),
- _position(0)
- {
- }
-
- virtual ~DecoderStrategy()
- {
- }
-
- virtual void SetPresets(const JlsCustomParameters& presets) = 0;
- virtual size_t DecodeScan(void* outputData, const JlsRect& size, const void* compressedData, size_t byteCount, bool bCheck) = 0;
-
- void Init(BYTE* compressedBytes, size_t byteCount)
- {
- _validBits = 0;
- _readCache = 0;
- _position = compressedBytes;
- _endPosition = compressedBytes + byteCount;
- _nextFFPosition = FindNextFF();
- MakeValid();
- }
-
- inlinehint void Skip(LONG length)
- {
- _validBits -= length;
- _readCache = _readCache << length;
- }
-
-
- void OnLineBegin(LONG /*cpixel*/, void* /*ptypeBuffer*/, LONG /*pixelStride*/)
- {}
-
-
- void OnLineEnd(LONG pixelCount, const void* ptypeBuffer, LONG pixelStride)
- {
- _processLine->NewLineDecoded(ptypeBuffer, pixelCount, pixelStride);
- }
-
- void EndScan()
- {
- if ((*_position) != 0xFF)
- {
- ReadBit();
-
- if ((*_position) != 0xFF)
- throw JlsException(TooMuchCompressedData);
- }
-
- if (_readCache != 0)
- throw JlsException(TooMuchCompressedData);
- }
-
-
- inlinehint bool OptimizedRead()
- {
- // Easy & fast: if there is no 0xFF byte in sight, we can read without bitstuffing
- if (_position < _nextFFPosition - (sizeof(bufType)-1))
- {
- _readCache |= FromBigEndian<sizeof(bufType)>::Read(_position) >> _validBits;
- int bytesToRead = (bufferbits - _validBits) >> 3;
- _position += bytesToRead;
- _validBits += bytesToRead * 8;
- ASSERT(_validBits >= bufferbits - 8);
- return true;
- }
- return false;
- }
-
- typedef size_t bufType;
-
- enum {
- bufferbits = sizeof( bufType ) * 8
- };
-
- void MakeValid()
- {
- ASSERT(_validBits <=bufferbits - 8);
-
- if (OptimizedRead())
- return;
-
- do
- {
- if (_position >= _endPosition)
- {
- if (_validBits <= 0)
- throw JlsException(InvalidCompressedData);
-
- return;
- }
-
- bufType valnew = _position[0];
-
- if (valnew == 0xFF)
- {
- // JPEG bitstream rule: no FF may be followed by 0x80 or higher
- if (_position == _endPosition - 1 || (_position[1] & 0x80) != 0)
- {
- if (_validBits <= 0)
- throw JlsException(InvalidCompressedData);
-
- return;
- }
- }
-
- _readCache |= valnew << (bufferbits - 8 - _validBits);
- _position += 1;
- _validBits += 8;
-
- if (valnew == 0xFF)
- {
- _validBits--;
- }
- }
- while (_validBits < bufferbits - 8);
-
- _nextFFPosition = FindNextFF();
- return;
-
- }
-
-
- BYTE* FindNextFF()
- {
- BYTE* pbyteNextFF = _position;
-
- while (pbyteNextFF < _endPosition)
- {
- if (*pbyteNextFF == 0xFF)
- {
- break;
- }
- pbyteNextFF++;
- }
-
-
- return pbyteNextFF;
- }
-
-
- BYTE* GetCurBytePos() const
- {
- LONG validBits = _validBits;
- BYTE* compressedBytes = _position;
-
- for (;;)
- {
- LONG cbitLast = compressedBytes[-1] == 0xFF ? 7 : 8;
-
- if (validBits < cbitLast )
- return compressedBytes;
-
- validBits -= cbitLast;
- compressedBytes--;
- }
- }
-
-
- inlinehint LONG ReadValue(LONG length)
- {
- if (_validBits < length)
- {
- MakeValid();
- if (_validBits < length)
- throw JlsException(InvalidCompressedData);
- }
-
- ASSERT(length != 0 && length <= _validBits);
- ASSERT(length < 32);
- LONG result = LONG(_readCache >> (bufferbits - length));
- Skip(length);
- return result;
- }
-
-
- inlinehint LONG PeekByte()
- {
- if (_validBits < 8)
- {
- MakeValid();
- }
-
- return _readCache >> (bufferbits - 8);
- }
-
-
-
- inlinehint bool ReadBit()
- {
- if (_validBits <= 0)
- {
- MakeValid();
- }
-
- bool bSet = (_readCache & (bufType(1) << (bufferbits - 1))) != 0;
- Skip(1);
- return bSet;
- }
-
-
-
- inlinehint LONG Peek0Bits()
- {
- if (_validBits < 16)
- {
- MakeValid();
- }
- bufType valTest = _readCache;
-
- for (LONG count = 0; count < 16; count++)
- {
- if ((valTest & (bufType(1) << (bufferbits - 1))) != 0)
- return count;
-
- valTest <<= 1;
- }
- return -1;
- }
-
-
-
- inlinehint LONG ReadHighbits()
- {
- LONG count = Peek0Bits();
- if (count >= 0)
- {
- Skip(count + 1);
- return count;
- }
- Skip(15);
-
- for (LONG highbits = 15; ; highbits++)
- {
- if (ReadBit())
- return highbits;
- }
- }
-
-
- LONG ReadLongValue(LONG length)
- {
- if (length <= 24)
- return ReadValue(length);
-
- return (ReadValue(length - 24) << 24) + ReadValue(24);
- }
-
-protected:
- JlsParameters _info;
- std::auto_ptr<ProcessLine> _processLine;
-
-private:
- // decoding
- bufType _readCache;
- LONG _validBits;
- BYTE* _position;
- BYTE* _nextFFPosition;
- BYTE* _endPosition;
-};
-
-
-#endif
diff --git a/header.cpp b/header.cpp
deleted file mode 100644
index b8c1642..0000000
--- a/header.cpp
+++ /dev/null
@@ -1,627 +0,0 @@
-//
-// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
-//
-
-#include "config.h"
-#include "util.h"
-#include "header.h"
-#include "streams.h"
-#include "decoderstrategy.h"
-#include "encoderstrategy.h"
-#include <memory>
-
-
-// JFIF\0
-BYTE jfifID[] = {'J','F','I','F','\0'};
-
-
-bool IsDefault(const JlsCustomParameters* pcustom)
-{
- if (pcustom->MAXVAL != 0)
- return false;
-
- if (pcustom->T1 != 0)
- return false;
-
- if (pcustom->T2 != 0)
- return false;
-
- if (pcustom->T3 != 0)
- return false;
-
- if (pcustom->RESET != 0)
- return false;
-
- return true;
-}
-
-
-LONG CLAMP(LONG i, LONG j, LONG MAXVAL)
-{
- if (i > MAXVAL || i < j)
- return j;
-
- return i;
-}
-
-
-JlsCustomParameters ComputeDefault(LONG MAXVAL, LONG NEAR)
-{
- JlsCustomParameters preset = JlsCustomParameters();
-
- LONG FACTOR = (MIN(MAXVAL, 4095) + 128)/256;
-
- preset.T1 = CLAMP(FACTOR * (BASIC_T1 - 2) + 2 + 3*NEAR, NEAR + 1, MAXVAL);
- preset.T2 = CLAMP(FACTOR * (BASIC_T2 - 3) + 3 + 5*NEAR, preset.T1, MAXVAL);
- preset.T3 = CLAMP(FACTOR * (BASIC_T3 - 4) + 4 + 7*NEAR, preset.T2, MAXVAL);
- preset.MAXVAL = MAXVAL;
- preset.RESET = BASIC_RESET;
- return preset;
-}
-
-
-JLS_ERROR CheckParameterCoherent(const JlsParameters* pparams)
-{
- if (pparams->bitspersample < 6 || pparams->bitspersample > 16)
- return ParameterValueNotSupported;
-
- if (pparams->ilv < 0 || pparams->ilv > 2)
- throw JlsException(InvalidCompressedData);
-
- if (pparams->bitspersample < 6 || pparams->bitspersample > 16)
- return ParameterValueNotSupported;
-
- switch (pparams->components)
- {
- case 4: return pparams->ilv == ILV_SAMPLE ? ParameterValueNotSupported : OK;
- case 3: return OK;
- case 1: return pparams->ilv != ILV_NONE ? ParameterValueNotSupported : OK;
- case 0: return InvalidJlsParameters;
-
- default: return pparams->ilv != ILV_NONE ? ParameterValueNotSupported : OK;
- }
-}
-
-//
-// JpegMarkerSegment
-//
-class JpegMarkerSegment : public JpegSegment
-{
-public:
- JpegMarkerSegment(BYTE marker, std::vector<BYTE> vecbyte)
- {
- _marker = marker;
- std::swap(_vecbyte, vecbyte);
- }
-
- virtual void Write(JLSOutputStream* pstream)
- {
- pstream->WriteByte(0xFF);
- pstream->WriteByte(_marker);
- pstream->WriteWord(USHORT(_vecbyte.size() + 2));
- pstream->WriteBytes(_vecbyte);
- }
-
- BYTE _marker;
- std::vector<BYTE> _vecbyte;
-};
-
-
-//
-// push_back()
-//
-void push_back(std::vector<BYTE>& vec, USHORT value)
-{
- vec.push_back(BYTE(value / 0x100));
- vec.push_back(BYTE(value % 0x100));
-}
-
-
-//
-// CreateMarkerStartOfFrame()
-//
-JpegSegment* CreateMarkerStartOfFrame(Size size, LONG bitsPerSample, LONG ccomp)
-{
-
- std::vector<BYTE> vec;
- vec.push_back(static_cast<BYTE>(bitsPerSample));
- push_back(vec, static_cast<USHORT>(size.cy));
- push_back(vec, static_cast<USHORT>(size.cx));
-
- // components
- vec.push_back(static_cast<BYTE>(ccomp));
- for (BYTE component = 0; component < ccomp; component++)
- {
- // rescaling
- vec.push_back(component + 1);
- vec.push_back(0x11);
- //"Tq1" reserved, 0
- vec.push_back(0);
- }
-
- return new JpegMarkerSegment(JPEG_SOF, vec);
-}
-
-
-
-
-//
-// ctor()
-//
-JLSOutputStream::JLSOutputStream() :
- _bCompare(false),
- _pdata(NULL),
- _cbyteOffset(0),
- _cbyteLength(0),
- _icompLast(0)
-{
-}
-
-
-
-//
-// dtor()
-//
-JLSOutputStream::~JLSOutputStream()
-{
- for (size_t i = 0; i < _segments.size(); ++i)
- {
- delete _segments[i];
- }
- _segments.empty();
-}
-
-
-
-
-//
-// Init()
-//
-void JLSOutputStream::Init(Size size, LONG bitsPerSample, LONG ccomp)
-{
- _segments.push_back(CreateMarkerStartOfFrame(size, bitsPerSample, ccomp));
-}
-
-
-void JLSOutputStream::AddColorTransform(int i)
-{
- std::vector<BYTE> rgbyteXform;
- rgbyteXform.push_back('m');
- rgbyteXform.push_back('r');
- rgbyteXform.push_back('f');
- rgbyteXform.push_back('x');
- rgbyteXform.push_back((BYTE)i);
-
- _segments.push_back(new JpegMarkerSegment(JPEG_APP8, rgbyteXform));
-}
-
-
-//
-// Write()
-//
-size_t JLSOutputStream::Write(BYTE* pdata, size_t cbyteLength)
-{
- _pdata = pdata;
- _cbyteLength = cbyteLength;
-
- WriteByte(0xFF);
- WriteByte(JPEG_SOI);
-
- for (size_t i = 0; i < _segments.size(); ++i)
- {
- _segments[i]->Write(this);
- }
-
- //_bCompare = false;
-
- WriteByte(0xFF);
- WriteByte(JPEG_EOI);
-
- return _cbyteOffset;
-}
-
-
-
-JLSInputStream::JLSInputStream(const BYTE* pdata, size_t cbyteLength) :
- _pdata(pdata),
- _cbyteOffset(0),
- _cbyteLength(cbyteLength),
- _bCompare(false),
- _info(),
- _rect()
-{
-}
-
-//
-// Read()
-//
-void JLSInputStream::Read(void* pvoid, size_t cbyteAvailable)
-{
- ReadHeader();
-
- JLS_ERROR error = CheckParameterCoherent(&_info);
- if (error != OK)
- throw JlsException(error);
-
- ReadPixels(pvoid, cbyteAvailable);
-}
-
-
-
-
-
-//
-// ReadPixels()
-//
-void JLSInputStream::ReadPixels(void* pvoid, size_t cbyteAvailable)
-{
-
- if (_rect.Width <= 0)
- {
- _rect.Width = _info.width;
- _rect.Height = _info.height;
- }
-
- int64_t cbytePlane = (int64_t)(_rect.Width) * _rect.Height * ((_info.bitspersample + 7)/8);
-
- if (int64_t(cbyteAvailable) < cbytePlane * _info.components)
- throw JlsException(UncompressedBufferTooSmall);
-
- int scancount = _info.ilv == ILV_NONE ? _info.components : 1;
-
- BYTE* pbyte = (BYTE*)pvoid;
- for (LONG scan = 0; scan < scancount; ++scan)
- {
- ReadScan(pbyte);
- pbyte += cbytePlane;
- }
-}
-
-// ReadNBytes()
-//
-void JLSInputStream::ReadNBytes(std::vector<char>& dst, int byteCount)
-{
- for (int i = 0; i < byteCount; ++i)
- {
- dst.push_back((char)ReadByte());
- }
-}
-
-
-//
-// ReadHeader()
-//
-void JLSInputStream::ReadHeader()
-{
- if (ReadByte() != 0xFF)
- throw JlsException(InvalidCompressedData);
-
- if (ReadByte() != JPEG_SOI)
- throw JlsException(InvalidCompressedData);
-
- for (;;)
- {
- if (ReadByte() != 0xFF)
- throw JlsException(InvalidCompressedData);
-
- BYTE marker = (BYTE)ReadByte();
-
- size_t cbyteStart = _cbyteOffset;
- LONG cbyteMarker = ReadWord();
-
- switch (marker)
- {
- case JPEG_SOS: ReadStartOfScan(); break;
- case JPEG_SOF: ReadStartOfFrame(); break;
- case JPEG_COM: ReadComment(); break;
- case JPEG_LSE: ReadPresetParameters(); break;
- case JPEG_APP0: ReadJfif(); break;
- case JPEG_APP7: ReadColorSpace(); break;
- case JPEG_APP8: ReadColorXForm(); break;
- // Other tags not supported (among which DNL DRI)
- default: throw JlsException(ImageTypeNotSupported);
- }
-
- if (marker == JPEG_SOS)
- {
- _cbyteOffset = cbyteStart - 2;
- return;
- }
- _cbyteOffset = cbyteStart + cbyteMarker;
- }
-}
-
-
-JpegMarkerSegment* EncodeStartOfScan(const JlsParameters* pparams, LONG icomponent)
-{
- BYTE itable = 0;
-
- std::vector<BYTE> rgbyte;
-
- if (icomponent < 0)
- {
- rgbyte.push_back((BYTE)pparams->components);
- for (LONG icomponent = 0; icomponent < pparams->components; ++icomponent )
- {
- rgbyte.push_back(BYTE(icomponent + 1));
- rgbyte.push_back(itable);
- }
- }
- else
- {
- rgbyte.push_back(1);
- rgbyte.push_back((BYTE)icomponent);
- rgbyte.push_back(itable);
- }
-
- rgbyte.push_back(BYTE(pparams->allowedlossyerror));
- rgbyte.push_back(BYTE(pparams->ilv));
- rgbyte.push_back(0); // transform
-
- return new JpegMarkerSegment(JPEG_SOS, rgbyte);
-}
-
-
-
-JpegMarkerSegment* CreateLSE(const JlsCustomParameters* pcustom)
-{
- std::vector<BYTE> rgbyte;
-
- rgbyte.push_back(1);
- push_back(rgbyte, (USHORT)pcustom->MAXVAL);
- push_back(rgbyte, (USHORT)pcustom->T1);
- push_back(rgbyte, (USHORT)pcustom->T2);
- push_back(rgbyte, (USHORT)pcustom->T3);
- push_back(rgbyte, (USHORT)pcustom->RESET);
-
- return new JpegMarkerSegment(JPEG_LSE, rgbyte);
-}
-
-//
-// ReadPresetParameters()
-//
-void JLSInputStream::ReadPresetParameters()
-{
- LONG type = ReadByte();
-
-
- switch (type)
- {
- case 1:
- {
- _info.custom.MAXVAL = ReadWord();
- _info.custom.T1 = ReadWord();
- _info.custom.T2 = ReadWord();
- _info.custom.T3 = ReadWord();
- _info.custom.RESET = ReadWord();
- return;
- }
- }
-
-
-}
-
-
-//
-// ReadStartOfScan()
-//
-void JLSInputStream::ReadStartOfScan()
-{
- LONG ccomp = ReadByte();
- for (LONG i = 0; i < ccomp; ++i)
- {
- ReadByte();
- ReadByte();
- }
- _info.allowedlossyerror = ReadByte();
- _info.ilv = interleavemode(ReadByte());
-
- if(_info.bytesperline == 0)
- {
- int width = _rect.Width != 0 ? _rect.Width : _info.width;
- int components = _info.ilv == ILV_NONE ? 1 : _info.components;
- _info.bytesperline = components * width * ((_info.bitspersample + 7)/8);
- }
-}
-
-
-//
-// ReadComment()
-//
-void JLSInputStream::ReadComment()
-{}
-
-
-//
-// ReadJfif()
-//
-void JLSInputStream::ReadJfif()
-{
- for(int i = 0; i < (int)sizeof(jfifID); i++)
- {
- if(jfifID[i] != ReadByte())
- return;
- }
- _info.jfif.Ver = ReadWord();
-
- // DPI or DPcm
- _info.jfif.units = ReadByte();
- _info.jfif.XDensity = ReadWord();
- _info.jfif.YDensity = ReadWord();
-
- // thumbnail
- _info.jfif.Xthumb = ReadByte();
- _info.jfif.Ythumb = ReadByte();
- if(_info.jfif.Xthumb > 0 && _info.jfif.pdataThumbnail)
- {
- std::vector<char> tempbuff((char*)_info.jfif.pdataThumbnail, (char*)_info.jfif.pdataThumbnail+3*_info.jfif.Xthumb*_info.jfif.Ythumb);
- ReadNBytes(tempbuff, 3*_info.jfif.Xthumb*_info.jfif.Ythumb);
- }
-}
-
-//
-// CreateJFIF()
-//
-JpegMarkerSegment* CreateJFIF(const JfifParameters* jfif)
-{
- std::vector<BYTE> rgbyte;
- for(int i = 0; i < (int)sizeof(jfifID); i++)
- {
- rgbyte.push_back(jfifID[i]);
- }
-
- push_back(rgbyte, (USHORT)jfif->Ver);
-
- rgbyte.push_back(jfif->units);
- push_back(rgbyte, (USHORT)jfif->XDensity);
- push_back(rgbyte, (USHORT)jfif->YDensity);
-
- // thumbnail
- rgbyte.push_back((BYTE)jfif->Xthumb);
- rgbyte.push_back((BYTE)jfif->Ythumb);
- if(jfif->Xthumb > 0)
- {
- if(jfif->pdataThumbnail)
- throw JlsException(InvalidJlsParameters);
-
- rgbyte.insert(rgbyte.end(), (BYTE*)jfif->pdataThumbnail, (BYTE*)jfif->pdataThumbnail+3*jfif->Xthumb*jfif->Ythumb
- );
- }
-
- return new JpegMarkerSegment(JPEG_APP0, rgbyte);
-}
-
-
-//
-// ReadStartOfFrame()
-//
-void JLSInputStream::ReadStartOfFrame()
-{
- _info.bitspersample = ReadByte();
- int cline = ReadWord();
- int ccol = ReadWord();
- _info.width = ccol;
- _info.height = cline;
- _info.components= ReadByte();
-}
-
-
-//
-// ReadByte()
-//
-BYTE JLSInputStream::ReadByte()
-{
- if (_cbyteOffset >= _cbyteLength)
- throw JlsException(InvalidCompressedData);
-
- 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, _info.custom);
-
- _cbyteOffset += qcodec->DecodeScan(pvout, _rect, _pdata + _cbyteOffset, _cbyteLength - _cbyteOffset, _bCompare);
-}
-
-
-class JpegImageDataSegment: public JpegSegment
-{
-public:
- JpegImageDataSegment(const void* pvoidRaw, const JlsParameters& info, LONG icompStart, int ccompScan) :
- _ccompScan(ccompScan),
- _icompStart(icompStart),
- _pvoidRaw(pvoidRaw),
- _info(info)
- {
- }
-
- void Write(JLSOutputStream* pstream)
- {
- JlsParameters info = _info;
- info.components = _ccompScan;
- std::auto_ptr<EncoderStrategy> qcodec =JlsCodecFactory<EncoderStrategy>().GetCodec(info, _info.custom);
- size_t cbyteWritten = qcodec->EncodeScan((BYTE*)_pvoidRaw, pstream->GetPos(), pstream->GetLength(), pstream->_bCompare ? pstream->GetPos() : NULL);
- pstream->Seek(cbyteWritten);
- }
-
-
- int _ccompScan;
- LONG _icompStart;
- const void* _pvoidRaw;
- JlsParameters _info;
-};
-
-
-void JLSOutputStream::AddScan(const void* compareData, const JlsParameters* pparams)
-{
- if (pparams->jfif.Ver)
- {
- _segments.push_back(CreateJFIF(&pparams->jfif));
- }
- if (!IsDefault(&pparams->custom))
- {
- _segments.push_back(CreateLSE(&pparams->custom));
- }
- else if (pparams->bitspersample > 12)
- {
- JlsCustomParameters preset = ComputeDefault((1 << pparams->bitspersample) - 1, pparams->allowedlossyerror);
- _segments.push_back(CreateLSE(&preset));
- }
-
- _icompLast += 1;
- _segments.push_back(EncodeStartOfScan(pparams,pparams->ilv == ILV_NONE ? _icompLast : -1));
-
- Size size = Size(pparams->width, pparams->height);
- int ccomp = pparams->ilv == ILV_NONE ? 1 : pparams->components;
- _segments.push_back(new JpegImageDataSegment(compareData, *pparams, _icompLast, ccomp));
-}
-
-
-//
-// ReadColorSpace()
-//
-void JLSInputStream::ReadColorSpace()
-{}
-
-
-
-//
-// ReadColorXForm()
-//
-void JLSInputStream::ReadColorXForm()
-{
- std::vector<char> sourceTag;
- ReadNBytes(sourceTag, 4);
-
- if(strncmp(&sourceTag[0],"mrfx", 4) != 0)
- return;
-
- int xform = ReadByte();
- switch(xform)
- {
- case COLORXFORM_NONE:
- case COLORXFORM_HP1:
- case COLORXFORM_HP2:
- case COLORXFORM_HP3:
- _info.colorTransform = xform;
- return;
- case COLORXFORM_RGB_AS_YUV_LOSSY:
- case COLORXFORM_MATRIX:
- throw JlsException(ImageTypeNotSupported);
- default:
- throw JlsException(InvalidCompressedData);
- }
-}
-
diff --git a/header.h b/header.h
deleted file mode 100644
index 034325c..0000000
--- a/header.h
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
-//
-
-
-#ifndef CHARLS_HEADER
-#define CHARLS_HEADER
-
-#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
-#define JPEG_APP0 0xE0 // JFIF
-#define JPEG_APP7 0xE7 // colorspace
-#define JPEG_APP8 0xE8 // colorXForm
-
-
-
-// Default bin sizes for JPEG-LS statistical modeling. Can be overriden at compression time, however this is rarely done.
-const int BASIC_T1 = 3;
-const int BASIC_T2 = 7;
-const int BASIC_T3 = 21;
-
-const LONG BASIC_RESET = 64;
-
-class JLSOutputStream;
-
-
-template<class STRATEGY>
-class JlsCodecFactory
-{
-public:
- std::auto_ptr<STRATEGY> GetCodec(const JlsParameters& info, const JlsCustomParameters&);
-private:
- STRATEGY* GetCodecImpl(const JlsParameters& info);
-};
-
-JLS_ERROR CheckParameterCoherent(const JlsParameters* pparams);
-
-JlsCustomParameters ComputeDefault(LONG MAXVAL, LONG NEAR);
-
-//
-// JpegSegment
-//
-class JpegSegment
-{
-protected:
- JpegSegment() {}
-public:
- virtual ~JpegSegment() {}
- virtual void Write(JLSOutputStream* pstream) = 0;
-};
-
-#endif
diff --git a/interface.cpp b/interface.cpp
deleted file mode 100644
index 2ee050b..0000000
--- a/interface.cpp
+++ /dev/null
@@ -1,206 +0,0 @@
-//
-// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
-//
-
-
-//implement correct linkage for win32 dlls
-#if defined(_WIN32)
-#define CHARLS_IMEXPORT(returntype) __declspec(dllexport) returntype __stdcall
-#endif
-
-#include "config.h"
-#include "util.h"
-#include "interface.h"
-#include "header.h"
-
-
-JLS_ERROR CheckInput(const void* compressedData, size_t compressedLength, const void* uncompressedData, size_t uncompressedLength, const JlsParameters* pparams)
-{
- if (pparams == NULL)
- return InvalidJlsParameters;
-
- if (compressedLength == 0)
- return InvalidJlsParameters;
-
- if (compressedData == NULL)
- return InvalidJlsParameters;
-
- if (uncompressedData == NULL)
- return InvalidJlsParameters;
-
- if (pparams->width < 1 || pparams->width > 65535)
- return ParameterValueNotSupported;
-
- if (pparams->height < 1 || pparams->height > 65535)
- return ParameterValueNotSupported;
-
- int bytesperline = pparams->bytesperline < 0 ? -pparams->bytesperline : pparams->bytesperline;
-
- if (uncompressedLength < size_t(bytesperline * pparams->height))
- return InvalidJlsParameters;
-
- return CheckParameterCoherent(pparams);
-}
-
-
-
-extern "C"
-{
-
-CHARLS_IMEXPORT(JLS_ERROR) JpegLsEncode(void* compressedData, size_t compressedLength, size_t* pcbyteWritten, const void* uncompressedData, size_t uncompressedLength, struct JlsParameters* pparams)
-{
- JlsParameters info = *pparams;
- if(info.bytesperline == 0)
- {
- info.bytesperline = info.width * ((info.bitspersample + 7)/8);
- if (info.ilv != ILV_NONE)
- {
- info.bytesperline *= info.components;
- }
- }
-
- JLS_ERROR parameterError = CheckInput(compressedData, compressedLength, uncompressedData, uncompressedLength, &info);
-
- if (parameterError != OK)
- return parameterError;
-
- if (pcbyteWritten == NULL)
- return InvalidJlsParameters;
-
- Size size = Size(info.width, info.height);
- JLSOutputStream stream;
-
- stream.Init(size, info.bitspersample, info.components);
-
- if (info.colorTransform != 0)
- {
- stream.AddColorTransform(info.colorTransform);
- }
-
- if (info.ilv == ILV_NONE)
- {
- LONG cbyteComp = size.cx*size.cy*((info.bitspersample +7)/8);
- for (LONG component = 0; component < info.components; ++component)
- {
- const BYTE* compareData = static_cast<const BYTE*>(uncompressedData) + component*cbyteComp;
- stream.AddScan(compareData, &info);
- }
- }
- else
- {
- stream.AddScan(uncompressedData, &info);
- }
-
-
- stream.Write((BYTE*)compressedData, compressedLength);
-
- *pcbyteWritten = stream.GetBytesWritten();
- return OK;
-}
-
-CHARLS_IMEXPORT(JLS_ERROR) JpegLsDecode(void* uncompressedData, size_t uncompressedLength, const void* compressedData, size_t compressedLength, JlsParameters* info)
-{
- JLSInputStream reader((BYTE*)compressedData, compressedLength);
-
- if(info != NULL)
- {
- reader.SetInfo(info);
- }
-
- try
- {
- reader.Read(uncompressedData, uncompressedLength);
- return OK;
- }
- catch (JlsException& e)
- {
- return e._error;
- }
-}
-
-
-CHARLS_IMEXPORT(JLS_ERROR) JpegLsDecodeRect(void* uncompressedData, size_t uncompressedLength, const void* compressedData, size_t compressedLength, JlsRect roi, JlsParameters* info)
-{
- JLSInputStream reader((BYTE*)compressedData, compressedLength);
-
- if(info != NULL)
- {
- reader.SetInfo(info);
- }
-
- reader.SetRect(roi);
-
- try
- {
- reader.Read(uncompressedData, uncompressedLength);
- return OK;
- }
- catch (JlsException& e)
- {
- return e._error;
- }
-}
-
-
-CHARLS_IMEXPORT(JLS_ERROR) JpegLsVerifyEncode(const void* uncompressedData, size_t uncompressedLength, const void* compressedData, size_t compressedLength)
-{
- JlsParameters info = JlsParameters();
-
- JLS_ERROR error = JpegLsReadHeader(compressedData, compressedLength, &info);
- if (error != OK)
- return error;
-
- error = CheckInput(compressedData, compressedLength, uncompressedData, uncompressedLength, &info);
-
- if (error != OK)
- return error;
-
- Size size = Size(info.width, info.height);
-
- JLSOutputStream stream;
-
- stream.Init(size, info.bitspersample, info.components);
-
- if (info.ilv == ILV_NONE)
- {
- LONG cbyteComp = size.cx*size.cy*((info.bitspersample +7)/8);
- for (LONG component = 0; component < info.components; ++component)
- {
- const BYTE* compareData = static_cast<const BYTE*>(uncompressedData) + component*cbyteComp;
- stream.AddScan(compareData, &info);
- }
- }
- else
- {
- stream.AddScan(uncompressedData, &info);
- }
-
- std::vector<BYTE> rgbyteCompressed(compressedLength + 16);
-
- memcpy(&rgbyteCompressed[0], compressedData, compressedLength);
-
- stream.EnableCompare(true);
- stream.Write(&rgbyteCompressed[0], compressedLength);
-
- return OK;
-}
-
-
-CHARLS_IMEXPORT(JLS_ERROR) JpegLsReadHeader(const void* compressedData, size_t compressedLength, JlsParameters* pparams)
-{
- try
- {
- JLSInputStream reader((BYTE*)compressedData, compressedLength);
- reader.ReadHeader();
- JlsParameters info = reader.GetMetadata();
- *pparams = info;
- return OK;
- }
- catch (JlsException& e)
- {
- return e._error;
- }
-
-}
-
-}
diff --git a/interface.h b/interface.h
deleted file mode 100644
index 76e1161..0000000
--- a/interface.h
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
-//
-
-
-#ifndef JLS_INTERFACE
-#define JLS_INTERFACE
-
-#include "publictypes.h"
-
-#if defined(_WIN32)
-#ifndef CHARLS_IMEXPORT
-#define CHARLS_IMEXPORT(returntype) __declspec(dllimport) returntype __stdcall
-#endif
-#else
-#ifndef CHARLS_IMEXPORT
-#define CHARLS_IMEXPORT(returntype) returntype
-#endif
-#endif /* _WIN32 */
-
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
- CHARLS_IMEXPORT(enum JLS_ERROR) JpegLsEncode(void* compressedData, size_t compressedLength, size_t* pcbyteWritten,
- const void* uncompressedData, size_t uncompressedLength, struct JlsParameters* pparams);
-
- CHARLS_IMEXPORT(enum JLS_ERROR) JpegLsDecode(void* uncompressedData, size_t uncompressedLength,
- const void* compressedData, size_t compressedLength,
- struct JlsParameters* info);
-
-
- CHARLS_IMEXPORT(enum JLS_ERROR) JpegLsDecodeRect(void* uncompressedData, size_t uncompressedLength,
- const void* compressedData, size_t compressedLength,
- struct JlsRect rect, struct JlsParameters* info);
-
- CHARLS_IMEXPORT(enum JLS_ERROR) JpegLsReadHeader(const void* compressedData, size_t compressedLength,
- struct JlsParameters* pparams);
-
- CHARLS_IMEXPORT(enum JLS_ERROR) JpegLsVerifyEncode(const void* uncompressedData, size_t uncompressedLength,
- const void* compressedData, size_t compressedLength);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/plainc/plainc.c b/plainc/plainc.c
index a86b30c..4e9eb42 100644
--- a/plainc/plainc.c
+++ b/plainc/plainc.c
@@ -1,8 +1,13 @@
-#include <stdio.h>
-#include "../interface.h"
-
-void main()
-{
-
-
+
+
+#define CHARLS_STATIC 1
+
+#include <stdlib.h>
+
+#include "../interface.h"
+
+void main()
+{
+
+
}
\ No newline at end of file
diff --git a/plainc/plainc.vcproj b/plainc/plainc.vcproj
deleted file mode 100644
index 7c4de0b..0000000
--- a/plainc/plainc.vcproj
+++ /dev/null
@@ -1,186 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="9.00"
- Name="plainc"
- ProjectGUID="{1FB6C79F-9A01-41A4-9278-F666DEF6D4C6}"
- RootNamespace="plainc"
- Keyword="Win32Proj"
- TargetFrameworkVersion="196613"
- >
- <Platforms>
- <Platform
- Name="Win32"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="$(SolutionDir)$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)"
- ConfigurationType="1"
- CharacterSet="1"
- >
- <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="3"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- LinkIncremental="2"
- GenerateDebugInformation="true"
- SubSystem="1"
- 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="$(SolutionDir)$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)"
- ConfigurationType="1"
- CharacterSet="1"
- WholeProgramOptimization="1"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="2"
- EnableIntrinsicFunctions="true"
- PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
- RuntimeLibrary="2"
- EnableFunctionLevelLinking="true"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- DebugInformationFormat="3"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- LinkIncremental="1"
- GenerateDebugInformation="true"
- SubSystem="1"
- OptimizeReferences="2"
- EnableCOMDATFolding="2"
- 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>
- <File
- RelativePath=".\plainc.c"
- >
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- DisableLanguageExtensions="true"
- ForceConformanceInForLoopScope="false"
- RuntimeTypeInfo="false"
- WarningLevel="4"
- />
- </FileConfiguration>
- </File>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
diff --git a/processline.h b/processline.h
deleted file mode 100644
index 91f5770..0000000
--- a/processline.h
+++ /dev/null
@@ -1,225 +0,0 @@
-//
-// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
-//
-#ifndef CHARLS_PROCESSLINE
-#define CHARLS_PROCESSLINE
-
-#include "colortransform.h"
-
-//
-// This file defines the ProcessLine base class, its derivitives and helper functions.
-// During coding/decoding, CharLS process one line at a time. The different Processline implementations
-// convert the uncompressed format to and from the internal format for encoding.
-// Conversions include color transforms, line interleaved vs sample interleaved, masking out unused bits,
-// accounting for line padding etc.
-// This mechanism could be used to encode/decode images as they are received.
-//
-
-class ProcessLine
-{
-public:
- virtual ~ProcessLine() {}
- virtual void NewLineDecoded(const void* pSrc, int pixelCount, int bytesperline) = 0;
- virtual void NewLineRequested(void* pSrc, int pixelCount, int bytesperline) = 0;
-};
-
-
-class PostProcesSingleComponent : public ProcessLine
-{
-public:
- PostProcesSingleComponent(void* pbyteOutput, const JlsParameters& info, int bytesPerPixel) :
- _pbyteOutput((BYTE*)pbyteOutput),
- _bytesPerPixel(bytesPerPixel),
- _bytesPerLine(info.bytesperline)
- {
- }
-
- void NewLineRequested(void* pDst, int pixelCount, int /*byteStride*/)
- {
- ::memcpy(pDst, _pbyteOutput, pixelCount * _bytesPerPixel);
- _pbyteOutput += _bytesPerLine;
- }
-
- void NewLineDecoded(const void* pSrc, int pixelCount, int /*byteStride*/)
- {
- ::memcpy(_pbyteOutput, pSrc, pixelCount * _bytesPerPixel);
- _pbyteOutput += _bytesPerLine;
- }
-
-private:
- BYTE* _pbyteOutput;
- int _bytesPerPixel;
- int _bytesPerLine;
-};
-
-
-template<class TRANSFORM, class SAMPLE>
-void TransformLineToQuad(const SAMPLE* ptypeInput, LONG pixelStrideIn, Quad<SAMPLE>* pbyteBuffer, LONG pixelStride, TRANSFORM& transform)
-{
- int cpixel = MIN(pixelStride, pixelStrideIn);
- Quad<SAMPLE>* ptypeBuffer = (Quad<SAMPLE>*)pbyteBuffer;
-
- for (int x = 0; x < cpixel; ++x)
- {
- Quad<SAMPLE> pixel(transform(ptypeInput[x], ptypeInput[x + pixelStrideIn], ptypeInput[x + 2*pixelStrideIn]),ptypeInput[x + 3*pixelStrideIn]) ;
-
- ptypeBuffer[x] = pixel;
- }
-}
-
-
-template<class TRANSFORM, class SAMPLE>
-void TransformQuadToLine(const Quad<SAMPLE>* pbyteInput, LONG pixelStrideIn, SAMPLE* ptypeBuffer, LONG pixelStride, TRANSFORM& transform)
-{
- int cpixel = MIN(pixelStride, pixelStrideIn);
- const Quad<SAMPLE>* ptypeBufferIn = (Quad<SAMPLE>*)pbyteInput;
-
- for (int x = 0; x < cpixel; ++x)
- {
- Quad<SAMPLE> color = ptypeBufferIn[x];
- Quad<SAMPLE> colorTranformed(transform(color.v1, color.v2, color.v3), color.v4);
-
- ptypeBuffer[x] = colorTranformed.v1;
- ptypeBuffer[x + pixelStride] = colorTranformed.v2;
- ptypeBuffer[x + 2 *pixelStride] = colorTranformed.v3;
- ptypeBuffer[x + 3 *pixelStride] = colorTranformed.v4;
- }
-}
-
-
-template<class SAMPLE>
-void TransformRgbToBgr(SAMPLE* pDest, int samplesPerPixel, int pixelCount)
-{
- for (int i = 0; i < pixelCount; ++i)
- {
- std::swap(pDest[0], pDest[2]);
- pDest += samplesPerPixel;
- }
-}
-
-
-template<class TRANSFORM, class SAMPLE>
-void TransformLine(Triplet<SAMPLE>* pDest, const Triplet<SAMPLE>* pSrc, int pixelCount, TRANSFORM& transform)
-{
- for (int i = 0; i < pixelCount; ++i)
- {
- pDest[i] = transform(pSrc[i].v1, pSrc[i].v2, pSrc[i].v3);
- }
-}
-
-
-template<class TRANSFORM, class SAMPLE>
-void TransformLineToTriplet(const SAMPLE* ptypeInput, LONG pixelStrideIn, Triplet<SAMPLE>* pbyteBuffer, LONG pixelStride, TRANSFORM& transform)
-{
- int cpixel = MIN(pixelStride, pixelStrideIn);
- Triplet<SAMPLE>* ptypeBuffer = (Triplet<SAMPLE>*)pbyteBuffer;
-
- for (int x = 0; x < cpixel; ++x)
- {
- ptypeBuffer[x] = transform(ptypeInput[x], ptypeInput[x + pixelStrideIn], ptypeInput[x + 2*pixelStrideIn]);
- }
-}
-
-
-template<class TRANSFORM, class SAMPLE>
-void TransformTripletToLine(const Triplet<SAMPLE>* pbyteInput, LONG pixelStrideIn, SAMPLE* ptypeBuffer, LONG pixelStride, TRANSFORM& transform)
-{
- int cpixel = MIN(pixelStride, pixelStrideIn);
- const Triplet<SAMPLE>* ptypeBufferIn = (Triplet<SAMPLE>*)pbyteInput;
-
- for (int x = 0; x < cpixel; ++x)
- {
- Triplet<SAMPLE> color = ptypeBufferIn[x];
- Triplet<SAMPLE> colorTranformed = transform(color.v1, color.v2, color.v3);
-
- ptypeBuffer[x] = colorTranformed.v1;
- ptypeBuffer[x + pixelStride] = colorTranformed.v2;
- ptypeBuffer[x + 2 *pixelStride] = colorTranformed.v3;
- }
-}
-
-
-template<class TRANSFORM>
-class ProcessTransformed : public ProcessLine
-{
- typedef typename TRANSFORM::SAMPLE SAMPLE;
-
- ProcessTransformed(const ProcessTransformed&) {}
-public:
- ProcessTransformed(void* pbyteOutput, const JlsParameters& info, TRANSFORM transform) :
- _pbyteOutput((BYTE*)pbyteOutput),
- _info(info),
- _templine(info.width * info.components),
- _transform(transform),
- _inverseTransform(transform)
- {
-// ASSERT(_info.components == sizeof(TRIPLET)/sizeof(TRIPLET::SAMPLE));
- }
-
-
- void NewLineRequested(void* pDst, int pixelCount, int stride)
- {
- SAMPLE* pLine = (SAMPLE*)_pbyteOutput;
- if (_info.outputBgr)
- {
- pLine = &_templine[0];
- memcpy(pLine, _pbyteOutput, sizeof(Triplet<SAMPLE>)*pixelCount);
- TransformRgbToBgr(pLine, _info.components, pixelCount);
- }
-
- if (_info.components == 3)
- {
- if (_info.ilv == ILV_SAMPLE)
- {
- TransformLine((Triplet<SAMPLE>*)pDst, (const Triplet<SAMPLE>*)pLine, pixelCount, _transform);
- }
- else
- {
- TransformTripletToLine((const Triplet<SAMPLE>*)pLine, pixelCount, (SAMPLE*)pDst, stride, _transform);
- }
- }
- else if (_info.components == 4 && _info.ilv == ILV_LINE)
- {
- TransformQuadToLine((const Quad<SAMPLE>*)pLine, pixelCount, (SAMPLE*)pDst, stride, _transform);
- }
- _pbyteOutput += _info.bytesperline;
- }
-
-
- void NewLineDecoded(const void* pSrc, int pixelCount, int byteStride)
- {
- if (_info.components == 3)
- {
- if (_info.ilv == ILV_SAMPLE)
- {
- TransformLine((Triplet<SAMPLE>*)_pbyteOutput, (const Triplet<SAMPLE>*)pSrc, pixelCount, _inverseTransform);
- }
- else
- {
- TransformLineToTriplet((const SAMPLE*)pSrc, byteStride, (Triplet<SAMPLE>*)_pbyteOutput, pixelCount, _inverseTransform);
- }
- }
- else if (_info.components == 4 && _info.ilv == ILV_LINE)
- {
- TransformLineToQuad((const SAMPLE*)pSrc, byteStride, (Quad<SAMPLE>*)_pbyteOutput, pixelCount, _inverseTransform);
- }
-
- if (_info.outputBgr)
- {
- TransformRgbToBgr(_pbyteOutput, _info.components, pixelCount);
- }
- _pbyteOutput += _info.bytesperline;
- }
-
-
-private:
- BYTE* _pbyteOutput;
- const JlsParameters& _info;
- std::vector<SAMPLE> _templine;
- TRANSFORM _transform;
- typename TRANSFORM::INVERSE _inverseTransform;
-};
-
-
-
-#endif
diff --git a/publictypes.h b/publictypes.h
deleted file mode 100644
index 612738c..0000000
--- a/publictypes.h
+++ /dev/null
@@ -1,76 +0,0 @@
-//
-// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
-//
-#ifndef CHARLS_PUBLICTYPES
-#define CHARLS_PUBLICTYPES
-
-#include "config.h"
-
-enum JLS_ERROR
-{
- OK = 0,
- InvalidJlsParameters,
- ParameterValueNotSupported,
- UncompressedBufferTooSmall,
- CompressedBufferTooSmall,
- InvalidCompressedData,
- TooMuchCompressedData,
- ImageTypeNotSupported,
- UnsupportedBitDepthForTransform,
- UnsupportedColorTransform
-};
-
-
-enum interleavemode
-{
- ILV_NONE = 0,
- ILV_LINE = 1,
- ILV_SAMPLE = 2
-};
-
-
-struct JlsCustomParameters
-{
- int MAXVAL;
- int T1;
- int T2;
- int T3;
- int RESET;
-};
-
-
-struct JlsRect
-{
- int X, Y;
- int Width, Height;
-};
-
-
-struct JfifParameters
-{
- int Ver;
- char units;
- int XDensity;
- int YDensity;
- short Xthumb;
- short Ythumb;
- void* pdataThumbnail; // user must set buffer which size is Xthumb*Ythumb*3(RGB) before JpegLsDecode()
-};
-
-
-struct JlsParameters
-{
- int width;
- int height;
- int bitspersample;
- int bytesperline; // for [source (at encoding)][decoded (at decoding)] pixel image in user buffer
- int components;
- int allowedlossyerror;
- enum interleavemode ilv;
- int colorTransform;
- char outputBgr;
- struct JlsCustomParameters custom;
- struct JfifParameters jfif;
-};
-
-#endif
diff --git a/src/JpegStreamWriter.cd b/src/JpegStreamWriter.cd
new file mode 100644
index 0000000..90e5209
--- /dev/null
+++ b/src/JpegStreamWriter.cd
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ClassDiagram MajorVersion="1" MinorVersion="1">
+ <Comment CommentText="The JpegStreamWriter can be used to create JPEG streams containing JPEG-LS encodeded images.
The basic mechanism is that the JpegStreamWriter serializes JpegSegments to the output destination. There are 2 types of JpegSegments: The JpegMarkerSegments contain predefines JPEG markers that hold info about the encoded data and define the structure of the stream. The JpegImageDataSegments contain the actual encoded bits.">
+ <Position X="0.625" Y="5.74" Height="1.271" Width="5.106" />
+ </Comment>
+ <Class Name="JpegSegment">
+ <Position X="2.5" Y="0.5" Width="1.5" />
+ <TypeIdentifier>
+ <HashCode>AAAAIAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAEAAAA=</HashCode>
+ <FileName>header.h</FileName>
+ </TypeIdentifier>
+ </Class>
+ <Class Name="JpegMarkerSegment">
+ <Position X="0.5" Y="3" Width="1.75" />
+ <Compartments>
+ <Compartment Name="Fields" Collapsed="true" />
+ </Compartments>
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAAAAAAAAABACAAAAAAAAAAAAAAAAAAAEAAgA=</HashCode>
+ <FileName>header.cpp</FileName>
+ </TypeIdentifier>
+ </Class>
+ <Class Name="JpegImageDataSegment">
+ <Position X="4" Y="3" Width="2" />
+ <Compartments>
+ <Compartment Name="Fields" Collapsed="true" />
+ </Compartments>
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAAAAAAAAAgAAAAAAIAAAAAAAAAAAhAAEAgAA=</HashCode>
+ <FileName>header.cpp</FileName>
+ </TypeIdentifier>
+ </Class>
+ <Class Name="JpegMarkerWriter">
+ <Position X="6.75" Y="0.5" Width="2.25" />
+ <Compartments>
+ <Compartment Name="Fields" Collapsed="true" />
+ </Compartments>
+ <TypeIdentifier>
+ <HashCode>AAAQAAgABKAAAAAADgAAEAgAQAAKAIAgAAAQAAUCAAA=</HashCode>
+ <FileName>jpegmarker.h</FileName>
+ </TypeIdentifier>
+ </Class>
+ <Font Name="Segoe UI" Size="9" />
+</ClassDiagram>
\ No newline at end of file
diff --git a/License.txt b/src/License.txt
similarity index 100%
rename from License.txt
rename to src/License.txt
diff --git a/charls.def b/src/charls.def
similarity index 53%
rename from charls.def
rename to src/charls.def
index edfce16..d950de3 100644
--- a/charls.def
+++ b/src/charls.def
@@ -1,7 +1,10 @@
-LIBRARY "CharLS"
-EXPORTS
- JpegLsEncode
- JpegLsDecode
- JpegLsDecodeRect
- JpegLsReadHeader
- JpegLsVerifyEncode
\ No newline at end of file
+LIBRARY "CharLS"
+EXPORTS
+ JpegLsEncode
+ JpegLsDecode
+ JpegLsDecodeRect
+ JpegLsReadHeader
+ JpegLsVerifyEncode
+ JpegLsEncodeStream
+ JpegLsDecodeStream
+ JpegLsReadHeaderStream
\ No newline at end of file
diff --git a/src/charls.rc b/src/charls.rc
new file mode 100644
index 0000000..90bdb59
Binary files /dev/null and b/src/charls.rc differ
diff --git a/colortransform.h b/src/colortransform.h
similarity index 98%
rename from colortransform.h
rename to src/colortransform.h
index 548e993..06e31d3 100644
--- a/colortransform.h
+++ b/src/colortransform.h
@@ -9,6 +9,9 @@
// They are invoked in processline.h to convert between decoded values and the internal line buffers.
// Color transforms work best for computer generated images.
//
+#ifdef _MSC_VER
+#pragma warning (disable: 4127)
+#endif
template<class sample>
struct TransformNoneImpl
diff --git a/config.h b/src/config.h
similarity index 80%
rename from config.h
rename to src/config.h
index ec90c21..ccb1ac4 100644
--- a/config.h
+++ b/src/config.h
@@ -1,6 +1,6 @@
-//
-// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
-//
+/*
+ (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
+*/
#ifndef CHARLS_CONFIG
@@ -9,7 +9,6 @@
#ifdef NDEBUG
# ifndef ASSERT
# define ASSERT(t) { }
-# define assert(t) { }
# endif
#else
#include <assert.h>
@@ -30,8 +29,7 @@ typedef long long int64_t;
typedef unsigned long long uint64_t;
#endif
-// Typedef used by Charls for the default integral type.
-// charls will work correctly with 64 or 32 bit.
+/* Typedef used by Charls for the default integral type. charls will work correctly with 64 or 32 bit. */
typedef long LONG;
enum constants
diff --git a/context.h b/src/context.h
similarity index 72%
rename from context.h
rename to src/context.h
index dd797e7..71c089e 100644
--- a/context.h
+++ b/src/context.h
@@ -6,6 +6,8 @@
#ifndef CHARLS_CONTEXT
#define CHARLS_CONTEXT
+#include <cstdlib>
+
//
// JlsContext: a JPEG-LS context with it's current statistics.
@@ -43,8 +45,8 @@ public:
ASSERT(N != 0);
// For performance work on copies of A,B,N (compiler will use registers).
+ int a = A + std::abs(errorValue);
int b = B + errorValue * (2 * NEAR + 1);
- int a = A + abs(errorValue);
int n = N;
ASSERT(a < 65536 * 256);
@@ -57,8 +59,10 @@ public:
n = n >> 1;
}
+ A = a;
n = n + 1;
-
+ N = (short)n;
+
if (b + n <= 0)
{
b = b + n;
@@ -66,7 +70,7 @@ public:
{
b = -n + 1;
}
- C = _tableC[C - 1];
+ C = C - (C > -128);
}
else if (b > 0)
{
@@ -75,11 +79,10 @@ public:
{
b = 0;
}
- C = _tableC[C + 1];
+ C = C + (C < 127);
}
- A = a;
B = b;
- N = (short)n;
+
ASSERT(N != 0);
}
@@ -89,7 +92,14 @@ public:
{
LONG Ntest = N;
LONG Atest = A;
- LONG k = 0;
+
+ if (Ntest >= Atest) return 0;
+ if (Ntest << 1 >= Atest) return 1;
+ if (Ntest << 2 >= Atest) return 2;
+ if (Ntest << 3 >= Atest) return 3;
+ if (Ntest << 4 >= Atest) return 4;
+
+ LONG k = 5;
for(; (Ntest << k) < Atest; k++)
{
ASSERT(k <= 32);
@@ -97,26 +107,7 @@ public:
return k;
}
- static signed char* CreateTableC()
- {
- static std::vector<signed char> rgtableC;
-
- rgtableC.reserve(256 + 2);
-
- rgtableC.push_back(-128);
- for (int i = -128; i < 128; i++)
- {
- rgtableC.push_back(char(i));
- }
- rgtableC.push_back(127);
-
- signed char* pZero = &rgtableC[128 + 1];
- ASSERT(pZero[0] == 0);
- return pZero;
- }
-private:
-
- static signed char* _tableC;
+
};
#endif
diff --git a/contextrunmode.h b/src/contextrunmode.h
similarity index 85%
rename from contextrunmode.h
rename to src/contextrunmode.h
index 0eac1e0..5154a4b 100644
--- a/contextrunmode.h
+++ b/src/contextrunmode.h
@@ -64,7 +64,7 @@ struct CContextRunMode
{
bool map = temp & 1;
- LONG errvalabs = (temp + map) / 2;
+ LONG errvalabs = (temp + LONG(map)) / 2;
if ((k != 0 || (2 * Nn >= N)) == map)
{
@@ -80,19 +80,19 @@ struct CContextRunMode
bool ComputeMap(LONG Errval, LONG k) const
{
if ((k == 0) && (Errval > 0) && (2 * Nn < N))
- return 1;
+ return true;
- else if ((Errval < 0) && (2 * Nn >= N))
- return 1;
+ if ((Errval < 0) && (2 * Nn >= N))
+ return true;
- else if ((Errval < 0) && (k != 0))
- return 1;
+ if ((Errval < 0) && (k != 0))
+ return true;
- return 0;
+ return false;
}
- inlinehint LONG ComputeMapNegativeE(LONG k) const
+ inlinehint bool ComputeMapNegativeE(LONG k) const
{
return k != 0 || (2 * Nn >= N );
}
diff --git a/src/decoderstrategy.h b/src/decoderstrategy.h
new file mode 100644
index 0000000..9488b62
--- /dev/null
+++ b/src/decoderstrategy.h
@@ -0,0 +1,325 @@
+//
+// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
+
+#ifndef CHARLS_DECODERSTATEGY
+#define CHARLS_DECODERSTATEGY
+
+#include "jpegmarker.h"
+#include "processline.h"
+#include "config.h"
+#include "util.h"
+
+// Implements encoding to stream of bits. In encoding mode JpegLsCodec inherits from EncoderStrategy
+
+class DecoderStrategy
+{
+public:
+ DecoderStrategy(const JlsParameters& info) :
+ _info(info),
+ _byteStream(NULL),
+ _readCache(0),
+ _validBits(0),
+ _position(NULL),
+ _nextFFPosition(NULL),
+ _endPosition(NULL)
+ {
+ }
+
+ virtual ~DecoderStrategy()
+ {
+ }
+
+ virtual ProcessLine* CreateProcess(ByteStreamInfo rawStreamInfo) = 0;
+
+ virtual void SetPresets(const JlsCustomParameters& presets) = 0;
+ virtual void DecodeScan(std::auto_ptr<ProcessLine> outputData, const JlsRect& size, ByteStreamInfo* compressedData, bool bCheck) = 0;
+
+ void Init(ByteStreamInfo* compressedStream)
+ {
+ _validBits = 0;
+ _readCache = 0;
+
+ if (compressedStream->rawStream != NULL)
+ {
+ _buffer.resize(40000);
+ _position = (BYTE*)&_buffer[0];
+ _endPosition = _position;
+ _byteStream = compressedStream->rawStream;
+ AddBytesFromStream();
+ }
+ else
+ {
+ _byteStream = NULL;
+ _position = compressedStream->rawData;
+ _endPosition = _position + compressedStream->count;
+ }
+
+ _nextFFPosition = FindNextFF();
+ MakeValid();
+ }
+
+ void AddBytesFromStream()
+ {
+ if (_byteStream == NULL || _byteStream->sgetc() == std::char_traits<char>::eof())
+ return;
+
+ size_t count = _endPosition - _position;
+
+ if (count > 64)
+ return;
+
+ for (size_t i = 0; i < count; ++i)
+ {
+ _buffer[i] = _position[i];
+ }
+ size_t offset = &_buffer[0] - _position;
+
+ _position += offset;
+ _endPosition += offset;
+ _nextFFPosition += offset;
+
+ std::streamsize readbytes = _byteStream->sgetn((char*)_endPosition, _buffer.size() - count);
+ _endPosition += readbytes;
+ }
+
+ inlinehint void Skip(LONG length)
+ {
+ _validBits -= length;
+ _readCache = _readCache << length;
+ }
+
+
+ void OnLineBegin(LONG /*cpixel*/, void* /*ptypeBuffer*/, LONG /*pixelStride*/)
+ {
+ }
+
+
+ void OnLineEnd(LONG pixelCount, const void* ptypeBuffer, LONG pixelStride)
+ {
+ _processLine->NewLineDecoded(ptypeBuffer, pixelCount, pixelStride);
+ }
+
+ void EndScan()
+ {
+ if ((*_position) != 0xFF)
+ {
+ ReadBit();
+
+ if ((*_position) != 0xFF)
+ throw JlsException(TooMuchCompressedData);
+ }
+
+ if (_readCache != 0)
+ throw JlsException(TooMuchCompressedData);
+ }
+
+
+ inlinehint bool OptimizedRead()
+ {
+ // Easy & fast: if there is no 0xFF byte in sight, we can read without bitstuffing
+ if (_position < _nextFFPosition - (sizeof(bufType)-1))
+ {
+ _readCache |= FromBigEndian<sizeof(bufType)>::Read(_position) >> _validBits;
+ int bytesToRead = (bufferbits - _validBits) >> 3;
+ _position += bytesToRead;
+ _validBits += bytesToRead * 8;
+ ASSERT(_validBits >= bufferbits - 8);
+ return true;
+ }
+ return false;
+ }
+
+ typedef size_t bufType;
+
+ enum {
+ bufferbits = sizeof( bufType ) * 8
+ };
+
+ void MakeValid()
+ {
+ ASSERT(_validBits <=bufferbits - 8);
+
+ if (OptimizedRead())
+ return;
+
+ AddBytesFromStream();
+
+ do
+ {
+ if (_position >= _endPosition)
+ {
+ if (_validBits <= 0)
+ throw JlsException(InvalidCompressedData);
+
+ return;
+ }
+
+ bufType valnew = _position[0];
+
+ if (valnew == 0xFF)
+ {
+ // JPEG bitstream rule: no FF may be followed by 0x80 or higher
+ if (_position == _endPosition - 1 || (_position[1] & 0x80) != 0)
+ {
+ if (_validBits <= 0)
+ throw JlsException(InvalidCompressedData);
+
+ return;
+ }
+ }
+
+ _readCache |= valnew << (bufferbits - 8 - _validBits);
+ _position += 1;
+ _validBits += 8;
+
+ if (valnew == 0xFF)
+ {
+ _validBits--;
+ }
+ }
+ while (_validBits < bufferbits - 8);
+
+ _nextFFPosition = FindNextFF();
+ return;
+ }
+
+
+ BYTE* FindNextFF()
+ {
+ BYTE* pbyteNextFF = _position;
+
+ while (pbyteNextFF < _endPosition)
+ {
+ if (*pbyteNextFF == 0xFF)
+ break;
+
+ pbyteNextFF++;
+ }
+
+ return pbyteNextFF;
+ }
+
+
+ BYTE* GetCurBytePos() const
+ {
+ LONG validBits = _validBits;
+ BYTE* compressedBytes = _position;
+
+ for (;;)
+ {
+ LONG cbitLast = compressedBytes[-1] == 0xFF ? 7 : 8;
+
+ if (validBits < cbitLast )
+ return compressedBytes;
+
+ validBits -= cbitLast;
+ compressedBytes--;
+ }
+ }
+
+
+ inlinehint LONG ReadValue(LONG length)
+ {
+ if (_validBits < length)
+ {
+ MakeValid();
+ if (_validBits < length)
+ throw JlsException(InvalidCompressedData);
+ }
+
+ ASSERT(length != 0 && length <= _validBits);
+ ASSERT(length < 32);
+ LONG result = LONG(_readCache >> (bufferbits - length));
+ Skip(length);
+ return result;
+ }
+
+
+ inlinehint LONG PeekByte()
+ {
+ if (_validBits < 8)
+ {
+ MakeValid();
+ }
+
+ return _readCache >> (bufferbits - 8);
+ }
+
+
+ inlinehint bool ReadBit()
+ {
+ if (_validBits <= 0)
+ {
+ MakeValid();
+ }
+
+ bool bSet = (_readCache & (bufType(1) << (bufferbits - 1))) != 0;
+ Skip(1);
+ return bSet;
+ }
+
+
+ inlinehint LONG Peek0Bits()
+ {
+ if (_validBits < 16)
+ {
+ MakeValid();
+ }
+ bufType valTest = _readCache;
+
+ for (LONG count = 0; count < 16; count++)
+ {
+ if ((valTest & (bufType(1) << (bufferbits - 1))) != 0)
+ return count;
+
+ valTest <<= 1;
+ }
+ return -1;
+ }
+
+
+ inlinehint LONG ReadHighbits()
+ {
+ LONG count = Peek0Bits();
+ if (count >= 0)
+ {
+ Skip(count + 1);
+ return count;
+ }
+ Skip(15);
+
+ for (LONG highbits = 15; ; highbits++)
+ {
+ if (ReadBit())
+ return highbits;
+ }
+ }
+
+
+ LONG ReadLongValue(LONG length)
+ {
+ if (length <= 24)
+ return ReadValue(length);
+
+ return (ReadValue(length - 24) << 24) + ReadValue(24);
+ }
+
+protected:
+ JlsParameters _info;
+ std::auto_ptr<ProcessLine> _processLine;
+
+private:
+ std::vector<BYTE> _buffer;
+ std::basic_streambuf<char>* _byteStream;
+
+ // decoding
+ bufType _readCache;
+ LONG _validBits;
+ BYTE* _position;
+ BYTE* _nextFFPosition;
+ BYTE* _endPosition;
+};
+
+
+#endif
diff --git a/defaulttraits.h b/src/defaulttraits.h
similarity index 88%
rename from defaulttraits.h
rename to src/defaulttraits.h
index 5032f7d..2456429 100644
--- a/defaulttraits.h
+++ b/src/defaulttraits.h
@@ -13,6 +13,8 @@
// This is to allow the traits class to replace the default implementation here with optimized specific implementations.
// This is done for lossless coding/decoding: see losslesstraits.h
+#include <cstdlib>
+
template <class sample, class pixel>
struct DefaultTraitsT
{
@@ -53,8 +55,7 @@ public:
inlinehint LONG ComputeErrVal(LONG e) const
{
- LONG q = Quantize(e);
- return ModRange(q);
+ return ModRange(Quantize(e));
}
inlinehint SAMPLE ComputeReconstructedSample(LONG Px, LONG ErrVal)
@@ -63,13 +64,13 @@ public:
}
inlinehint bool IsNear(LONG lhs, LONG rhs) const
- { return abs(lhs-rhs) <=NEAR; }
+ { return std::abs(lhs-rhs) <=NEAR; }
bool IsNear(Triplet<SAMPLE> lhs, Triplet<SAMPLE> rhs) const
{
- return abs(lhs.v1-rhs.v1) <=NEAR &&
- abs(lhs.v2-rhs.v2) <=NEAR &&
- abs(lhs.v3-rhs.v3) <=NEAR;
+ return std::abs(lhs.v1 - rhs.v1) <= NEAR &&
+ std::abs(lhs.v2 - rhs.v2) <= NEAR &&
+ std::abs(lhs.v3 - rhs.v3) <= NEAR;
}
inlinehint LONG CorrectPrediction(LONG Pxc) const
@@ -82,14 +83,14 @@ public:
inlinehint LONG ModRange(LONG Errval) const
{
- ASSERT(abs(Errval) <= RANGE);
+ ASSERT(std::abs(Errval) <= RANGE);
if (Errval < 0)
Errval = Errval + RANGE;
if (Errval >= ((RANGE + 1) / 2))
Errval = Errval - RANGE;
- ASSERT(abs(Errval) <= RANGE/2);
+ ASSERT(std::abs(Errval) <= RANGE/2);
return Errval;
}
diff --git a/encoderstrategy.h b/src/encoderstrategy.h
similarity index 55%
rename from encoderstrategy.h
rename to src/encoderstrategy.h
index f2426db..1c8cb45 100644
--- a/encoderstrategy.h
+++ b/src/encoderstrategy.h
@@ -15,14 +15,14 @@ class EncoderStrategy
public:
explicit EncoderStrategy(const JlsParameters& info) :
- _qdecoder(0),
_info(info),
- _processLine(0),
- valcurrent(0),
+ valcurrent(0),
bitpos(0),
+ _compressedLength(0),
+ _position(0),
_isFFWritten(false),
- _bytesWritten(0)
-
+ _bytesWritten(0),
+ _compressedStream(NULL)
{
}
@@ -31,7 +31,7 @@ public:
}
LONG PeekByte();
-
+
void OnLineBegin(LONG cpixel, void* ptypeBuffer, LONG pixelStride)
{
_processLine->NewLineRequested(ptypeBuffer, cpixel, pixelStride);
@@ -39,23 +39,36 @@ public:
void OnLineEnd(LONG /*cpixel*/, void* /*ptypeBuffer*/, LONG /*pixelStride*/) { }
- virtual void SetPresets(const JlsCustomParameters& presets) = 0;
-
- virtual size_t EncodeScan(const void* pvoid, void* pvoidOut, size_t byteCount, void* pvoidCompare) = 0;
+ virtual void SetPresets(const JlsCustomParameters& presets) = 0;
+
+ virtual size_t EncodeScan(std::auto_ptr<ProcessLine> rawData, ByteStreamInfo* compressedData, void* pvoidCompare) = 0;
+
+ virtual ProcessLine* CreateProcess(ByteStreamInfo rawStreamInfo) = 0;
protected:
- void Init(BYTE* compressedBytes, size_t byteCount)
+ void Init(ByteStreamInfo* compressedStream)
{
bitpos = 32;
valcurrent = 0;
- _position = compressedBytes;
- _compressedLength = byteCount;
+
+ if (compressedStream->rawStream == NULL)
+ {
+ _position = compressedStream->rawData;
+ _compressedLength = compressedStream->count;
+ }
+ else
+ {
+ _compressedStream = compressedStream->rawStream;
+ _buffer.resize(4000);
+ _position = (BYTE*)&_buffer[0];
+ _compressedLength = _buffer.size();
+ }
}
void AppendToBitStream(LONG value, LONG length)
- {
+ {
ASSERT(length < 32 && length >= 0);
ASSERT((_qdecoder.get() == NULL) || (length == 0 && value == 0) ||( _qdecoder->ReadLongValue(length) == value));
@@ -74,13 +87,19 @@ protected:
valcurrent = valcurrent | (value << bitpos);
return;
}
- valcurrent |= value >> -bitpos;
+ valcurrent |= value >> -bitpos;
Flush();
-
- ASSERT(bitpos >=0);
- valcurrent |= value << bitpos;
+ // A second flush may be required if extra marker-detect bits were needed and not all bits could be written.
+ if (bitpos < 0)
+ {
+ valcurrent |= value >> -bitpos;
+ Flush();
+ }
+
+ ASSERT(bitpos >=0);
+ valcurrent |= value << bitpos;
}
void EndScan()
@@ -92,13 +111,38 @@ protected:
AppendToBitStream(0, (bitpos - 1) % 8);
else
AppendToBitStream(0, bitpos % 8);
-
+
Flush();
ASSERT(bitpos == 0x20);
+
+ if (_compressedStream != NULL)
+ {
+ OverFlow();
+ }
+ }
+
+ void OverFlow()
+ {
+ if (_compressedStream == NULL)
+ throw JlsException(CompressedBufferTooSmall);
+
+ size_t bytesCount = _position-(BYTE*)&_buffer[0];
+ size_t bytesWritten = (size_t)_compressedStream->sputn((char*)&_buffer[0], _position - (BYTE*)&_buffer[0]);
+
+ if (bytesWritten != bytesCount)
+ throw JlsException(CompressedBufferTooSmall);
+
+ _position = (BYTE*)&_buffer[0];
+ _compressedLength = _buffer.size();
}
void Flush()
{
+ if (_compressedLength < 4)
+ {
+ OverFlow();
+ }
+
for (LONG i = 0; i < 4; ++i)
{
if (bitpos >= 32)
@@ -106,34 +150,30 @@ protected:
if (_isFFWritten)
{
- // insert highmost bit
+ // JPEG-LS requirement (T.87, A.1) to detect markers: after a xFF value a single 0 bit needs to be inserted.
*_position = BYTE(valcurrent >> 25);
- valcurrent = valcurrent << 7;
- bitpos += 7;
- _isFFWritten = false;
+ valcurrent = valcurrent << 7;
+ bitpos += 7;
}
else
{
*_position = BYTE(valcurrent >> 24);
- valcurrent = valcurrent << 8;
- bitpos += 8;
- _isFFWritten = *_position == 0xFF;
+ valcurrent = valcurrent << 8;
+ bitpos += 8;
}
-
+
+ _isFFWritten = *_position == 0xFF;
_position++;
_compressedLength--;
_bytesWritten++;
-
}
-
}
size_t GetLength()
- {
+ {
return _bytesWritten - (bitpos -32)/8;
}
-
inlinehint void AppendOnesToBitStream(LONG length)
{
AppendToBitStream((1 << length) - 1, length);
@@ -145,17 +185,20 @@ protected:
protected:
JlsParameters _info;
std::auto_ptr<ProcessLine> _processLine;
-private:
+private:
unsigned int valcurrent;
LONG bitpos;
size_t _compressedLength;
-
+
+
// encoding
BYTE* _position;
bool _isFFWritten;
size_t _bytesWritten;
+ std::vector<BYTE> _buffer;
+ std::basic_streambuf<char>* _compressedStream;
};
#endif
diff --git a/src/header.cpp b/src/header.cpp
new file mode 100644
index 0000000..9ddedc8
--- /dev/null
+++ b/src/header.cpp
@@ -0,0 +1,388 @@
+//
+// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
+
+#include "config.h"
+#include "util.h"
+#include "header.h"
+#include "jpegmarker.h"
+#include "jpegstreamwriter.h"
+#include "jpegmarkersegment.h"
+#include "jpegimagedatasegment.h"
+#include "decoderstrategy.h"
+#include "encoderstrategy.h"
+#include <memory>
+
+
+// JFIF\0
+BYTE jfifID[] = {'J','F','I','F','\0'};
+
+
+LONG CLAMP(LONG i, LONG j, LONG MAXVAL)
+{
+ if (i > MAXVAL || i < j)
+ return j;
+
+ return i;
+}
+
+
+JlsCustomParameters ComputeDefault(LONG MAXVAL, LONG NEAR)
+{
+ JlsCustomParameters preset = JlsCustomParameters();
+
+ LONG FACTOR = (MIN(MAXVAL, 4095) + 128)/256;
+
+ preset.T1 = CLAMP(FACTOR * (BASIC_T1 - 2) + 2 + 3*NEAR, NEAR + 1, MAXVAL);
+ preset.T2 = CLAMP(FACTOR * (BASIC_T2 - 3) + 3 + 5*NEAR, preset.T1, MAXVAL);
+ preset.T3 = CLAMP(FACTOR * (BASIC_T3 - 4) + 4 + 7*NEAR, preset.T2, MAXVAL);
+ preset.MAXVAL = MAXVAL;
+ preset.RESET = BASIC_RESET;
+ return preset;
+}
+
+
+JLS_ERROR CheckParameterCoherent(const JlsParameters* pparams)
+{
+ if (pparams->bitspersample < 2 || pparams->bitspersample > 16)
+ return ParameterValueNotSupported;
+
+ if (pparams->ilv < 0 || pparams->ilv > 2)
+ return InvalidCompressedData;
+
+ switch (pparams->components)
+ {
+ case 4: return pparams->ilv == ILV_SAMPLE ? ParameterValueNotSupported : OK;
+ case 3: return OK;
+ case 1: return pparams->ilv != ILV_NONE ? ParameterValueNotSupported : OK;
+ case 0: return InvalidJlsParameters;
+
+ default: return pparams->ilv != ILV_NONE ? ParameterValueNotSupported : OK;
+ }
+}
+
+
+void JpegImageDataSegment::Serialize(JpegStreamWriter& streamWriter)
+{
+ JlsParameters info = _info;
+ info.components = _ccompScan;
+ std::auto_ptr<EncoderStrategy> qcodec = JlsCodecFactory<EncoderStrategy>().GetCodec(info, _info.custom);
+ ProcessLine* processLine = qcodec->CreateProcess(_rawStreamInfo);
+ ByteStreamInfo compressedData = streamWriter.OutputStream();
+ size_t cbyteWritten = qcodec->EncodeScan(std::auto_ptr<ProcessLine>(processLine), &compressedData, streamWriter._bCompare ? streamWriter.GetPos() : NULL);
+ streamWriter.Seek(cbyteWritten);
+}
+
+
+int ReadScanHeader(BYTE* compressedBytes)
+{
+ BYTE rgbyte[20];
+ size_t readBytes = 0;
+ ::memcpy(rgbyte, compressedBytes, 4);
+ readBytes += 4;
+
+ size_t cbyteScanheader = rgbyte[3] - 2;
+
+ if (cbyteScanheader > sizeof(rgbyte))
+ throw JlsException(InvalidCompressedData);
+
+ ::memcpy(rgbyte, compressedBytes, cbyteScanheader);
+ readBytes += cbyteScanheader;
+ return (int) readBytes;
+}
+
+
+void Assert(bool valid)
+{
+ if (!valid)
+ throw JlsException(InvalidCompressedData);
+}
+
+
+JpegMarkerReader::JpegMarkerReader(ByteStreamInfo byteStreamInfo) :
+ _byteStream(byteStreamInfo),
+ _bCompare(false),
+ _info(),
+ _rect()
+{
+}
+
+
+void JpegMarkerReader::Read(ByteStreamInfo rawPixels)
+{
+ ReadHeader();
+
+ JLS_ERROR error = CheckParameterCoherent(&_info);
+ if (error != OK)
+ throw JlsException(error);
+
+ if (_rect.Width <= 0)
+ {
+ _rect.Width = _info.width;
+ _rect.Height = _info.height;
+ }
+
+ int64_t bytesPerPlane = (int64_t)(_rect.Width) * _rect.Height * ((_info.bitspersample + 7)/8);
+
+ if (rawPixels.rawData != NULL && int64_t(rawPixels.count) < bytesPerPlane * _info.components)
+ throw JlsException(UncompressedBufferTooSmall);
+
+ int componentIndex = 0;
+
+ while (componentIndex < _info.components)
+ {
+ ReadStartOfScan(componentIndex == 0);
+
+ std::auto_ptr<DecoderStrategy> qcodec = JlsCodecFactory<DecoderStrategy>().GetCodec(_info, _info.custom);
+ ProcessLine* processLine = qcodec->CreateProcess(rawPixels);
+ qcodec->DecodeScan(std::auto_ptr<ProcessLine>(processLine), _rect, &_byteStream, _bCompare);
+ SkipBytes(&rawPixels, (size_t)bytesPerPlane);
+
+ if (_info.ilv != ILV_NONE)
+ return;
+
+ componentIndex += 1;
+ }
+}
+
+
+void JpegMarkerReader::ReadNBytes(std::vector<char>& dst, int byteCount)
+{
+ for (int i = 0; i < byteCount; ++i)
+ {
+ dst.push_back((char)ReadByte());
+ }
+}
+
+
+void JpegMarkerReader::ReadHeader()
+{
+ if (ReadByte() != 0xFF)
+ throw JlsException(MissingJpegMarkerStart);
+
+ if (ReadByte() != JPEG_SOI)
+ throw JlsException(InvalidCompressedData);
+
+ for (;;)
+ {
+ if (ReadByte() != 0xFF)
+ throw JlsException(MissingJpegMarkerStart);
+
+ BYTE marker = (BYTE)ReadByte();
+
+ if (marker == JPEG_SOS)
+ return;
+
+ LONG cbyteMarker = ReadWord();
+
+ int bytesRead = ReadMarker(marker) + 2;
+
+ int paddingToRead = cbyteMarker - bytesRead;
+
+ if (paddingToRead < 0)
+ throw JlsException(InvalidCompressedData);
+
+ for (int i = 0; i < paddingToRead; ++i)
+ {
+ ReadByte();
+ }
+ }
+}
+
+
+int JpegMarkerReader::ReadMarker(BYTE marker)
+{
+ switch (marker)
+ {
+ case JPEG_SOF_55: return ReadStartOfFrame();
+ case JPEG_COM: return ReadComment();
+ case JPEG_LSE: return ReadPresetParameters();
+ case JPEG_APP0: return 0;
+ case JPEG_APP7: return ReadColorSpace();
+ case JPEG_APP8: return ReadColorXForm();
+ case JPEG_SOF_0:
+ case JPEG_SOF_1:
+ case JPEG_SOF_2:
+ case JPEG_SOF_3:
+ case JPEG_SOF_5:
+ case JPEG_SOF_6:
+ case JPEG_SOF_7:
+ case JPEG_SOF_9:
+ case JPEG_SOF_10:
+ case JPEG_SOF_11:
+ throw JlsException(UnsupportedEncoding);
+
+ // Other tags not supported (among which DNL DRI)
+ default: throw JlsException(UnknownJpegMarker);
+ }
+}
+
+
+int JpegMarkerReader::ReadPresetParameters()
+{
+ LONG type = ReadByte();
+
+ switch (type)
+ {
+ case 1:
+ {
+ _info.custom.MAXVAL = ReadWord();
+ _info.custom.T1 = ReadWord();
+ _info.custom.T2 = ReadWord();
+ _info.custom.T3 = ReadWord();
+ _info.custom.RESET = ReadWord();
+ return 11;
+ }
+ }
+
+ return 1;
+}
+
+
+void JpegMarkerReader::ReadStartOfScan(bool firstComponent)
+{
+ if (!firstComponent)
+ {
+ Assert(ReadByte() == 0xFF);
+ Assert(ReadByte() == JPEG_SOS);
+ }
+ int length = ReadByte(); //length
+ length = length * 256 + ReadByte();
+
+ LONG componentCount = ReadByte();
+ if (componentCount != 1 && componentCount != _info.components)
+ throw JlsException(ParameterValueNotSupported);
+
+ for (LONG i = 0; i < componentCount; ++i)
+ {
+ ReadByte();
+ ReadByte();
+ }
+ _info.allowedlossyerror = ReadByte();
+ _info.ilv = interleavemode(ReadByte());
+ Assert(ILV_NONE <= _info.ilv && _info.ilv <= ILV_SAMPLE);
+ Assert(ReadByte() == 0);
+
+ if(_info.bytesperline == 0)
+ {
+ int width = _rect.Width != 0 ? _rect.Width : _info.width;
+ int components = _info.ilv == ILV_NONE ? 1 : _info.components;
+ _info.bytesperline = components * width * ((_info.bitspersample + 7)/8);
+ }
+}
+
+
+int JpegMarkerReader::ReadComment()
+{
+ return 0;
+}
+
+
+void JpegMarkerReader::ReadJfif()
+{
+ for(int i = 0; i < (int)sizeof(jfifID); i++)
+ {
+ if(jfifID[i] != ReadByte())
+ return;
+ }
+ _info.jfif.Ver = ReadWord();
+
+ // DPI or DPcm
+ _info.jfif.units = ReadByte();
+ _info.jfif.XDensity = ReadWord();
+ _info.jfif.YDensity = ReadWord();
+
+ // thumbnail
+ _info.jfif.Xthumb = ReadByte();
+ _info.jfif.Ythumb = ReadByte();
+ if(_info.jfif.Xthumb > 0 && _info.jfif.pdataThumbnail)
+ {
+ std::vector<char> tempbuff((char*)_info.jfif.pdataThumbnail, (char*)_info.jfif.pdataThumbnail+3*_info.jfif.Xthumb*_info.jfif.Ythumb);
+ ReadNBytes(tempbuff, 3*_info.jfif.Xthumb*_info.jfif.Ythumb);
+ }
+}
+
+
+int JpegMarkerReader::ReadStartOfFrame()
+{
+ _info.bitspersample = ReadByte();
+ int cline = ReadWord();
+ int ccol = ReadWord();
+ _info.width = ccol;
+ _info.height = cline;
+ _info.components= ReadByte();
+ return 6;
+}
+
+
+BYTE JpegMarkerReader::ReadByte()
+{
+ if (_byteStream.rawStream != NULL)
+ return (BYTE)_byteStream.rawStream->sbumpc();
+
+ if (_byteStream.count <= 0)
+ throw JlsException(InvalidCompressedData);
+
+ BYTE value = _byteStream.rawData[0];
+
+ SkipBytes(&_byteStream, 1);
+
+ return value;
+}
+
+
+int JpegMarkerReader::ReadWord()
+{
+ int i = ReadByte() * 256;
+ return i + ReadByte();
+}
+
+
+int JpegMarkerReader::ReadColorSpace()
+{
+ return 0;
+}
+
+
+int JpegMarkerReader::ReadColorXForm()
+{
+ std::vector<char> sourceTag;
+ ReadNBytes(sourceTag, 4);
+
+ if(strncmp(&sourceTag[0],"mrfx", 4) != 0)
+ return 4;
+
+ int xform = ReadByte();
+ switch(xform)
+ {
+ case COLORXFORM_NONE:
+ case COLORXFORM_HP1:
+ case COLORXFORM_HP2:
+ case COLORXFORM_HP3:
+ _info.colorTransform = xform;
+ return 5;
+ case COLORXFORM_RGB_AS_YUV_LOSSY:
+ case COLORXFORM_MATRIX:
+ throw JlsException(ImageTypeNotSupported);
+ default:
+ throw JlsException(InvalidCompressedData);
+ }
+}
+
+
+ByteStreamInfo FromStream(std::basic_streambuf<char>* stream)
+{
+ ByteStreamInfo info = ByteStreamInfo();
+ info.rawStream = stream;
+ return info;
+}
+
+
+void SkipBytes(ByteStreamInfo* streamInfo, size_t count)
+{
+ if (streamInfo->rawData == NULL)
+ return;
+
+ streamInfo->rawData += count;
+ streamInfo->count -= count;
+}
diff --git a/src/header.h b/src/header.h
new file mode 100644
index 0000000..b511a00
--- /dev/null
+++ b/src/header.h
@@ -0,0 +1,70 @@
+//
+// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
+
+
+#ifndef CHARLS_HEADER
+#define CHARLS_HEADER
+
+#include "jpegmarker.h"
+
+// JPEG Marker codes have the pattern 0xFFaa. The valid 'aa' options are defined by several ITU / IEC standards.
+// 0x00, 0x01, 0xFE, 0xC0-0xDF are defined in ITU T.81/IEC 10918-1
+// 0xF0 - 0xF6 are defined in ITU T.84/IEC 10918-3 JPEG extensions
+// 0xF7 - 0xF8 are defined in ITU T.87/IEC 14495-1 JPEG LS
+// 0x4F - 0x6F, 0x90 - 0x93 are defined in JPEG 2000 IEC 15444-1
+
+#define JPEG_SOI 0xD8 // Start Of Image
+#define JPEG_EOI 0xD9 // End Of Image
+#define JPEG_SOS 0xDA // Start Of Scan
+
+// The following markers are defined in ITU T.81 | ISO IEC 10918-1.
+#define JPEG_SOF_0 0xC0 // Start Of Frame (Baseline jpeg)
+#define JPEG_SOF_1 0xC1 // Start Of Frame (Extended sequential, huffman)
+#define JPEG_SOF_2 0xC2 // Start Of Frame (progressive, huffman)
+#define JPEG_SOF_3 0xC3 // Start Of Frame (lossless, huffman)
+#define JPEG_SOF_5 0xC5 // Start Of Frame (differential sequential, huffman)
+#define JPEG_SOF_6 0xC6 // Start Of Frame (differential progressive, huffman)
+#define JPEG_SOF_7 0xC7 // Start Of Frame (differential lossless, huffman)
+#define JPEG_JPG 0xC8 // Reserved for JPEG extension
+#define JPEG_SOF_9 0xC9 // Start Of Frame (extended sequential, arithmetic)
+#define JPEG_SOF_10 0xCA // Start Of Frame (progressive, arithmetic)
+#define JPEG_SOF_11 0xCB // Start Of Frame (lossless, arithmetic)
+
+#define JPEG_SOF_55 0xF7 // Start Of Frame (JPEG-LS encoded)
+#define JPEG_LSE 0xF8 // JPEG-LS extended parameters
+#define JPEG_DNL 0xDC
+#define JPEG_DRI 0xDD
+#define JPEG_RSTm 0xD0
+#define JPEG_COM 0xFE
+#define JPEG_APP0 0xE0 // Application data 0: used for JFIF header.
+#define JPEG_APP7 0xE7 // Application data 7: colorspace
+#define JPEG_APP8 0xE8 // Application data 8: colorXForm
+
+
+
+// Default bin sizes for JPEG-LS statistical modeling. Can be overriden at compression time, however this is rarely done.
+const int BASIC_T1 = 3;
+const int BASIC_T2 = 7;
+const int BASIC_T3 = 21;
+
+const LONG BASIC_RESET = 64;
+
+class JpegMarkerWriter;
+
+
+template<class STRATEGY>
+class JlsCodecFactory
+{
+public:
+ std::auto_ptr<STRATEGY> GetCodec(const JlsParameters& info, const JlsCustomParameters&);
+private:
+ STRATEGY* GetCodecImpl(const JlsParameters& info);
+};
+
+JLS_ERROR CheckParameterCoherent(const JlsParameters* pparams);
+
+JlsCustomParameters ComputeDefault(LONG MAXVAL, LONG NEAR);
+
+
+#endif
diff --git a/src/interface.cpp b/src/interface.cpp
new file mode 100644
index 0000000..2c661dd
--- /dev/null
+++ b/src/interface.cpp
@@ -0,0 +1,234 @@
+//
+// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
+
+
+// Implement correct linkage for win32 dlls
+#if defined(WIN32) && defined(CHARLS_DLL)
+#define CHARLS_IMEXPORT(returntype) __declspec(dllexport) returntype __stdcall
+#else
+#define CHARLS_IMEXPORT(returntype) returntype
+#endif
+
+#include "config.h"
+#include "util.h"
+#include "interface.h"
+#include "header.h"
+#include "jpegstreamwriter.h"
+#include <sstream>
+
+
+static JLS_ERROR CheckInput(ByteStreamInfo uncompressedStream, const JlsParameters* pparams)
+{
+ if (pparams == NULL)
+ return InvalidJlsParameters;
+
+ if (uncompressedStream.rawStream == NULL && uncompressedStream.rawData == NULL)
+ return InvalidJlsParameters;
+
+ if (pparams->width < 1 || pparams->width > 65535)
+ return ParameterValueNotSupported;
+
+ if (pparams->height < 1 || pparams->height > 65535)
+ return ParameterValueNotSupported;
+
+ if (uncompressedStream.rawData != NULL)
+ {
+ if (uncompressedStream.count < size_t(pparams->height * pparams->width * pparams->components * (pparams->bitspersample > 8 ? 2 : 1)))
+ return UncompressedBufferTooSmall;
+ }
+ else if (uncompressedStream.rawStream == NULL)
+ return InvalidJlsParameters;
+
+ return CheckParameterCoherent(pparams);
+}
+
+
+CHARLS_IMEXPORT(JLS_ERROR) JpegLsEncodeStream(ByteStreamInfo compressedStreamInfo, size_t* pcbyteWritten, ByteStreamInfo rawStreamInfo, struct JlsParameters* pparams)
+{
+ if (pcbyteWritten == NULL)
+ return InvalidJlsParameters;
+
+ JLS_ERROR parameterError = CheckInput(rawStreamInfo, pparams);
+ if (parameterError != OK)
+ return parameterError;
+
+ try
+ {
+ JlsParameters info = *pparams;
+ if (info.bytesperline == 0)
+ {
+ info.bytesperline = info.width * ((info.bitspersample + 7)/8);
+ if (info.ilv != ILV_NONE)
+ {
+ info.bytesperline *= info.components;
+ }
+ }
+
+ Size size = Size(info.width, info.height);
+
+ JpegStreamWriter writer(info.jfif, size, info.bitspersample, info.components);
+
+ if (info.colorTransform != 0)
+ {
+ writer.AddColorTransform(info.colorTransform);
+ }
+
+ if (info.ilv == ILV_NONE)
+ {
+ LONG cbyteComp = size.cx*size.cy*((info.bitspersample +7)/8);
+ for (LONG component = 0; component < info.components; ++component)
+ {
+ writer.AddScan(rawStreamInfo, &info);
+ SkipBytes(&rawStreamInfo, cbyteComp);
+ }
+ }
+ else
+ {
+ writer.AddScan(rawStreamInfo, &info);
+ }
+
+ writer.Write(compressedStreamInfo);
+ *pcbyteWritten = writer.GetBytesWritten();
+ return OK;
+ }
+ catch (const JlsException& e)
+ {
+ return e._error;
+ }
+}
+
+
+CHARLS_IMEXPORT(JLS_ERROR) JpegLsDecodeStream(ByteStreamInfo rawStream, ByteStreamInfo compressedStream, JlsParameters* info)
+{
+ JpegMarkerReader reader(compressedStream);
+
+ if (info != NULL)
+ {
+ reader.SetInfo(info);
+ }
+
+ try
+ {
+ reader.Read(rawStream);
+ return OK;
+ }
+ catch (const JlsException& e)
+ {
+ return e._error;
+ }
+}
+
+
+CHARLS_IMEXPORT(JLS_ERROR) JpegLsReadHeaderStream(ByteStreamInfo rawStreamInfo, JlsParameters* pparams)
+{
+ try
+ {
+ JpegMarkerReader reader(rawStreamInfo);
+ reader.ReadHeader();
+ reader.ReadStartOfScan(true);
+ JlsParameters info = reader.GetMetadata();
+ *pparams = info;
+ return OK;
+ }
+ catch (const JlsException& e)
+ {
+ return e._error;
+ }
+}
+
+extern "C"
+{
+ CHARLS_IMEXPORT(JLS_ERROR) JpegLsEncode(void* compressedData, size_t compressedLength, size_t* pcbyteWritten, const void* uncompressedData, size_t uncompressedLength, struct JlsParameters* pparams)
+ {
+ ByteStreamInfo rawStreamInfo = FromByteArray(uncompressedData, uncompressedLength);
+ ByteStreamInfo compressedStreamInfo = FromByteArray(compressedData, compressedLength);
+
+ return JpegLsEncodeStream(compressedStreamInfo, pcbyteWritten, rawStreamInfo, pparams);
+ }
+
+
+ CHARLS_IMEXPORT(JLS_ERROR) JpegLsDecode(void* uncompressedData, size_t uncompressedLength, const void* compressedData, size_t compressedLength, JlsParameters* info)
+ {
+ ByteStreamInfo compressedStream = FromByteArray(compressedData, compressedLength);
+ ByteStreamInfo rawStreamInfo = FromByteArray(uncompressedData, uncompressedLength);
+
+ return JpegLsDecodeStream(rawStreamInfo, compressedStream, info);
+ }
+
+
+ CHARLS_IMEXPORT(JLS_ERROR) JpegLsReadHeader(const void* compressedData, size_t compressedLength, JlsParameters* pparams)
+ {
+ return JpegLsReadHeaderStream(FromByteArray(compressedData, compressedLength), pparams);
+ }
+
+
+ CHARLS_IMEXPORT(JLS_ERROR) JpegLsVerifyEncode(const void* uncompressedData, size_t uncompressedLength, const void* compressedData, size_t compressedLength)
+ {
+ JlsParameters info = JlsParameters();
+
+ JLS_ERROR error = JpegLsReadHeader(compressedData, compressedLength, &info);
+ if (error != OK)
+ return error;
+
+ ByteStreamInfo rawStreamInfo = FromByteArray(uncompressedData, uncompressedLength);
+
+ error = CheckInput(rawStreamInfo, &info);
+
+ if (error != OK)
+ return error;
+
+ Size size = Size(info.width, info.height);
+
+ JpegStreamWriter writer(info.jfif, size, info.bitspersample, info.components);
+
+ if (info.ilv == ILV_NONE)
+ {
+ LONG fieldLength = size.cx*size.cy*((info.bitspersample +7)/8);
+ for (LONG component = 0; component < info.components; ++component)
+ {
+ writer.AddScan(rawStreamInfo, &info);
+ SkipBytes(&rawStreamInfo, fieldLength);
+ }
+ }
+ else
+ {
+ writer.AddScan(rawStreamInfo, &info);
+ }
+
+ std::vector<BYTE> rgbyteCompressed(compressedLength + 16);
+
+ memcpy(&rgbyteCompressed[0], compressedData, compressedLength);
+
+ writer.EnableCompare(true);
+ writer.Write(FromByteArray(&rgbyteCompressed[0], rgbyteCompressed.size()));
+
+ return OK;
+ }
+
+
+ CHARLS_IMEXPORT(JLS_ERROR) JpegLsDecodeRect(void* uncompressedData, size_t uncompressedLength, const void* compressedData, size_t compressedLength, JlsRect roi, JlsParameters* info)
+ {
+ ByteStreamInfo compressedStream = FromByteArray(compressedData, compressedLength);
+ JpegMarkerReader reader(compressedStream);
+
+ ByteStreamInfo rawStreamInfo = FromByteArray(uncompressedData, uncompressedLength);
+
+ if (info != NULL)
+ {
+ reader.SetInfo(info);
+ }
+
+ reader.SetRect(roi);
+
+ try
+ {
+ reader.Read(rawStreamInfo);
+ return OK;
+ }
+ catch (const JlsException& e)
+ {
+ return e._error;
+ }
+ }
+}
diff --git a/src/interface.h b/src/interface.h
new file mode 100644
index 0000000..db40bff
--- /dev/null
+++ b/src/interface.h
@@ -0,0 +1,66 @@
+/*
+ (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
+*/
+
+
+#ifndef JLS_INTERFACE
+#define JLS_INTERFACE
+
+#include "publictypes.h"
+
+/* non-windows (static linking) */
+#if !defined(CHARLS_IMEXPORT) && !defined(_WIN32)
+# define CHARLS_IMEXPORT(returntype) returntype
+#endif
+
+/* windows static linking */
+#if !defined(CHARLS_IMEXPORT) && defined(CHARLS_STATIC)
+# define CHARLS_IMEXPORT(returntype) returntype
+#endif
+
+/* windows dll */
+#if !defined(CHARLS_IMEXPORT) && defined(CHARLS_DLL)
+# define CHARLS_IMEXPORT(returntype) __declspec(dllimport) returntype __stdcall
+#endif
+
+#if !defined(CHARLS_IMEXPORT)
+#error Please #define CHARLS_STATIC or CHARLS_DLL before including "interface.h" to indicate if CharLS is built as a static library or as a dll.
+#endif
+
+
+#ifdef __cplusplus
+
+#include <iostream>
+
+extern "C"
+{
+
+#endif
+ CHARLS_IMEXPORT(enum JLS_ERROR) JpegLsEncode(void* compressedData, size_t compressedLength, size_t* byteCountWritten,
+ const void* uncompressedData, size_t uncompressedLength, struct JlsParameters* info);
+
+ CHARLS_IMEXPORT(enum JLS_ERROR) JpegLsDecode(void* uncompressedData, size_t uncompressedLength,
+ const void* compressedData, size_t compressedLength,
+ struct JlsParameters* info);
+
+ CHARLS_IMEXPORT(enum JLS_ERROR) JpegLsDecodeRect(void* uncompressedData, size_t uncompressedLength,
+ const void* compressedData, size_t compressedLength,
+ struct JlsRect rect, struct JlsParameters* info);
+
+ CHARLS_IMEXPORT(enum JLS_ERROR) JpegLsReadHeader(const void* compressedData, size_t compressedLength,
+ struct JlsParameters* info);
+
+ CHARLS_IMEXPORT(enum JLS_ERROR) JpegLsVerifyEncode(const void* uncompressedData, size_t uncompressedLength,
+ const void* compressedData, size_t compressedLength);
+
+
+#ifdef __cplusplus
+
+}
+ CHARLS_IMEXPORT(enum JLS_ERROR) JpegLsEncodeStream(ByteStreamInfo rawStream, size_t* bytesWritten, ByteStreamInfo inputStream, struct JlsParameters* info);
+ CHARLS_IMEXPORT(enum JLS_ERROR) JpegLsDecodeStream(ByteStreamInfo output, ByteStreamInfo input, struct JlsParameters* info);
+ CHARLS_IMEXPORT(enum JLS_ERROR) JpegLsReadHeaderStream(ByteStreamInfo input, struct JlsParameters* info);
+
+#endif
+
+#endif
diff --git a/src/jpegimagedatasegment.h b/src/jpegimagedatasegment.h
new file mode 100644
index 0000000..65f0361
--- /dev/null
+++ b/src/jpegimagedatasegment.h
@@ -0,0 +1,28 @@
+//
+// (C) CharLS Team 2014, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
+
+#pragma once
+
+#include "util.h"
+#include "jpegsegment.h"
+#include "jpegstreamwriter.h"
+#include <vector>
+
+class JpegImageDataSegment : public JpegSegment
+{
+public:
+ JpegImageDataSegment(ByteStreamInfo rawStream, const JlsParameters& info, int ccompScan) :
+ _ccompScan(ccompScan),
+ _rawStreamInfo(rawStream),
+ _info(info)
+ {
+ }
+
+ void Serialize(JpegStreamWriter& streamWriter);
+
+private:
+ int _ccompScan;
+ ByteStreamInfo _rawStreamInfo;
+ JlsParameters _info;
+};
diff --git a/jpegls.cpp b/src/jpegls.cpp
similarity index 98%
rename from jpegls.cpp
rename to src/jpegls.cpp
index 6a6bcf4..42c1df8 100644
--- a/jpegls.cpp
+++ b/src/jpegls.cpp
@@ -4,7 +4,7 @@
#include "config.h"
#include "util.h"
-#include "streams.h"
+#include "jpegmarker.h"
#include "header.h"
@@ -21,7 +21,6 @@
#include "lookuptable.h"
-signed char* JlsContext::_tableC = CreateTableC();
// As defined in the JPEG-LS standard
diff --git a/src/jpegmarker.h b/src/jpegmarker.h
new file mode 100644
index 0000000..7547597
--- /dev/null
+++ b/src/jpegmarker.h
@@ -0,0 +1,75 @@
+//
+// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
+#ifndef CHARLS_JPEGMARKER
+#define CHARLS_JPEGMARKER
+
+#include <memory>
+#include <vector>
+#include "util.h"
+
+
+// This file defines JPEG-LS markers: The header and the actual pixel data. Header markers have fixed length, the pixeldata not.
+
+
+class JpegSegment;
+
+
+
+ByteStreamInfo FromByteArray(const void* bytes, size_t count);
+ByteStreamInfo FromStream(std::basic_streambuf<char>* stream);
+void SkipBytes(ByteStreamInfo* streamInfo, size_t count);
+
+
+
+//
+// JpegMarkerReader: minimal implementation to read JPEG markers
+//
+class JpegMarkerReader
+{
+public:
+ JpegMarkerReader(ByteStreamInfo byteStreamInfo);
+
+ const JlsParameters& GetMetadata() const
+ { return _info; }
+
+ const JlsCustomParameters& GetCustomPreset() const
+ { return _info.custom; }
+
+ void Read(ByteStreamInfo info);
+ void ReadHeader();
+
+ void EnableCompare(bool bCompare)
+ { _bCompare = bCompare; }
+
+ void SetInfo(JlsParameters* info) { _info = *info; }
+
+ void SetRect(JlsRect rect) { _rect = rect; }
+
+ void ReadStartOfScan(bool firstComponent);
+ BYTE ReadByte();
+
+private:
+ void ReadScan(ByteStreamInfo rawPixels);
+ int ReadPresetParameters();
+ int ReadComment();
+ int ReadStartOfFrame();
+ int ReadWord();
+ void ReadNBytes(std::vector<char>& dst, int byteCount);
+ int ReadMarker(BYTE marker);
+
+ // JFIF
+ void ReadJfif();
+ // Color Transform Application Markers & Code Stream (HP extension)
+ int ReadColorSpace();
+ int ReadColorXForm();
+
+private:
+ ByteStreamInfo _byteStream;
+ bool _bCompare;
+ JlsParameters _info;
+ JlsRect _rect;
+};
+
+
+#endif
diff --git a/src/jpegmarkersegment.cpp b/src/jpegmarkersegment.cpp
new file mode 100644
index 0000000..900b7b1
--- /dev/null
+++ b/src/jpegmarkersegment.cpp
@@ -0,0 +1,120 @@
+//
+// (C) CharLS Team 2014, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
+
+#include "jpegmarkersegment.h"
+#include "header.h"
+#include "util.h"
+#include <vector>
+
+
+JpegMarkerSegment* JpegMarkerSegment::CreateStartOfFrameMarker(Size size, LONG bitsPerSample, LONG ccomp)
+{
+ std::vector<BYTE> vec;
+ vec.push_back(static_cast<BYTE>(bitsPerSample));
+ push_back(vec, static_cast<USHORT>(size.cy));
+ push_back(vec, static_cast<USHORT>(size.cx));
+
+ // components
+ vec.push_back(static_cast<BYTE>(ccomp));
+ for (BYTE component = 0; component < ccomp; component++)
+ {
+ // rescaling
+ vec.push_back(component + 1);
+ vec.push_back(0x11);
+ //"Tq1" reserved, 0
+ vec.push_back(0);
+ }
+
+ return new JpegMarkerSegment(JPEG_SOF_55, vec);
+}
+
+
+JpegMarkerSegment* JpegMarkerSegment::CreateJpegFileInterchangeFormatMarker(const JfifParameters& jfifParameters)
+{
+ BYTE jfifID [] = { 'J', 'F', 'I', 'F', '\0' };
+
+ std::vector<BYTE> rgbyte;
+ for (int i = 0; i < (int)sizeof(jfifID); i++)
+ {
+ rgbyte.push_back(jfifID[i]);
+ }
+
+ push_back(rgbyte, (USHORT) jfifParameters.Ver);
+
+ rgbyte.push_back(jfifParameters.units);
+ push_back(rgbyte, (USHORT) jfifParameters.XDensity);
+ push_back(rgbyte, (USHORT) jfifParameters.YDensity);
+
+ // thumbnail
+ rgbyte.push_back((BYTE) jfifParameters.Xthumb);
+ rgbyte.push_back((BYTE) jfifParameters.Ythumb);
+ if (jfifParameters.Xthumb > 0)
+ {
+ if (jfifParameters.pdataThumbnail)
+ throw JlsException(InvalidJlsParameters);
+
+ rgbyte.insert(rgbyte.end(), (BYTE*) jfifParameters.pdataThumbnail, (BYTE*) jfifParameters.pdataThumbnail + 3 * jfifParameters.Xthumb * jfifParameters.Ythumb);
+ }
+
+ return new JpegMarkerSegment(JPEG_APP0, rgbyte);
+}
+
+
+JpegMarkerSegment* JpegMarkerSegment::CreateJpegLSExtendedParametersMarker(const JlsCustomParameters& customParameters)
+{
+ std::vector<BYTE> rgbyte;
+
+ rgbyte.push_back(1);
+ push_back(rgbyte, (USHORT) customParameters.MAXVAL);
+ push_back(rgbyte, (USHORT) customParameters.T1);
+ push_back(rgbyte, (USHORT) customParameters.T2);
+ push_back(rgbyte, (USHORT) customParameters.T3);
+ push_back(rgbyte, (USHORT) customParameters.RESET);
+
+ return new JpegMarkerSegment(JPEG_LSE, rgbyte);
+}
+
+
+JpegMarkerSegment* JpegMarkerSegment::CreateColorTransformMarker(int i)
+{
+ std::vector<BYTE> rgbyteXform;
+
+ rgbyteXform.push_back('m');
+ rgbyteXform.push_back('r');
+ rgbyteXform.push_back('f');
+ rgbyteXform.push_back('x');
+ rgbyteXform.push_back((BYTE) i);
+
+ return new JpegMarkerSegment(JPEG_APP8, rgbyteXform);
+}
+
+
+JpegMarkerSegment* JpegMarkerSegment::CreateStartOfScanMarker(const JlsParameters* pparams, LONG icomponent)
+{
+ BYTE itable = 0;
+
+ std::vector<BYTE> rgbyte;
+
+ if (icomponent < 0)
+ {
+ rgbyte.push_back((BYTE) pparams->components);
+ for (LONG i = 0; i < pparams->components; ++i)
+ {
+ rgbyte.push_back(BYTE(i + 1));
+ rgbyte.push_back(itable);
+ }
+ }
+ else
+ {
+ rgbyte.push_back(1);
+ rgbyte.push_back((BYTE) icomponent);
+ rgbyte.push_back(itable);
+ }
+
+ rgbyte.push_back(BYTE(pparams->allowedlossyerror));
+ rgbyte.push_back(BYTE(pparams->ilv));
+ rgbyte.push_back(0); // transform
+
+ return new JpegMarkerSegment(JPEG_SOS, rgbyte);
+}
diff --git a/src/jpegmarkersegment.h b/src/jpegmarkersegment.h
new file mode 100644
index 0000000..6e914ef
--- /dev/null
+++ b/src/jpegmarkersegment.h
@@ -0,0 +1,40 @@
+//
+// (C) CharLS Team 2014, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
+
+#pragma once
+
+#include "util.h"
+#include "jpegsegment.h"
+#include "jpegstreamwriter.h"
+#include <vector>
+
+
+class JpegMarkerSegment : public JpegSegment
+{
+public:
+ JpegMarkerSegment(BYTE marker, std::vector<BYTE> vecbyte)
+ {
+ _marker = marker;
+ std::swap(_vecbyte, vecbyte);
+ }
+
+ virtual void Serialize(JpegStreamWriter& streamWriter)
+ {
+ streamWriter.WriteByte(0xFF);
+ streamWriter.WriteByte(_marker);
+ streamWriter.WriteWord(USHORT(_vecbyte.size() + 2));
+ streamWriter.WriteBytes(_vecbyte);
+ }
+
+ static JpegMarkerSegment* CreateStartOfFrameMarker(Size size, LONG bitsPerSample, LONG ccomp);
+ static JpegMarkerSegment* CreateJpegFileInterchangeFormatMarker(const JfifParameters& jfif);
+ static JpegMarkerSegment* CreateJpegLSExtendedParametersMarker(const JlsCustomParameters& pcustom);
+ static JpegMarkerSegment* CreateColorTransformMarker(int i);
+ static JpegMarkerSegment* CreateStartOfScanMarker(const JlsParameters* pparams, LONG icomponent);
+
+private:
+ BYTE _marker;
+ std::vector<BYTE> _vecbyte;
+};
+
diff --git a/src/jpegsegment.h b/src/jpegsegment.h
new file mode 100644
index 0000000..7806a9b
--- /dev/null
+++ b/src/jpegsegment.h
@@ -0,0 +1,22 @@
+//
+// (C) CharLS Team 2014, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
+
+#ifndef CHARLS_JPEGSEGMENT
+#define CHARLS_JPEGSEGMENT
+
+class JpegStreamWriter;
+
+//
+// Purpose: base class for segments that can be written to JPEG streams.
+//
+class JpegSegment
+{
+protected:
+ JpegSegment() {}
+public:
+ virtual ~JpegSegment() {}
+ virtual void Serialize(JpegStreamWriter& streamWriter) = 0;
+};
+
+#endif
diff --git a/src/jpegstreamwriter.cpp b/src/jpegstreamwriter.cpp
new file mode 100644
index 0000000..4d89882
--- /dev/null
+++ b/src/jpegstreamwriter.cpp
@@ -0,0 +1,107 @@
+//
+// (C) CharLS Team 2014, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
+
+
+#include "jpegstreamwriter.h"
+#include "jpegmarkersegment.h"
+#include "jpegimagedatasegment.h"
+#include "header.h"
+#include "util.h"
+#include <vector>
+
+
+namespace
+{
+ bool IsDefault(const JlsCustomParameters* pcustom)
+ {
+ if (pcustom->MAXVAL != 0)
+ return false;
+
+ if (pcustom->T1 != 0)
+ return false;
+
+ if (pcustom->T2 != 0)
+ return false;
+
+ if (pcustom->T3 != 0)
+ return false;
+
+ if (pcustom->RESET != 0)
+ return false;
+
+ return true;
+ }
+}
+
+
+JpegStreamWriter::JpegStreamWriter(const JfifParameters& jfifParameters, Size size, LONG bitsPerSample, LONG ccomp) :
+_bCompare(false),
+_data(),
+_byteOffset(0),
+_lastCompenentIndex(0)
+{
+ if (jfifParameters.Ver)
+ {
+ AddSegment(JpegMarkerSegment::CreateJpegFileInterchangeFormatMarker(jfifParameters));
+ }
+
+ AddSegment(JpegMarkerSegment::CreateStartOfFrameMarker(size, bitsPerSample, ccomp));
+}
+
+
+JpegStreamWriter::~JpegStreamWriter()
+{
+ for (size_t i = 0; i < _segments.size(); ++i)
+ {
+ delete _segments[i];
+ }
+}
+
+
+void JpegStreamWriter::AddColorTransform(int i)
+{
+ AddSegment(JpegMarkerSegment::CreateColorTransformMarker(i));
+}
+
+
+size_t JpegStreamWriter::Write(ByteStreamInfo info)
+{
+ _data = info;
+
+ WriteByte(0xFF);
+ WriteByte(JPEG_SOI);
+
+ for (size_t i = 0; i < _segments.size(); ++i)
+ {
+ _segments[i]->Serialize(*this);
+ }
+
+ //_bCompare = false;
+
+ WriteByte(0xFF);
+ WriteByte(JPEG_EOI);
+
+ return _byteOffset;
+}
+
+
+void JpegStreamWriter::AddScan(ByteStreamInfo info, const JlsParameters* pparams)
+{
+ if (!IsDefault(&pparams->custom))
+ {
+ AddSegment(JpegMarkerSegment::CreateJpegLSExtendedParametersMarker(pparams->custom));
+ }
+ else if (pparams->bitspersample > 12)
+ {
+ JlsCustomParameters preset = ComputeDefault((1 << pparams->bitspersample) - 1, pparams->allowedlossyerror);
+ AddSegment(JpegMarkerSegment::CreateJpegLSExtendedParametersMarker(preset));
+ }
+
+ _lastCompenentIndex += 1;
+ AddSegment(JpegMarkerSegment::CreateStartOfScanMarker(pparams, pparams->ilv == ILV_NONE ? _lastCompenentIndex : -1));
+
+ int ccomp = pparams->ilv == ILV_NONE ? 1 : pparams->components;
+
+ AddSegment(new JpegImageDataSegment(info, *pparams, ccomp));
+}
diff --git a/src/jpegstreamwriter.h b/src/jpegstreamwriter.h
new file mode 100644
index 0000000..d0ebd49
--- /dev/null
+++ b/src/jpegstreamwriter.h
@@ -0,0 +1,114 @@
+//
+// (C) CharLS Team 2014, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
+
+#ifndef CHARLS_JPEGSTREAMWRITER
+#define CHARLS_JPEGSTREAMWRITER
+
+#include "util.h"
+#include "jpegsegment.h"
+#include <vector>
+
+
+//
+// Purpose: 'Writer'class that can generate JPEG-LS file streams.
+//
+class JpegStreamWriter
+{
+ friend class JpegMarkerSegment;
+ friend class JpegImageDataSegment;
+
+public:
+ JpegStreamWriter(const JfifParameters& jfifParameters, Size size, LONG bitsPerSample, LONG ccomp);
+ virtual ~JpegStreamWriter();
+
+ void AddSegment(JpegSegment* segment)
+ {
+ _segments.push_back(segment);
+ }
+
+ void AddScan(ByteStreamInfo info, const JlsParameters* pparams);
+
+ void AddLSE(const JlsCustomParameters* pcustom);
+
+ void AddColorTransform(int i);
+
+ size_t GetBytesWritten()
+ {
+ return _byteOffset;
+ }
+
+ size_t GetLength()
+ {
+ return _data.count - _byteOffset;
+ }
+
+ size_t Write(ByteStreamInfo info);
+
+ void EnableCompare(bool bCompare)
+ {
+ _bCompare = bCompare;
+ }
+
+private:
+ BYTE* GetPos() const
+ {
+ return _data.rawData + _byteOffset;
+ }
+
+ ByteStreamInfo OutputStream() const
+ {
+ ByteStreamInfo data = _data;
+ data.count -= _byteOffset;
+ data.rawData += _byteOffset;
+ return data;
+ }
+
+ void WriteByte(BYTE val)
+ {
+ ASSERT(!_bCompare || _data.rawData[_byteOffset] == val);
+
+ if (_data.rawStream != NULL)
+ {
+ _data.rawStream->sputc(val);
+ }
+ else
+ {
+ if (_byteOffset >= _data.count)
+ throw JlsException(CompressedBufferTooSmall);
+
+ _data.rawData[_byteOffset++] = val;
+ }
+ }
+
+ void WriteBytes(const std::vector<BYTE>& rgbyte)
+ {
+ for (size_t i = 0; i < rgbyte.size(); ++i)
+ {
+ WriteByte(rgbyte[i]);
+ }
+ }
+
+ void WriteWord(USHORT val)
+ {
+ WriteByte(BYTE(val / 0x100));
+ WriteByte(BYTE(val % 0x100));
+ }
+
+ void Seek(size_t byteCount)
+ {
+ if (_data.rawStream != NULL)
+ return;
+
+ _byteOffset += byteCount;
+ }
+
+private:
+ bool _bCompare;
+ ByteStreamInfo _data;
+ size_t _byteOffset;
+ LONG _lastCompenentIndex;
+ std::vector<JpegSegment*> _segments;
+};
+
+#endif
diff --git a/lookuptable.h b/src/lookuptable.h
similarity index 100%
rename from lookuptable.h
rename to src/lookuptable.h
diff --git a/losslesstraits.h b/src/losslesstraits.h
similarity index 100%
rename from losslesstraits.h
rename to src/losslesstraits.h
diff --git a/src/processline.h b/src/processline.h
new file mode 100644
index 0000000..ab96b2e
--- /dev/null
+++ b/src/processline.h
@@ -0,0 +1,346 @@
+//
+// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
+#ifndef CHARLS_PROCESSLINE
+#define CHARLS_PROCESSLINE
+
+#include "colortransform.h"
+#include <iostream>
+#include <vector>
+
+#ifdef _MSC_VER
+#pragma warning(disable: 4996) // disable 'function': was declared deprecated also 'std::<function name>': Function call with parameters that may be unsafe
+#endif
+
+//
+// This file defines the ProcessLine base class, its derivitives and helper functions.
+// During coding/decoding, CharLS process one line at a time. The different Processline implementations
+// convert the uncompressed format to and from the internal format for encoding.
+// Conversions include color transforms, line interleaved vs sample interleaved, masking out unused bits,
+// accounting for line padding etc.
+// This mechanism could be used to encode/decode images as they are received.
+//
+
+class ProcessLine
+{
+public:
+ virtual ~ProcessLine() {}
+ virtual void NewLineDecoded(const void* pSrc, int pixelCount, int sourceStride) = 0;
+ virtual void NewLineRequested(void* pDest, int pixelCount, int destStride) = 0;
+};
+
+
+class PostProcesSingleComponent : public ProcessLine
+{
+public:
+ PostProcesSingleComponent(void* rawData, const JlsParameters& info, int bytesPerPixel) :
+ _rawData((BYTE*)rawData),
+ _bytesPerPixel(bytesPerPixel),
+ _bytesPerLine(info.bytesperline)
+ {
+ }
+
+ void NewLineRequested(void* dest, int pixelCount, int /*byteStride*/)
+ {
+ ::memcpy(dest, _rawData, pixelCount * _bytesPerPixel);
+ _rawData += _bytesPerLine;
+ }
+
+ void NewLineDecoded(const void* pSrc, int pixelCount, int /*sourceStride*/)
+ {
+ ::memcpy(_rawData, pSrc, pixelCount * _bytesPerPixel);
+ _rawData += _bytesPerLine;
+ }
+
+private:
+ BYTE* _rawData;
+ int _bytesPerPixel;
+ int _bytesPerLine;
+};
+
+
+inline void ByteSwap(unsigned char* data, int count)
+{
+ if (count & 1)
+ throw JlsException(InvalidJlsParameters);
+
+ unsigned int* data32 = (unsigned int*)data;
+ for(int i = 0; i < count/4; i++)
+ {
+ unsigned int value = data32[i];
+ data32[i] = ((value >> 8) & 0x00FF00FF) | ((value & 0x00FF00FF) << 8);
+ }
+
+ if ((count % 4) != 0)
+ {
+ std::swap(data[count-2], data[count-1]);
+ }
+}
+
+class PostProcesSingleStream : public ProcessLine
+{
+public:
+ PostProcesSingleStream(std::basic_streambuf<char>* rawData, const JlsParameters& info, int bytesPerPixel) :
+ _rawData(rawData),
+ _bytesPerPixel(bytesPerPixel),
+ _bytesPerLine(info.bytesperline)
+ {
+ }
+
+ void NewLineRequested(void* dest, int pixelCount, int /*destStride*/)
+ {
+ size_t bytesToRead = pixelCount * _bytesPerPixel;
+ while (bytesToRead != 0)
+ {
+ std::streamsize bytesRead = _rawData->sgetn((char*)dest, bytesToRead);
+ if (bytesRead == 0)
+ throw JlsException(UncompressedBufferTooSmall);
+
+ bytesToRead = (size_t)(bytesToRead - bytesRead);
+ }
+
+ if (_bytesPerPixel == 2 )
+ {
+ ByteSwap((unsigned char*)dest, 2 * pixelCount);
+ }
+
+ if (_bytesPerLine - pixelCount * _bytesPerPixel > 0)
+ {
+ _rawData->pubseekoff(std::streamoff(_bytesPerLine - bytesToRead), std::ios_base::cur);
+ }
+ }
+
+ void NewLineDecoded(const void* pSrc, int pixelCount, int /*sourceStride*/)
+ {
+ int bytesToWrite = pixelCount * _bytesPerPixel;
+ std::streamsize bytesWritten = _rawData->sputn((const char*)pSrc, bytesToWrite);
+ if (bytesWritten != bytesToWrite)
+ throw JlsException(UncompressedBufferTooSmall);
+ }
+
+private:
+ std::basic_streambuf<char>* _rawData;
+ int _bytesPerPixel;
+ int _bytesPerLine;
+};
+
+
+template<class TRANSFORM, class SAMPLE>
+void TransformLineToQuad(const SAMPLE* ptypeInput, LONG pixelStrideIn, Quad<SAMPLE>* pbyteBuffer, LONG pixelStride, TRANSFORM& transform)
+{
+ int cpixel = MIN(pixelStride, pixelStrideIn);
+ Quad<SAMPLE>* ptypeBuffer = (Quad<SAMPLE>*)pbyteBuffer;
+
+ for (int x = 0; x < cpixel; ++x)
+ {
+ Quad<SAMPLE> pixel(transform(ptypeInput[x], ptypeInput[x + pixelStrideIn], ptypeInput[x + 2*pixelStrideIn]),ptypeInput[x + 3*pixelStrideIn]) ;
+
+ ptypeBuffer[x] = pixel;
+ }
+}
+
+
+template<class TRANSFORM, class SAMPLE>
+void TransformQuadToLine(const Quad<SAMPLE>* pbyteInput, LONG pixelStrideIn, SAMPLE* ptypeBuffer, LONG pixelStride, TRANSFORM& transform)
+{
+ int cpixel = MIN(pixelStride, pixelStrideIn);
+ const Quad<SAMPLE>* ptypeBufferIn = (Quad<SAMPLE>*)pbyteInput;
+
+ for (int x = 0; x < cpixel; ++x)
+ {
+ Quad<SAMPLE> color = ptypeBufferIn[x];
+ Quad<SAMPLE> colorTranformed(transform(color.v1, color.v2, color.v3), color.v4);
+
+ ptypeBuffer[x] = colorTranformed.v1;
+ ptypeBuffer[x + pixelStride] = colorTranformed.v2;
+ ptypeBuffer[x + 2 *pixelStride] = colorTranformed.v3;
+ ptypeBuffer[x + 3 *pixelStride] = colorTranformed.v4;
+ }
+}
+
+
+template<class SAMPLE>
+void TransformRgbToBgr(SAMPLE* pDest, int samplesPerPixel, int pixelCount)
+{
+ for (int i = 0; i < pixelCount; ++i)
+ {
+ std::swap(pDest[0], pDest[2]);
+ pDest += samplesPerPixel;
+ }
+}
+
+
+template<class TRANSFORM, class SAMPLE>
+void TransformLine(Triplet<SAMPLE>* pDest, const Triplet<SAMPLE>* pSrc, int pixelCount, TRANSFORM& transform)
+{
+ for (int i = 0; i < pixelCount; ++i)
+ {
+ pDest[i] = transform(pSrc[i].v1, pSrc[i].v2, pSrc[i].v3);
+ }
+}
+
+
+template<class TRANSFORM, class SAMPLE>
+void TransformLineToTriplet(const SAMPLE* ptypeInput, LONG pixelStrideIn, Triplet<SAMPLE>* pbyteBuffer, LONG pixelStride, TRANSFORM& transform)
+{
+ int cpixel = MIN(pixelStride, pixelStrideIn);
+ Triplet<SAMPLE>* ptypeBuffer = (Triplet<SAMPLE>*)pbyteBuffer;
+
+ for (int x = 0; x < cpixel; ++x)
+ {
+ ptypeBuffer[x] = transform(ptypeInput[x], ptypeInput[x + pixelStrideIn], ptypeInput[x + 2*pixelStrideIn]);
+ }
+}
+
+
+template<class TRANSFORM, class SAMPLE>
+void TransformTripletToLine(const Triplet<SAMPLE>* pbyteInput, LONG pixelStrideIn, SAMPLE* ptypeBuffer, LONG pixelStride, TRANSFORM& transform)
+{
+ int cpixel = MIN(pixelStride, pixelStrideIn);
+ const Triplet<SAMPLE>* ptypeBufferIn = (Triplet<SAMPLE>*)pbyteInput;
+
+ for (int x = 0; x < cpixel; ++x)
+ {
+ Triplet<SAMPLE> color = ptypeBufferIn[x];
+ Triplet<SAMPLE> colorTranformed = transform(color.v1, color.v2, color.v3);
+
+ ptypeBuffer[x] = colorTranformed.v1;
+ ptypeBuffer[x + pixelStride] = colorTranformed.v2;
+ ptypeBuffer[x + 2 *pixelStride] = colorTranformed.v3;
+ }
+}
+
+
+template<class TRANSFORM>
+class ProcessTransformed : public ProcessLine
+{
+ typedef typename TRANSFORM::SAMPLE SAMPLE;
+
+public:
+ ProcessTransformed(ByteStreamInfo rawStream, const JlsParameters& info, TRANSFORM transform) :
+ _info(info),
+ _templine(info.width * info.components),
+ _buffer(info.width * info.components * sizeof(SAMPLE)),
+ _transform(transform),
+ _inverseTransform(transform),
+ _rawPixels(rawStream)
+ {
+ }
+
+ void NewLineRequested(void* dest, int pixelCount, int destStride)
+ {
+ if (_rawPixels.rawStream == NULL)
+ {
+ Transform(_rawPixels.rawData, dest, pixelCount, destStride);
+ _rawPixels.rawData += _info.bytesperline;
+ return;
+ }
+
+ Transform(_rawPixels.rawStream, dest, pixelCount, destStride);
+ }
+
+ void Transform(std::basic_streambuf<char>* rawStream, void* dest, int pixelCount, int destStride)
+ {
+ std::streamsize bytesToRead = pixelCount * _info.components * sizeof(SAMPLE);
+ while(bytesToRead != 0)
+ {
+ std::streamsize read = rawStream->sgetn((char*)&_buffer[0], bytesToRead);
+ if (read == 0)
+ throw new JlsException(UncompressedBufferTooSmall);
+
+ bytesToRead -= read;
+ }
+ if (sizeof(SAMPLE) == 2 && _info.colorTransform == XFORM_BIGENDIAN)
+ {
+ ByteSwap(&_buffer[0], _info.components * sizeof(SAMPLE) * pixelCount);
+ }
+ Transform(&_buffer[0], dest, pixelCount, destStride);
+ }
+
+ void Transform(const void* source, void* dest, int pixelCount, int destStride)
+ {
+ if (_info.outputBgr)
+ {
+ memcpy(&_templine[0], source, sizeof(Triplet<SAMPLE>)*pixelCount);
+ TransformRgbToBgr((SAMPLE*)&_templine[0], _info.components, pixelCount);
+ source = &_templine[0];
+ }
+
+ if (_info.components == 3)
+ {
+ if (_info.ilv == ILV_SAMPLE)
+ {
+ TransformLine((Triplet<SAMPLE>*)dest, (const Triplet<SAMPLE>*)source, pixelCount, _transform);
+ }
+ else
+ {
+ TransformTripletToLine((const Triplet<SAMPLE>*)source, pixelCount, (SAMPLE*)dest, destStride, _transform);
+ }
+ }
+ else if (_info.components == 4 && _info.ilv == ILV_LINE)
+ {
+ TransformQuadToLine((const Quad<SAMPLE>*)source, pixelCount, (SAMPLE*)dest, destStride, _transform);
+ }
+ }
+
+
+ void DecodeTransform(const void* pSrc, void* rawData, int pixelCount, int byteStride)
+ {
+ if (_info.components == 3)
+ {
+ if (_info.ilv == ILV_SAMPLE)
+ {
+ TransformLine((Triplet<SAMPLE>*)rawData, (const Triplet<SAMPLE>*)pSrc, pixelCount, _inverseTransform);
+ }
+ else
+ {
+ TransformLineToTriplet((const SAMPLE*)pSrc, byteStride, (Triplet<SAMPLE>*)rawData, pixelCount, _inverseTransform);
+ }
+ }
+ else if (_info.components == 4 && _info.ilv == ILV_LINE)
+ {
+ TransformLineToQuad((const SAMPLE*)pSrc, byteStride, (Quad<SAMPLE>*)rawData, pixelCount, _inverseTransform);
+ }
+
+ if (_info.outputBgr)
+ {
+ TransformRgbToBgr((SAMPLE*)rawData, _info.components, pixelCount);
+ }
+ }
+
+ void NewLineDecoded(const void* pSrc, int pixelCount, int sourceStride)
+ {
+ if (_rawPixels.rawStream != NULL)
+ {
+ std::streamsize bytesToWrite = pixelCount * _info.components * sizeof(SAMPLE);
+ DecodeTransform(pSrc, &_buffer[0], pixelCount, sourceStride);
+
+ if (sizeof(SAMPLE) == 2 && _info.colorTransform == XFORM_BIGENDIAN)
+ {
+ ByteSwap(&_buffer[0], _info.components * sizeof(SAMPLE) * pixelCount);
+ }
+
+ std::streamsize bytesWritten = _rawPixels.rawStream->sputn((char*)&_buffer[0], bytesToWrite);
+ if (bytesWritten != bytesToWrite)
+ throw JlsException(UncompressedBufferTooSmall);
+ }
+ else
+ {
+ DecodeTransform(pSrc, _rawPixels.rawData, pixelCount, sourceStride);
+ _rawPixels.rawData += _info.bytesperline;
+ }
+ }
+
+
+private:
+ const JlsParameters& _info;
+ std::vector<SAMPLE> _templine;
+ std::vector<BYTE> _buffer;
+ TRANSFORM _transform;
+ typename TRANSFORM::INVERSE _inverseTransform;
+ ByteStreamInfo _rawPixels;
+};
+
+
+
+#endif
diff --git a/src/publictypes.h b/src/publictypes.h
new file mode 100644
index 0000000..80e3ba6
--- /dev/null
+++ b/src/publictypes.h
@@ -0,0 +1,137 @@
+/*
+ (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
+*/
+#ifndef CHARLS_PUBLICTYPES
+#define CHARLS_PUBLICTYPES
+
+#include "config.h"
+
+#ifdef __cplusplus
+#include <iostream>
+#include <cstddef>
+#endif
+
+enum JLS_ERROR
+{
+ OK = 0,
+ InvalidJlsParameters,
+ ParameterValueNotSupported,
+ UncompressedBufferTooSmall,
+ CompressedBufferTooSmall,
+ InvalidCompressedData, // This error is returned when the encoded bit stream contains a general structural problem.
+ TooMuchCompressedData,
+ ImageTypeNotSupported, // This error is returned when the bit stream is encoded with an option that is not supported by this implementation.
+ UnsupportedBitDepthForTransform,
+ UnsupportedColorTransform,
+ UnsupportedEncoding, // This error is returned when an encoded frame is found that is not encoded with the JPEG-LS algorithm.
+ UnknownJpegMarker, // This error is returned when an unknown JPEG marker code is detected in the encoded bit stream.
+ MissingJpegMarkerStart // This error is returned when the algorithm expect a 0xFF code (indicates start of a JPEG marker) but none was found.
+};
+
+
+enum interleavemode
+{
+ ILV_NONE = 0,
+ ILV_LINE = 1,
+ ILV_SAMPLE = 2
+};
+
+
+
+struct JlsCustomParameters
+{
+ int MAXVAL;
+ int T1;
+ int T2;
+ int T3;
+ int RESET;
+};
+
+
+struct JlsRect
+{
+ int X, Y;
+ int Width, Height;
+};
+
+
+struct JfifParameters
+{
+ int Ver;
+ char units;
+ int XDensity;
+ int YDensity;
+ short Xthumb;
+ short Ythumb;
+ void* pdataThumbnail; /* user must set buffer which size is Xthumb*Ythumb*3(RGB) before JpegLsDecode() */
+};
+
+
+struct JlsParameters
+{
+ int width;
+ int height;
+ int bitspersample;
+ int bytesperline; /* for [source (at encoding)][decoded (at decoding)] pixel image in user buffer */
+ int components;
+ int allowedlossyerror;
+ enum interleavemode ilv;
+ int colorTransform;
+ char outputBgr;
+ struct JlsCustomParameters custom;
+ struct JfifParameters jfif;
+};
+
+
+
+enum JPEGLS_ColorXForm
+{
+ // default (RGB)
+ COLORXFORM_NONE = 0,
+
+ // Color transforms as defined by HP
+ // Not part of the JPEG-LS standard in any way, provided for compatibility with existing streams.
+ COLORXFORM_HP1,
+ COLORXFORM_HP2,
+ COLORXFORM_HP3,
+
+ // Defined by HP but not supported by CharLS
+ COLORXFORM_RGB_AS_YUV_LOSSY,
+ COLORXFORM_MATRIX,
+ XFORM_BIGENDIAN = 1 << 29,
+ XFORM_LITTLEENDIAN = 1 << 30
+};
+
+
+#ifdef __cplusplus
+
+//
+// ByteStreamInfo & FromByteArray helper function
+//
+// ByteStreamInfo describes the stream: either set rawStream to a valid stream, or rawData/count, not both.
+// it's possible to decode to memorystreams, but using rawData will always be faster.
+//
+// Example use:
+// ByteStreamInfo streamInfo = { fileStream.rdbuf() };
+// or
+// ByteStreamInfo streamInfo = FromByteArray( bytePtr, byteCount);
+//
+struct ByteStreamInfo
+{
+ std::basic_streambuf<char>* rawStream;
+ BYTE* rawData;
+ std::size_t count;
+};
+
+
+inline ByteStreamInfo FromByteArray(const void* bytes, std::size_t count)
+{
+ ByteStreamInfo info = ByteStreamInfo();
+ info.rawData = (BYTE*)bytes;
+ info.count = count;
+ return info;
+}
+
+#endif
+
+#endif
diff --git a/scan.h b/src/scan.h
similarity index 82%
rename from scan.h
rename to src/scan.h
index 2500420..2c445e6 100644
--- a/scan.h
+++ b/src/scan.h
@@ -6,8 +6,9 @@
#define CHARLS_SCAN
#include "lookuptable.h"
+#include <cstdlib>
-// This file contains the code for handling a "scan". Usually an image is encoded as a single scan.
+// This file contains the code for handling a "scan". Usually an image is encoded as a single scan.
#ifdef _MSC_VER
@@ -24,7 +25,7 @@ extern std::vector<signed char> rgquant16Ll;
// Apply
//
inlinehint LONG ApplySign(LONG i, LONG sign)
-{ return (sign ^ i) - sign; }
+{ return (sign ^ i) - sign; }
@@ -65,7 +66,7 @@ inlinehint LONG GetPredictedValue(LONG Ra, LONG Rb, LONG Rc)
if ((sgn ^ (Rc - Ra)) < 0)
{
return Rb;
- }
+ }
else if ((sgn ^ (Rb - Rc)) < 0)
{
return Ra;
@@ -113,7 +114,7 @@ public:
JlsCodec(const TRAITS& inTraits, const JlsParameters& info) : STRATEGY(info),
traits(inTraits),
_rect(),
- _width(0),
+ _width(info.width),
T1(0),
T2(0),
T3(0),
@@ -187,22 +188,22 @@ public:
void DoLine(SAMPLE* pdummy);
void DoLine(Triplet<SAMPLE>* pdummy);
- void DoScan(BYTE* compressedBytes, size_t compressedLength);
+ void DoScan();
public:
- ProcessLine* CreateProcess(void* pvoidOut);
+ ProcessLine* CreateProcess(ByteStreamInfo rawStreamInfo);
void InitDefault();
void InitParams(LONG t1, LONG t2, LONG t3, LONG nReset);
- size_t EncodeScan(const void* rawData, void* pvoidOut, size_t compressedLength, void* pvoidCompare);
- size_t DecodeScan(void* rawData, const JlsRect& size, const void* compressedData, size_t compressedLength, bool bCompare);
+ size_t EncodeScan(std::auto_ptr<ProcessLine> rawData, ByteStreamInfo* compressedData, void* pvoidCompare);
+ void DecodeScan(std::auto_ptr<ProcessLine> rawData, const JlsRect& size, ByteStreamInfo* compressedData, bool bCompare);
protected:
// codec parameters
TRAITS traits;
JlsRect _rect;
int _width;
- LONG T1;
+ LONG T1;
LONG T2;
LONG T3;
@@ -213,7 +214,6 @@ protected:
PIXEL* _previousLine; // previous line ptr
PIXEL* _currentLine; // current line ptr
-
// quantization lookup table
signed char* _pquant;
std::vector<signed char> _rgquant;
@@ -227,7 +227,7 @@ protected:
template<class TRAITS, class STRATEGY>
typename TRAITS::SAMPLE JlsCodec<TRAITS,STRATEGY>::DoRegular(LONG Qs, LONG, LONG pred, DecoderStrategy*)
-{
+{
LONG sign = BitWiseSign(Qs);
JlsContext& ctx = _contexts[ApplySign(Qs, sign)];
LONG k = ctx.GetGolomb();
@@ -239,15 +239,18 @@ typename TRAITS::SAMPLE JlsCodec<TRAITS,STRATEGY>::DoRegular(LONG Qs, LONG, LONG
{
STRATEGY::Skip(code.GetLength());
ErrVal = code.GetValue();
- ASSERT(abs(ErrVal) < 65535);
+ ASSERT(std::abs(ErrVal) < 65535);
}
else
{
ErrVal = UnMapErrVal(DecodeValue(k, traits.LIMIT, traits.qbpp));
- if (abs(ErrVal) > 65535)
+ if (std::abs(ErrVal) > 65535)
throw JlsException(InvalidCompressedData);
- }
- ErrVal = ErrVal ^ ((traits.NEAR == 0) ? ctx.GetErrorCorrection(k) : 0);
+ }
+ if (k == 0)
+ {
+ ErrVal = ErrVal ^ ctx.GetErrorCorrection(traits.NEAR);
+ }
ctx.UpdateVariables(ErrVal, traits.NEAR, traits.RESET);
ErrVal = ApplySign(ErrVal, sign);
return traits.ComputeReconstructedSample(Px, ErrVal);
@@ -260,7 +263,7 @@ typename TRAITS::SAMPLE JlsCodec<TRAITS,STRATEGY>::DoRegular(LONG Qs, LONG x, LO
LONG sign = BitWiseSign(Qs);
JlsContext& ctx = _contexts[ApplySign(Qs, sign)];
LONG k = ctx.GetGolomb();
- LONG Px = traits.CorrectPrediction(pred + ApplySign(ctx.C, sign));
+ LONG Px = traits.CorrectPrediction(pred + ApplySign(ctx.C, sign));
LONG ErrVal = traits.ComputeErrVal(ApplySign(x - Px, sign));
@@ -339,7 +342,7 @@ inlinehint void JlsCodec<TRAITS,STRATEGY>::EncodeMappedValue(LONG k, LONG mapped
if (highbits + 1 > 31)
{
STRATEGY::AppendToBitStream(0, highbits / 2);
- highbits = highbits - highbits / 2;
+ highbits = highbits - highbits / 2;
}
STRATEGY::AppendToBitStream(1, highbits + 1);
STRATEGY::AppendToBitStream((mappedError & ((1 << k) - 1)), k);
@@ -349,48 +352,54 @@ inlinehint void JlsCodec<TRAITS,STRATEGY>::EncodeMappedValue(LONG k, LONG mapped
if (limit - traits.qbpp > 31)
{
STRATEGY::AppendToBitStream(0, 31);
- STRATEGY::AppendToBitStream(1, limit - traits.qbpp - 31);
+ STRATEGY::AppendToBitStream(1, limit - traits.qbpp - 31);
}
else
{
- STRATEGY::AppendToBitStream(1, limit - traits.qbpp);
+ STRATEGY::AppendToBitStream(1, limit - traits.qbpp);
}
STRATEGY::AppendToBitStream((mappedError - 1) & ((1 << traits.qbpp) - 1), traits.qbpp);
}
+// Disable the Microsoft Static Analyzer warning: Potential comparison of a constant with another constant. (false warning, triggered by template construction)
+#ifdef _PREFAST_
+#pragma warning(push)
+#pragma warning(disable:6326)
+#endif
+
// Sets up a lookup table to "Quantize" sample difference.
template<class TRAITS, class STRATEGY>
void JlsCodec<TRAITS,STRATEGY>::InitQuantizationLUT()
{
- // for lossless mode with default parameters, we have precomputed te luts for bitcounts 8,10,12 and 16
+ // for lossless mode with default parameters, we have precomputed the luts for bitcounts 8,10,12 and 16.
if (traits.NEAR == 0 && traits.MAXVAL == (1 << traits.bpp) - 1)
{
JlsCustomParameters presets = ComputeDefault(traits.MAXVAL, traits.NEAR);
if (presets.T1 == T1 && presets.T2 == T2 && presets.T3 == T3)
{
- if (traits.bpp == 8)
+ if (traits.bpp == 8)
{
- _pquant = &rgquant8Ll[rgquant8Ll.size() / 2 ];
+ _pquant = &rgquant8Ll[rgquant8Ll.size() / 2 ];
return;
}
- if (traits.bpp == 10)
+ if (traits.bpp == 10)
{
- _pquant = &rgquant10Ll[rgquant10Ll.size() / 2 ];
+ _pquant = &rgquant10Ll[rgquant10Ll.size() / 2 ];
return;
- }
- if (traits.bpp == 12)
+ }
+ if (traits.bpp == 12)
{
- _pquant = &rgquant12Ll[rgquant12Ll.size() / 2 ];
+ _pquant = &rgquant12Ll[rgquant12Ll.size() / 2 ];
return;
- }
- if (traits.bpp == 16)
+ }
+ if (traits.bpp == 16)
{
- _pquant = &rgquant16Ll[rgquant16Ll.size() / 2 ];
+ _pquant = &rgquant16Ll[rgquant16Ll.size() / 2 ];
return;
- }
- }
+ }
+ }
}
LONG RANGE = 1 << traits.bpp;
@@ -404,6 +413,9 @@ void JlsCodec<TRAITS,STRATEGY>::InitQuantizationLUT()
}
}
+#ifdef _PREFAST_
+#pragma warning(pop)
+#endif
template<class TRAITS, class STRATEGY>
signed char JlsCodec<TRAITS,STRATEGY>::QuantizeGratientOrg(LONG Di)
@@ -428,20 +440,19 @@ template<class TRAITS, class STRATEGY>
LONG JlsCodec<TRAITS,STRATEGY>::DecodeRIError(CContextRunMode& ctx)
{
LONG k = ctx.GetGolomb();
- LONG EMErrval = DecodeValue(k, traits.LIMIT - J[_RUNindex]-1, traits.qbpp);
+ LONG EMErrval = DecodeValue(k, traits.LIMIT - J[_RUNindex]-1, traits.qbpp);
LONG Errval = ctx.ComputeErrVal(EMErrval + ctx._nRItype, k);
ctx.UpdateVariables(Errval, EMErrval);
return Errval;
}
-
template<class TRAITS, class STRATEGY>
void JlsCodec<TRAITS,STRATEGY>::EncodeRIError(CContextRunMode& ctx, LONG Errval)
{
LONG k = ctx.GetGolomb();
bool map = ctx.ComputeMap(Errval, k);
- LONG EMErrval = 2 * abs(Errval) - ctx._nRItype - map;
+ LONG EMErrval = 2 * std::abs(Errval) - ctx._nRItype - LONG(map);
ASSERT(Errval == ctx.ComputeErrVal(EMErrval + ctx._nRItype, k));
EncodeMappedValue(k, EMErrval, traits.LIMIT-J[_RUNindex]-1);
@@ -475,25 +486,23 @@ Triplet<typename TRAITS::SAMPLE> JlsCodec<TRAITS,STRATEGY>::EncodeRIPixel(Triple
LONG errval3 = traits.ComputeErrVal(Sign(Rb.v3 - Ra.v3) * (x.v3 - Rb.v3));
EncodeRIError(_contextRunmode[0], errval3);
-
return Triplet<SAMPLE>(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)));
}
-
template<class TRAITS, class STRATEGY>
typename TRAITS::SAMPLE JlsCodec<TRAITS,STRATEGY>::DecodeRIPixel(LONG Ra, LONG Rb)
{
- if (abs(Ra - Rb) <= traits.NEAR)
+ if (std::abs(Ra - Rb) <= traits.NEAR)
{
- LONG ErrVal = DecodeRIError(_contextRunmode[1]);
+ LONG ErrVal = DecodeRIError(_contextRunmode[1]);
return static_cast<SAMPLE>(traits.ComputeReconstructedSample(Ra, ErrVal));
}
else
{
- LONG ErrVal = DecodeRIError(_contextRunmode[0]);
+ LONG ErrVal = DecodeRIError(_contextRunmode[0]);
return static_cast<SAMPLE>(traits.ComputeReconstructedSample(Rb, ErrVal * Sign(Rb - Ra)));
}
}
@@ -502,7 +511,7 @@ typename TRAITS::SAMPLE JlsCodec<TRAITS,STRATEGY>::DecodeRIPixel(LONG Ra, LONG R
template<class TRAITS, class STRATEGY>
typename TRAITS::SAMPLE JlsCodec<TRAITS,STRATEGY>::EncodeRIPixel(LONG x, LONG Ra, LONG Rb)
{
- if (abs(Ra - Rb) <= traits.NEAR)
+ if (std::abs(Ra - Rb) <= traits.NEAR)
{
LONG ErrVal = traits.ComputeErrVal(x - Ra);
EncodeRIError(_contextRunmode[1], ErrVal);
@@ -562,7 +571,6 @@ LONG JlsCodec<TRAITS,STRATEGY>::DecodeRunPixels(PIXEL Ra, PIXEL* startPos, LONG
break;
}
-
if (index != cpixelMac)
{
// incomplete run
@@ -575,7 +583,7 @@ LONG JlsCodec<TRAITS,STRATEGY>::DecodeRunPixels(PIXEL Ra, PIXEL* startPos, LONG
for (LONG i = 0; i < index; ++i)
{
startPos[i] = Ra;
- }
+ }
return index;
}
@@ -640,7 +648,7 @@ void JlsCodec<TRAITS,STRATEGY>::DoLine(SAMPLE*)
LONG Rd = _previousLine[index];
while(index < _width)
- {
+ {
LONG Ra = _currentLine[index -1];
LONG Rc = Rb;
Rb = Rd;
@@ -650,15 +658,15 @@ void JlsCodec<TRAITS,STRATEGY>::DoLine(SAMPLE*)
if (Qs != 0)
{
- _currentLine[index] = DoRegular(Qs, _currentLine[index], GetPredictedValue(Ra, Rb, Rc), (STRATEGY*)(NULL));
+ _currentLine[index] = DoRegular(Qs, _currentLine[index], GetPredictedValue(Ra, Rb, Rc), static_cast<STRATEGY*>(NULL));
index++;
}
else
{
- index += DoRunMode(index, (STRATEGY*)(NULL));
+ index += DoRunMode(index, static_cast<STRATEGY*>(NULL));
Rb = _previousLine[index-1];
- Rd = _previousLine[index];
- }
+ Rd = _previousLine[index];
+ }
}
}
@@ -683,17 +691,17 @@ void JlsCodec<TRAITS,STRATEGY>::DoLine(Triplet<SAMPLE>*)
if (Qs1 == 0 && Qs2 == 0 && Qs3 == 0)
{
- index += DoRunMode(index, (STRATEGY*)(NULL));
+ index += DoRunMode(index, static_cast<STRATEGY*>(NULL));
}
else
{
Triplet<SAMPLE> Rx;
- Rx.v1 = DoRegular(Qs1, _currentLine[index].v1, GetPredictedValue(Ra.v1, Rb.v1, Rc.v1), (STRATEGY*)(NULL));
- Rx.v2 = DoRegular(Qs2, _currentLine[index].v2, GetPredictedValue(Ra.v2, Rb.v2, Rc.v2), (STRATEGY*)(NULL));
- Rx.v3 = DoRegular(Qs3, _currentLine[index].v3, GetPredictedValue(Ra.v3, Rb.v3, Rc.v3), (STRATEGY*)(NULL));
+ Rx.v1 = DoRegular(Qs1, _currentLine[index].v1, GetPredictedValue(Ra.v1, Rb.v1, Rc.v1), static_cast<STRATEGY*>(NULL));
+ Rx.v2 = DoRegular(Qs2, _currentLine[index].v2, GetPredictedValue(Ra.v2, Rb.v2, Rc.v2), static_cast<STRATEGY*>(NULL));
+ Rx.v3 = DoRegular(Qs3, _currentLine[index].v3, GetPredictedValue(Ra.v3, Rb.v3, Rc.v3), static_cast<STRATEGY*>(NULL));
_currentLine[index] = Rx;
index++;
- }
+ }
}
}
@@ -704,22 +712,18 @@ void JlsCodec<TRAITS,STRATEGY>::DoLine(Triplet<SAMPLE>*)
// In ILV_NONE mode, DoScan is called for each component
template<class TRAITS, class STRATEGY>
-void JlsCodec<TRAITS,STRATEGY>::DoScan(BYTE* compressedBytes, size_t compressedLength)
-{
- _width = Info().width;
-
- STRATEGY::Init(compressedBytes, compressedLength);
-
+void JlsCodec<TRAITS,STRATEGY>::DoScan()
+{
LONG pixelstride = _width + 4;
int components = Info().ilv == ILV_LINE ? Info().components : 1;
std::vector<PIXEL> vectmp(2 * components * pixelstride);
std::vector<LONG> rgRUNindex(components);
-
+
for (LONG line = 0; line < Info().height; ++line)
{
- _previousLine = &vectmp[1];
- _currentLine = &vectmp[1 + components * pixelstride];
+ _previousLine = &vectmp[1];
+ _currentLine = &vectmp[1 + components * pixelstride];
if ((line & 1) == 1)
{
std::swap(_previousLine, _currentLine);
@@ -730,17 +734,17 @@ void JlsCodec<TRAITS,STRATEGY>::DoScan(BYTE* compressedBytes, size_t compressedL
for (int component = 0; component < components; ++component)
{
_RUNindex = rgRUNindex[component];
-
+
// initialize edge pixels used for prediction
_previousLine[_width] = _previousLine[_width - 1];
_currentLine[-1] = _previousLine[0];
DoLine((PIXEL*) NULL); // dummy arg for overload resolution
-
+
rgRUNindex[component] = _RUNindex;
_previousLine += pixelstride;
_currentLine += pixelstride;
}
-
+
if (_rect.Y <= line && line < _rect.Y + _rect.Height)
{
STRATEGY::OnLineEnd(_rect.Width, _currentLine + _rect.X - (components * pixelstride), pixelstride);
@@ -754,32 +758,38 @@ void JlsCodec<TRAITS,STRATEGY>::DoScan(BYTE* compressedBytes, size_t compressedL
// Factory function for ProcessLine objects to copy/transform unencoded pixels to/from our scanline buffers.
template<class TRAITS, class STRATEGY>
-ProcessLine* JlsCodec<TRAITS,STRATEGY>::CreateProcess(void* pvoidOut)
+ProcessLine* JlsCodec<TRAITS,STRATEGY>::CreateProcess(ByteStreamInfo info)
{
if (!IsInterleaved())
- return new PostProcesSingleComponent(pvoidOut, Info(), sizeof(typename TRAITS::PIXEL));
+ {
+ return info.rawData != NULL ?
+ static_cast<ProcessLine*>(new PostProcesSingleComponent(info.rawData, Info(), sizeof(typename TRAITS::PIXEL))) :
+ static_cast<ProcessLine*>(new PostProcesSingleStream(info.rawStream, Info(), sizeof(typename TRAITS::PIXEL)));
+ }
+
+ int transform = Info().colorTransform & 0xFF;
- if (Info().colorTransform == 0)
- return new ProcessTransformed<TransformNone<typename TRAITS::SAMPLE> >(pvoidOut, Info(), TransformNone<SAMPLE>());
+ if (transform == 0)
+ return new ProcessTransformed<TransformNone<typename TRAITS::SAMPLE> >(info, Info(), TransformNone<SAMPLE>());
- if ((Info().bitspersample == sizeof(SAMPLE)*8))
+ if (Info().bitspersample == sizeof(SAMPLE)*8)
{
- switch(Info().colorTransform)
+ switch(transform)
{
- case COLORXFORM_HP1 : return new ProcessTransformed<TransformHp1<SAMPLE> >(pvoidOut, Info(), TransformHp1<SAMPLE>()); break;
- case COLORXFORM_HP2 : return new ProcessTransformed<TransformHp2<SAMPLE> >(pvoidOut, Info(), TransformHp2<SAMPLE>()); break;
- case COLORXFORM_HP3 : return new ProcessTransformed<TransformHp3<SAMPLE> >(pvoidOut, Info(), TransformHp3<SAMPLE>()); break;
+ case COLORXFORM_HP1 : return new ProcessTransformed<TransformHp1<SAMPLE> >(info, Info(), TransformHp1<SAMPLE>());
+ case COLORXFORM_HP2 : return new ProcessTransformed<TransformHp2<SAMPLE> >(info, Info(), TransformHp2<SAMPLE>());
+ case COLORXFORM_HP3 : return new ProcessTransformed<TransformHp3<SAMPLE> >(info, Info(), TransformHp3<SAMPLE>());
default: throw JlsException(UnsupportedColorTransform);
}
- }
+ }
else if (Info().bitspersample > 8)
{
int shift = 16 - Info().bitspersample;
- switch(Info().colorTransform)
+ switch(transform)
{
- case COLORXFORM_HP1 : return new ProcessTransformed<TransformShifted<TransformHp1<USHORT> > >(pvoidOut, Info(), TransformShifted<TransformHp1<USHORT> >(shift)); break;
- case COLORXFORM_HP2 : return new ProcessTransformed<TransformShifted<TransformHp2<USHORT> > >(pvoidOut, Info(), TransformShifted<TransformHp2<USHORT> >(shift)); break;
- case COLORXFORM_HP3 : return new ProcessTransformed<TransformShifted<TransformHp3<USHORT> > >(pvoidOut, Info(), TransformShifted<TransformHp3<USHORT> >(shift)); break;
+ case COLORXFORM_HP1 : return new ProcessTransformed<TransformShifted<TransformHp1<USHORT> > >(info, Info(), TransformShifted<TransformHp1<USHORT> >(shift));
+ case COLORXFORM_HP2 : return new ProcessTransformed<TransformShifted<TransformHp2<USHORT> > >(info, Info(), TransformShifted<TransformHp2<USHORT> >(shift));
+ case COLORXFORM_HP3 : return new ProcessTransformed<TransformShifted<TransformHp3<USHORT> > >(info, Info(), TransformShifted<TransformHp3<USHORT> >(shift));
default: throw JlsException(UnsupportedColorTransform);
}
}
@@ -787,61 +797,46 @@ ProcessLine* JlsCodec<TRAITS,STRATEGY>::CreateProcess(void* pvoidOut)
}
-
// Setup codec for encoding and calls DoScan
template<class TRAITS, class STRATEGY>
-size_t JlsCodec<TRAITS,STRATEGY>::EncodeScan(const void* rawData, void* compressedData, size_t compressedLength, void* pvoidCompare)
+size_t JlsCodec<TRAITS,STRATEGY>::EncodeScan(std::auto_ptr<ProcessLine> processLine, ByteStreamInfo* compressedData, void* pvoidCompare)
{
- STRATEGY::_processLine = std::auto_ptr<ProcessLine>(CreateProcess(const_cast<void*>(rawData)));
-
- BYTE* compressedBytes = static_cast<BYTE*>(compressedData);
+ STRATEGY::_processLine = processLine;
+ ByteStreamInfo info = { NULL, (BYTE*)pvoidCompare, compressedData->count };
if (pvoidCompare != NULL)
{
- STRATEGY::_qdecoder = std::auto_ptr<DecoderStrategy>(new JlsCodec<TRAITS,DecoderStrategy>(traits, Info()));
- STRATEGY::_qdecoder->Init((BYTE*)pvoidCompare, compressedLength);
+ STRATEGY::_qdecoder.reset(new JlsCodec<TRAITS,DecoderStrategy>(traits, Info()));
+ STRATEGY::_qdecoder->Init(&info);
}
- DoScan(compressedBytes, compressedLength);
-
- return STRATEGY::GetLength();
+ STRATEGY::Init(compressedData);
+
+ DoScan();
+ return STRATEGY::GetLength();
}
// Setup codec for decoding and calls DoScan
+
template<class TRAITS, class STRATEGY>
-size_t JlsCodec<TRAITS,STRATEGY>::DecodeScan(void* rawData, const JlsRect& rect, const void* compressedData, size_t compressedLength, bool bCompare)
+void JlsCodec<TRAITS,STRATEGY>::DecodeScan(std::auto_ptr<ProcessLine> processLine, const JlsRect& rect, ByteStreamInfo* compressedData, bool bCompare)
{
- STRATEGY::_processLine = std::auto_ptr<ProcessLine>(CreateProcess(rawData));
+ STRATEGY::_processLine = processLine;
- BYTE* compressedBytes = const_cast<BYTE*>(static_cast<const BYTE*>(compressedData));
+ BYTE* compressedBytes = const_cast<BYTE*>(static_cast<const BYTE*>(compressedData->rawData));
_bCompare = bCompare;
-
- BYTE rgbyte[20];
-
- size_t readBytes = 0;
- ::memcpy(rgbyte, compressedBytes, 4);
- readBytes += 4;
-
- size_t cbyteScanheader = rgbyte[3] - 2;
-
- if (cbyteScanheader > sizeof(rgbyte))
- throw JlsException(InvalidCompressedData);
-
- ::memcpy(rgbyte, compressedBytes, cbyteScanheader);
- readBytes += cbyteScanheader;
-
_rect = rect;
- DoScan(compressedBytes + readBytes, compressedLength - readBytes);
-
- return STRATEGY::GetCurBytePos() - compressedBytes;
+ STRATEGY::Init(compressedData);
+ DoScan();
+ SkipBytes(compressedData, STRATEGY::GetCurBytePos() - compressedBytes);
}
-// Initialize the codec data structures. Depends on JPEG-LS parameters like T1-T3.
+// Initialize the codec data structures. Depends on JPEG-LS parameters like T1-T3.
template<class TRAITS, class STRATEGY>
void JlsCodec<TRAITS,STRATEGY>::InitParams(LONG t1, LONG t2, LONG t3, LONG nReset)
{
diff --git a/util.h b/src/util.h
similarity index 93%
rename from util.h
rename to src/util.h
index 892cc47..5d491cb 100644
--- a/util.h
+++ b/src/util.h
@@ -6,10 +6,10 @@
#ifndef CHARLS_UTIL
#define CHARLS_UTIL
+#include "publictypes.h"
#include <stdlib.h>
#include <string.h>
-#include "publictypes.h"
-
+#include <vector>
#ifndef MAX
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
@@ -20,6 +20,13 @@
#endif
+inline void push_back(std::vector<BYTE>& vec, USHORT value)
+{
+ vec.push_back(BYTE(value / 0x100));
+ vec.push_back(BYTE(value % 0x100));
+}
+
+
inline LONG log_2(LONG n)
{
LONG x = 0;
diff --git a/stdafx.cpp b/stdafx.cpp
deleted file mode 100644
index e69de29..0000000
diff --git a/streams.h b/streams.h
deleted file mode 100644
index ee8dbd3..0000000
--- a/streams.h
+++ /dev/null
@@ -1,156 +0,0 @@
-//
-// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
-//
-#ifndef CHARLS_STREAMS
-#define CHARLS_STREAMS
-
-#include <memory>
-#include <vector>
-#include "util.h"
-
-
-
-// This file defines JPEG-LS streams: The header and the actual pixel data. Header markers have fixed length, the pixeldata not.
-
-
-
-class JpegSegment;
-
-enum JPEGLS_ColorXForm
-{
- // default (RGB)
- COLORXFORM_NONE = 0,
-
- // Color transforms as defined by HP
- COLORXFORM_HP1,
- COLORXFORM_HP2,
- COLORXFORM_HP3,
-
- // Defined by HP but not supported by CharLS
- COLORXFORM_RGB_AS_YUV_LOSSY,
- COLORXFORM_MATRIX
-};
-
-//
-// JLSOutputStream: minimal implementation to write JPEG header streams
-//
-class JLSOutputStream
-{
- friend class JpegMarkerSegment;
- friend class JpegImageDataSegment;
-
-public:
- JLSOutputStream();
- virtual ~JLSOutputStream();
-
- void Init(Size size, LONG bitsPerSample, LONG ccomp);
- void AddScan(const void* compareData, const JlsParameters* pparams);
- void AddLSE(const JlsCustomParameters* pcustom);
- void AddColorTransform(int i);
- size_t GetBytesWritten()
- { return _cbyteOffset; }
-
- size_t GetLength()
- { return _cbyteLength - _cbyteOffset; }
-
- size_t Write(BYTE* pdata, size_t cbyteLength);
-
- void EnableCompare(bool bCompare)
- { _bCompare = bCompare; }
-private:
- BYTE* GetPos() const
- { return _pdata + _cbyteOffset; }
-
- void WriteByte(BYTE val)
- {
- ASSERT(!_bCompare || _pdata[_cbyteOffset] == val);
-
- _pdata[_cbyteOffset++] = val;
- }
-
- void WriteBytes(const std::vector<BYTE>& rgbyte)
- {
- for (size_t i = 0; i < rgbyte.size(); ++i)
- {
- WriteByte(rgbyte[i]);
- }
- }
-
- void WriteWord(USHORT val)
- {
- WriteByte(BYTE(val / 0x100));
- WriteByte(BYTE(val % 0x100));
- }
-
-
- void Seek(size_t byteCount)
- { _cbyteOffset += byteCount; }
-
- bool _bCompare;
-
-private:
- BYTE* _pdata;
- size_t _cbyteOffset;
- size_t _cbyteLength;
- LONG _icompLast;
- std::vector<JpegSegment*> _segments;
-};
-
-
-//
-// JLSInputStream: minimal implementation to read JPEG header streams
-//
-class JLSInputStream
-{
-public:
- JLSInputStream(const BYTE* pdata, size_t cbyteLength);
-
- size_t GetBytesRead()
- { return _cbyteOffset; }
-
- const JlsParameters& GetMetadata() const
- { return _info; }
-
- const JlsCustomParameters& GetCustomPreset() const
- { return _info.custom; }
-
- void Read(void* pvoid, size_t cbyteAvailable);
- void ReadHeader();
-
- void EnableCompare(bool bCompare)
- { _bCompare = bCompare; }
-
- void SetInfo(JlsParameters* info) { _info = *info; }
-
- void SetRect(JlsRect rect) { _rect = rect; }
-
-private:
- void ReadPixels(void* pvoid, size_t cbyteAvailable);
- void ReadScan(void*);
- void ReadStartOfScan();
- void ReadPresetParameters();
- void ReadComment();
- void ReadStartOfFrame();
- BYTE ReadByte();
- int ReadWord();
- void ReadNBytes(std::vector<char>& dst, int byteCount);
-
- // JFIF
- void ReadJfif();
- // Color Transform Application Markers & Code Stream (HP extension)
- void ReadColorSpace();
- void ReadColorXForm();
-
-private:
- const BYTE* _pdata;
- size_t _cbyteOffset;
- size_t _cbyteLength;
- bool _bCompare;
- JlsParameters _info;
- JlsRect _rect;
-};
-
-
-
-
-#endif
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index c45bd66..277d014 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,5 +1,5 @@
-# test for charlls
-
-#add_library(CharLS STATIC IMPORTED)
-
+# test for charlls
+
+#add_library(CharLS STATIC IMPORTED)
+
link_directories (..)
\ No newline at end of file
diff --git a/test/bitstreamdamage.cpp b/test/bitstreamdamage.cpp
index a713a07..c17116f 100644
--- a/test/bitstreamdamage.cpp
+++ b/test/bitstreamdamage.cpp
@@ -1,124 +1,122 @@
-//
-// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
-//
-
-
-#include "config.h"
-#include <iostream>
-#include <vector>
-
-#include "../interface.h"
-#include "../util.h"
-#include "../defaulttraits.h"
-#include "../losslesstraits.h"
-#include "../colortransform.h"
-#include "../streams.h"
-#include "../processline.h"
-
-#include "util.h"
-
-void TestDamagedBitStream1()
-{
- std::vector<BYTE> rgbyteCompressed;
- if (!ReadFile("test/incorrect_images/InfiniteLoopFFMPEG.jls", &rgbyteCompressed, 0))
- return;
-
- std::vector<BYTE> rgbyteOut(256 * 256 * 2);
- JLS_ERROR error = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), &rgbyteCompressed[0], int(rgbyteCompressed.size()), NULL);
- assert(error == InvalidCompressedData);
-
-}
-
-
-void TestDamagedBitStream2()
-{
- std::vector<BYTE> rgbyteCompressed;
- if (!ReadFile("test/lena8b.jls", &rgbyteCompressed, 0))
- return;
-
- rgbyteCompressed.resize(900);
- rgbyteCompressed.resize(40000,3);
-
- std::vector<BYTE> rgbyteOut(512 * 512);
- JLS_ERROR error = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), &rgbyteCompressed[0], int(rgbyteCompressed.size()), NULL);
- assert(error == InvalidCompressedData);
-
-}
-
-
-
-void TestDamagedBitStream3()
-{
- std::vector<BYTE> rgbyteCompressed;
- if (!ReadFile("test/lena8b.jls", &rgbyteCompressed, 0))
- return;
- rgbyteCompressed[300] = 0xFF;
- rgbyteCompressed[301] = 0xFF;
-
- std::vector<BYTE> rgbyteOut(512 * 512);
- JLS_ERROR error = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), &rgbyteCompressed[0], int(rgbyteCompressed.size()), NULL);
- assert(error == InvalidCompressedData);
-
-}
-
-
-void TestFileWithRandomHeaderDamage(SZC filename)
-{
- std::vector<BYTE> rgbyteCompressedOrg;
- if (!ReadFile(filename, &rgbyteCompressedOrg, 0))
- return;
-
- srand(102347325);
-
- std::vector<BYTE> rgbyteOut(512 * 512);
-
- for (int i = 0; i < 40; ++i)
- {
- std::vector<BYTE> rgbyteCompressedTest(rgbyteCompressedOrg);
- std::vector<int> errors(10,0);
-
- for (int j = 0; j < 20; ++j)
- {
- rgbyteCompressedTest[i] = (BYTE)rand();
- rgbyteCompressedTest[i+1] = (BYTE)rand();
- rgbyteCompressedTest[i+2] = (BYTE)rand();
- rgbyteCompressedTest[i+3] = (BYTE)rand();
-
- JLS_ERROR error = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), &rgbyteCompressedTest[0], int(rgbyteCompressedTest.size()), NULL);
- errors[error] = errors[error] + 1;
- }
-
- std::cout << "With garbage input at index " << i << ": ";
- for(unsigned int error = 0; error < errors.size(); ++error)
- {
- if (errors[error] == 0)
- continue;
-
- std::cout << errors[error] << "x error (" << error << "); ";
- }
-
- std::cout << "\r\n";
- }
-}
-
-
-
-void TestRandomMalformedHeader()
-{
- TestFileWithRandomHeaderDamage("test/conformance/T8C0E0.JLS");
- TestFileWithRandomHeaderDamage("test/conformance/T8C1E0.JLS");
- TestFileWithRandomHeaderDamage("test/conformance/T8C2E0.JLS");
-}
-
-
-void DamagedBitstreamTests()
-{
- printf("Test Damaged bitstream\r\n");
- TestDamagedBitStream1();
- TestDamagedBitStream2();
- TestDamagedBitStream3();
-
- printf("Begin random malformed bitstream tests: \r\n");
- TestRandomMalformedHeader();
- printf("End randommalformed bitstream tests: \r\n");
-}
+//
+// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
+
+
+#include "config.h"
+#include <iostream>
+#include <vector>
+
+#include "../src/interface.h"
+#include "../src/util.h"
+#include "../src/jpegmarker.h"
+#include "../src/processline.h"
+
+#include "util.h"
+
+void TestDamagedBitStream1()
+{
+ std::vector<BYTE> rgbyteCompressed;
+ if (!ReadFile("test/incorrect_images/InfiniteLoopFFMPEG.jls", &rgbyteCompressed, 0))
+ return;
+
+ std::vector<BYTE> rgbyteOut(256 * 256 * 2);
+ JLS_ERROR error = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), &rgbyteCompressed[0], int(rgbyteCompressed.size()), NULL);
+ ASSERT(error == InvalidCompressedData);
+
+}
+
+
+void TestDamagedBitStream2()
+{
+ std::vector<BYTE> rgbyteCompressed;
+ if (!ReadFile("test/lena8b.jls", &rgbyteCompressed, 0))
+ return;
+
+ rgbyteCompressed.resize(900);
+ rgbyteCompressed.resize(40000,3);
+
+ std::vector<BYTE> rgbyteOut(512 * 512);
+ JLS_ERROR error = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), &rgbyteCompressed[0], int(rgbyteCompressed.size()), NULL);
+ ASSERT(error == InvalidCompressedData);
+
+}
+
+
+
+void TestDamagedBitStream3()
+{
+ std::vector<BYTE> rgbyteCompressed;
+ if (!ReadFile("test/lena8b.jls", &rgbyteCompressed, 0))
+ return;
+
+ rgbyteCompressed[300] = 0xFF;
+ rgbyteCompressed[301] = 0xFF;
+
+ std::vector<BYTE> rgbyteOut(512 * 512);
+ JLS_ERROR error = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), &rgbyteCompressed[0], int(rgbyteCompressed.size()), NULL);
+ ASSERT(error == InvalidCompressedData);
+
+}
+
+
+void TestFileWithRandomHeaderDamage(SZC filename)
+{
+ std::vector<BYTE> rgbyteCompressedOrg;
+ if (!ReadFile(filename, &rgbyteCompressedOrg, 0))
+ return;
+
+ srand(102347325);
+
+ std::vector<BYTE> rgbyteOut(512 * 512);
+
+ for (int i = 0; i < 40; ++i)
+ {
+ std::vector<BYTE> rgbyteCompressedTest(rgbyteCompressedOrg);
+ std::vector<int> errors(10,0);
+
+ for (int j = 0; j < 20; ++j)
+ {
+ rgbyteCompressedTest[i] = (BYTE)rand();
+ rgbyteCompressedTest[i+1] = (BYTE)rand();
+ rgbyteCompressedTest[i+2] = (BYTE)rand();
+ rgbyteCompressedTest[i+3] = (BYTE)rand();
+
+ JLS_ERROR error = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), &rgbyteCompressedTest[0], int(rgbyteCompressedTest.size()), NULL);
+ errors[error] = errors[error] + 1;
+ }
+
+ std::cout << "With garbage input at index " << i << ": ";
+ for(unsigned int error = 0; error < errors.size(); ++error)
+ {
+ if (errors[error] == 0)
+ continue;
+
+ std::cout << errors[error] << "x error (" << error << "); ";
+ }
+
+ std::cout << "\r\n";
+ }
+}
+
+
+
+void TestRandomMalformedHeader()
+{
+ TestFileWithRandomHeaderDamage("test/conformance/T8C0E0.JLS");
+ TestFileWithRandomHeaderDamage("test/conformance/T8C1E0.JLS");
+ TestFileWithRandomHeaderDamage("test/conformance/T8C2E0.JLS");
+}
+
+
+void DamagedBitstreamTests()
+{
+ printf("Test Damaged bitstream\r\n");
+ TestDamagedBitStream1();
+ TestDamagedBitStream2();
+ TestDamagedBitStream3();
+
+ printf("Begin random malformed bitstream tests: \r\n");
+ TestRandomMalformedHeader();
+ printf("End randommalformed bitstream tests: \r\n");
+}
diff --git a/test/compliance.cpp b/test/compliance.cpp
index 77d70b9..5558d63 100644
--- a/test/compliance.cpp
+++ b/test/compliance.cpp
@@ -1,241 +1,235 @@
-//
-// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
-//
-
-
-#include "config.h"
-
-#include "../interface.h"
-#include "../util.h"
-#include "../streams.h"
-
-#include <iostream>
-#include <vector>
-
-#include "util.h"
-
-
-void Triplet2Planar(std::vector<BYTE>& rgbyte, Size size)
-{
- std::vector<BYTE> rgbytePlanar(rgbyte.size());
-
- int cbytePlane = size.cx * size.cy;
- for (int index = 0; index < cbytePlane; index++)
- {
- rgbytePlanar[index] = rgbyte[index * 3 + 0];
- rgbytePlanar[index + 1*cbytePlane] = rgbyte[index * 3 + 1];
- rgbytePlanar[index + 2*cbytePlane] = rgbyte[index * 3 + 2];
- }
- std::swap(rgbyte, rgbytePlanar);
-}
-
-void Triplet2Line(std::vector<BYTE>& rgbyte, Size size)
-{
- std::vector<BYTE> rgbyteInterleaved(rgbyte.size());
-
- int cbyteLine = size.cx;
-
- for (int line = 0; line < size.cy; ++line)
- {
- const BYTE* pbyteLineIn = &rgbyte[line * size.cx * 3];
- BYTE* pbyteLineOut = &rgbyteInterleaved[line * size.cx * 3];
-
- for (int index = 0; index < cbyteLine; index++)
- {
- pbyteLineOut[index] = pbyteLineIn[index * 3 + 0];
- pbyteLineOut[index + 1*cbyteLine] = pbyteLineIn[index * 3 + 1];
- pbyteLineOut[index + 2*cbyteLine] = pbyteLineIn[index * 3 + 2];
- }
- }
- std::swap(rgbyte, rgbyteInterleaved);
-}
-
-
-
-
-
-void TestCompliance(const BYTE* compressedBytes, int compressedLength, const BYTE* rgbyteRaw, int cbyteRaw, bool bcheckEncode)
-{
- JlsParameters info = JlsParameters();
- JLS_ERROR err = JpegLsReadHeader(compressedBytes, compressedLength, &info);
- assert(err == OK);
-
- if (bcheckEncode)
- {
- err = JpegLsVerifyEncode(&rgbyteRaw[0], cbyteRaw, compressedBytes, compressedLength);
- assert(err == OK);
- }
-
- std::vector<BYTE> rgbyteCompressed(info.height *info.width* 4);
-
- std::vector<BYTE> rgbyteOut(info.height *info.width * ((info.bitspersample + 7) / 8) * info.components);
-
- err = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), compressedBytes, compressedLength, NULL);
- assert(err == OK);
-
- if (info.allowedlossyerror == 0)
- {
- BYTE* pbyteOut = &rgbyteOut[0];
- for (int i = 0; i < cbyteRaw; ++i)
- {
- if (rgbyteRaw[i] != pbyteOut[i])
- {
- assert(false);
- break;
- }
- }
- }
-
-}
-
-
-
-void DecompressFile(SZC strNameEncoded, SZC strNameRaw, int ioffs, bool bcheckEncode)
-{
- std::cout << "Conformance test:" << strNameEncoded << "\n\r";
- std::vector<BYTE> rgbyteFile;
- if (!ReadFile(strNameEncoded, &rgbyteFile))
- return;
-
- JlsParameters metadata;
- if (JpegLsReadHeader(&rgbyteFile[0], rgbyteFile.size(), &metadata) != OK)
- {
- assert(false);
- return;
- }
-
- std::vector<BYTE> rgbyteRaw;
- if (!ReadFile(strNameRaw, &rgbyteRaw, ioffs))
- return;
-
- if (metadata.bitspersample > 8)
- {
- FixEndian(&rgbyteRaw, false);
- }
-
- Size size = Size(metadata.width, metadata.height);
-
- if (metadata.ilv == ILV_NONE && metadata.components == 3)
- {
- Triplet2Planar(rgbyteRaw, Size(metadata.width, metadata.height));
- }
-
- TestCompliance(&rgbyteFile[0], rgbyteFile.size(), &rgbyteRaw[0], rgbyteRaw.size(), bcheckEncode);
-}
-
-
-BYTE palettisedDataH10[] = {
- 0xFF, 0xD8, //Start of image (SOI) marker
- 0xFF, 0xF7, //Start of JPEG-LS frame (SOF 55) marker � marker segment follows
- 0x00, 0x0B, //Length of marker segment = 11 bytes including the length field
- 0x02, //P = Precision = 2 bits per sample
- 0x00, 0x04, //Y = Number of lines = 4
- 0x00, 0x03, //X = Number of columns = 3
- 0x01, //Nf = Number of components in the frame = 1
- 0x01, //C1 = Component ID = 1 (first and only component)
- 0x11, //Sub-sampling: H1 = 1, V1 = 1
- 0x00, //Tq1 = 0 (this field is always 0)
-
- 0xFF, 0xF8, //LSE � JPEG-LS preset parameters marker
- 0x00, 0x11, //Length of marker segment = 17 bytes including the length field
- 0x02, //ID = 2, mapping table
- 0x05, //TID = 5 Table identifier (arbitrary)
- 0x03, //Wt = 3 Width of table entry
- 0xFF, 0xFF, 0xFF, //Entry for index 0
- 0xFF, 0x00, 0x00, //Entry for index 1
- 0x00, 0xFF, 0x00, //Entry for index 2
- 0x00, 0x00, 0xFF, //Entry for index 3
-
- 0xFF, 0xDA, //Start of scan (SOS) marker
- 0x00, 0x08, //Length of marker segment = 8 bytes including the length field
- 0x01, //Ns = Number of components for this scan = 1
- 0x01, //C1 = Component ID = 1
- 0x05, //Tm 1 = Mapping table identifier = 5
- 0x00, //NEAR = 0 (near-lossless max error)
- 0x00, //ILV = 0 (interleave mode = non-interleaved)
- 0x00, //Al = 0, Ah = 0 (no point transform)
- 0xDB, 0x95, 0xF0, //3 bytes of compressed image data
- 0xFF, 0xD9 //End of image (EOI) marker
-};
-
-
-
-
-
-
-
-
-
-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 TestSampleAnnexH3()
-{
- 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 TestColorTransforms_HpImages()
-{
- DecompressFile("test/jlsimage/banny_normal.jls", "test/jlsimage/banny.ppm",38, false);
- DecompressFile("test/jlsimage/banny_Hp1.jls", "test/jlsimage/banny.ppm",38, false);
- DecompressFile("test/jlsimage/banny_Hp2.jls", "test/jlsimage/banny.ppm",38, false);
- DecompressFile("test/jlsimage/banny_Hp3.jls", "test/jlsimage/banny.ppm",38, false);
-}
-
-void TestConformance()
-{
- // Test 1
- DecompressFile("test/conformance/T8C0E0.JLS", "test/conformance/TEST8.PPM",15);
-
- // Test 2
- DecompressFile("test/conformance/T8C1E0.JLS", "test/conformance/TEST8.PPM",15);
-
- // 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
- DecompressFile("test/conformance/T8C1E3.JLS", "test/conformance/TEST8.PPM",15);
-
- // 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);
-}
-
-
+//
+// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
+
+
+#include "config.h"
+
+#include "../src/interface.h"
+#include "../src/util.h"
+#include "../src/jpegmarker.h"
+
+#include <iostream>
+#include <vector>
+
+#include "util.h"
+
+
+void Triplet2Planar(std::vector<BYTE>& rgbyte, Size size)
+{
+ std::vector<BYTE> rgbytePlanar(rgbyte.size());
+
+ int cbytePlane = size.cx * size.cy;
+ for (int index = 0; index < cbytePlane; index++)
+ {
+ rgbytePlanar[index] = rgbyte[index * 3 + 0];
+ rgbytePlanar[index + 1*cbytePlane] = rgbyte[index * 3 + 1];
+ rgbytePlanar[index + 2*cbytePlane] = rgbyte[index * 3 + 2];
+ }
+ std::swap(rgbyte, rgbytePlanar);
+}
+
+
+void Triplet2Line(std::vector<BYTE>& rgbyte, Size size)
+{
+ std::vector<BYTE> rgbyteInterleaved(rgbyte.size());
+
+ int cbyteLine = size.cx;
+
+ for (int line = 0; line < size.cy; ++line)
+ {
+ const BYTE* pbyteLineIn = &rgbyte[line * size.cx * 3];
+ BYTE* pbyteLineOut = &rgbyteInterleaved[line * size.cx * 3];
+
+ for (int index = 0; index < cbyteLine; index++)
+ {
+ pbyteLineOut[index] = pbyteLineIn[index * 3 + 0];
+ pbyteLineOut[index + 1*cbyteLine] = pbyteLineIn[index * 3 + 1];
+ pbyteLineOut[index + 2*cbyteLine] = pbyteLineIn[index * 3 + 2];
+ }
+ }
+ std::swap(rgbyte, rgbyteInterleaved);
+}
+
+
+void TestCompliance(const BYTE* compressedBytes, size_t compressedLength, const BYTE* rgbyteRaw, size_t cbyteRaw, bool bcheckEncode)
+{
+ JlsParameters info = JlsParameters();
+ JLS_ERROR err = JpegLsReadHeader(compressedBytes, compressedLength, &info);
+ ASSERT(err == OK);
+
+ if (bcheckEncode)
+ {
+ err = JpegLsVerifyEncode(&rgbyteRaw[0], cbyteRaw, compressedBytes, compressedLength);
+ ASSERT(err == OK);
+ }
+
+ std::vector<BYTE> rgbyteCompressed(info.height *info.width* 4);
+
+ std::vector<BYTE> rgbyteOut(info.height *info.width * ((info.bitspersample + 7) / 8) * info.components);
+
+ err = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), compressedBytes, compressedLength, NULL);
+ ASSERT(err == OK);
+
+ if (info.allowedlossyerror == 0)
+ {
+ BYTE* pbyteOut = &rgbyteOut[0];
+ for (size_t i = 0; i < cbyteRaw; ++i)
+ {
+ if (rgbyteRaw[i] != pbyteOut[i])
+ {
+ ASSERT(false);
+ break;
+ }
+ }
+ }
+}
+
+
+void DecompressFile(SZC strNameEncoded, SZC strNameRaw, int ioffs, bool bcheckEncode)
+{
+ std::cout << "Conformance test:" << strNameEncoded << "\n\r";
+ std::vector<BYTE> rgbyteFile;
+ if (!ReadFile(strNameEncoded, &rgbyteFile))
+ return;
+
+ JlsParameters metadata;
+ if (JpegLsReadHeader(&rgbyteFile[0], rgbyteFile.size(), &metadata) != OK)
+ {
+ ASSERT(false);
+ return;
+ }
+
+ std::vector<BYTE> rgbyteRaw;
+ if (!ReadFile(strNameRaw, &rgbyteRaw, ioffs))
+ return;
+
+ if (metadata.bitspersample > 8)
+ {
+ FixEndian(&rgbyteRaw, false);
+ }
+
+ if (metadata.ilv == ILV_NONE && metadata.components == 3)
+ {
+ Triplet2Planar(rgbyteRaw, Size(metadata.width, metadata.height));
+ }
+
+ TestCompliance(&rgbyteFile[0], rgbyteFile.size(), &rgbyteRaw[0], rgbyteRaw.size(), bcheckEncode);
+}
+
+
+BYTE palettisedDataH10[] = {
+ 0xFF, 0xD8, //Start of image (SOI) marker
+ 0xFF, 0xF7, //Start of JPEG-LS frame (SOF 55) marker � marker segment follows
+ 0x00, 0x0B, //Length of marker segment = 11 bytes including the length field
+ 0x02, //P = Precision = 2 bits per sample
+ 0x00, 0x04, //Y = Number of lines = 4
+ 0x00, 0x03, //X = Number of columns = 3
+ 0x01, //Nf = Number of components in the frame = 1
+ 0x01, //C1 = Component ID = 1 (first and only component)
+ 0x11, //Sub-sampling: H1 = 1, V1 = 1
+ 0x00, //Tq1 = 0 (this field is always 0)
+
+ 0xFF, 0xF8, //LSE � JPEG-LS preset parameters marker
+ 0x00, 0x11, //Length of marker segment = 17 bytes including the length field
+ 0x02, //ID = 2, mapping table
+ 0x05, //TID = 5 Table identifier (arbitrary)
+ 0x03, //Wt = 3 Width of table entry
+ 0xFF, 0xFF, 0xFF, //Entry for index 0
+ 0xFF, 0x00, 0x00, //Entry for index 1
+ 0x00, 0xFF, 0x00, //Entry for index 2
+ 0x00, 0x00, 0xFF, //Entry for index 3
+
+ 0xFF, 0xDA, //Start of scan (SOS) marker
+ 0x00, 0x08, //Length of marker segment = 8 bytes including the length field
+ 0x01, //Ns = Number of components for this scan = 1
+ 0x01, //C1 = Component ID = 1
+ 0x05, //Tm 1 = Mapping table identifier = 5
+ 0x00, //NEAR = 0 (near-lossless max error)
+ 0x00, //ILV = 0 (interleave mode = non-interleaved)
+ 0x00, //Al = 0, Ah = 0 (no point transform)
+ 0xDB, 0x95, 0xF0, //3 bytes of compressed image data
+ 0xFF, 0xD9 //End of image (EOI) marker
+};
+
+
+
+
+
+
+
+
+
+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 TestSampleAnnexH3()
+{
+ //// 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 TestColorTransforms_HpImages()
+{
+ DecompressFile("test/jlsimage/banny_normal.jls", "test/jlsimage/banny.ppm",38, false);
+ DecompressFile("test/jlsimage/banny_Hp1.jls", "test/jlsimage/banny.ppm",38, false);
+ DecompressFile("test/jlsimage/banny_Hp2.jls", "test/jlsimage/banny.ppm",38, false);
+ DecompressFile("test/jlsimage/banny_Hp3.jls", "test/jlsimage/banny.ppm",38, false);
+}
+
+void TestConformance()
+{
+ // Test 1
+ DecompressFile("test/conformance/T8C0E0.JLS", "test/conformance/TEST8.PPM",15);
+
+ // Test 2
+ DecompressFile("test/conformance/T8C1E0.JLS", "test/conformance/TEST8.PPM",15);
+
+ // 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
+ DecompressFile("test/conformance/T8C1E3.JLS", "test/conformance/TEST8.PPM",15);
+
+ // 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);
+}
+
+
diff --git a/test/config.h b/test/config.h
index ae619be..0bd4a43 100644
--- a/test/config.h
+++ b/test/config.h
@@ -1,28 +1,28 @@
-//
-// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
-//
-
-#ifndef TEST_CONFIG
-#define TEST_CONFIG
-
-#if defined(_MSC_VER)
-#pragma warning (disable: 4996)
-#endif
-
-// enable ASSERT() on linux
-#ifndef _WIN32
-#ifndef _DEBUG
-#define _DEBUG
-#endif
-
-#else
-#include <assert.h>
-
-#endif
-
-#include <stdio.h>
-
-typedef unsigned char BYTE;
-typedef unsigned short USHORT;
-
-#endif
+//
+// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
+
+#ifndef TEST_CONFIG
+#define TEST_CONFIG
+
+#if defined(_MSC_VER)
+#pragma warning (disable: 4996)
+#endif
+
+// enable ASSERT() on linux
+#ifndef _WIN32
+#ifndef _DEBUG
+#define _DEBUG
+#endif
+
+#else
+#include <assert.h>
+#define CHARLS_DLL
+#endif
+
+#include <stdio.h>
+
+typedef unsigned char BYTE;
+typedef unsigned short USHORT;
+
+#endif
diff --git a/test/dicomsamples.cpp b/test/dicomsamples.cpp
index d1bee22..2dc75b2 100644
--- a/test/dicomsamples.cpp
+++ b/test/dicomsamples.cpp
@@ -1,78 +1,78 @@
-
-
-#include "config.h"
-#include <iostream>
-#include <vector>
-
-
-#include "util.h"
-#include "../interface.h"
-
-
-int findstring(std::vector<BYTE>& container, BYTE* bytesToFind, unsigned int bytesLength)
-{
- for (unsigned int i=0; i < container.size() - bytesLength; ++i)
- {
- for (unsigned int j=0; j < bytesLength; ++j)
- {
- if (bytesToFind[j] != container[i + j])
- goto next;
- }
- return i;
-
- next:;
- }
- return -1;
-}
-
-#define COUNT(x) (sizeof(x)/sizeof(x[0]))
-
-
-void TestDicomSampleImage(const char* name)
-{
- std::vector<BYTE> data;
- bool success = ReadFile(name, &data, 9);
-
- ASSERT(success);
-
- BYTE pixeldataStart[] = { 0x00, 0x00, 0x01, 0x00, 0xFF, 0xD8, 0xFF, 0xF7 };
-
- int offset = findstring(data, pixeldataStart, COUNT(pixeldataStart));
-
- data.erase(data.begin(), data.begin() + offset - 4);
-
- // remove the dicom fragment headers (in the concerned images they occur every 64k)
- for (unsigned int i = 0; i < data.size(); i+= 64 * 1024)
- {
- data.erase(data.begin() + i, data.begin() + i + 8);
- }
-
- JlsParameters info;
-
- JLS_ERROR error = JpegLsReadHeader(&data[0], data.size(), &info);
-
-
-// 0xFE, 0xFF, 0x00, 0xE0, 0x00, 0x00, 0x01, 0x00
- std::vector<BYTE> dataUnc;
- dataUnc.resize(info.bytesperline * info.height);
-
- error = JpegLsDecode(&dataUnc[0], dataUnc.size(), &data[0], data.size(), NULL);
- ASSERT(error == OK);
- std::cout << ".";
-}
-
-void TestDicomWG4Images()
-{
- TestDicomSampleImage("test/compsamples_jpegls/IMAGES/JLSL/XA1_JLSL");
- TestDicomSampleImage("test/compsamples_jpegls/IMAGES/JLSL/CT2_JLSL");
- TestDicomSampleImage("test/compsamples_jpegls/IMAGES/JLSL/MG1_JLSL");
- TestDicomSampleImage("test/compsamples_jpegls/IMAGES/JLSL/MR1_JLSL");
- TestDicomSampleImage("test/compsamples_jpegls/IMAGES/JLSL/MR2_JLSL");
- TestDicomSampleImage("test/compsamples_jpegls/IMAGES/JLSL/MR3_JLSL");
- TestDicomSampleImage("test/compsamples_jpegls/IMAGES/JLSL/MR4_JLSL");
- TestDicomSampleImage("test/compsamples_jpegls/IMAGES/JLSL/NM1_JLSL");
- TestDicomSampleImage("test/compsamples_jpegls/IMAGES/JLSL/RG1_JLSL");
- TestDicomSampleImage("test/compsamples_jpegls/IMAGES/JLSL/RG2_JLSL");
- TestDicomSampleImage("test/compsamples_jpegls/IMAGES/JLSL/RG3_JLSL");
- TestDicomSampleImage("test/compsamples_jpegls/IMAGES/JLSL/SC1_JLSL");
-}
+
+
+#include "config.h"
+#include <iostream>
+#include <vector>
+
+
+#include "util.h"
+#include "../src/interface.h"
+
+
+int findstring(std::vector<BYTE>& container, BYTE* bytesToFind, unsigned int bytesLength)
+{
+ for (unsigned int i=0; i < container.size() - bytesLength; ++i)
+ {
+ for (unsigned int j=0; j < bytesLength; ++j)
+ {
+ if (bytesToFind[j] != container[i + j])
+ goto next;
+ }
+ return i;
+
+ next:;
+ }
+ return -1;
+}
+
+#define COUNT(x) (sizeof(x)/sizeof(x[0]))
+
+
+void TestDicomSampleImage(const char* name)
+{
+ std::vector<BYTE> data;
+ bool success = ReadFile(name, &data, 9);
+
+ ASSERT(success);
+
+ BYTE pixeldataStart[] = { 0x00, 0x00, 0x01, 0x00, 0xFF, 0xD8, 0xFF, 0xF7 };
+
+ int offset = findstring(data, pixeldataStart, COUNT(pixeldataStart));
+
+ data.erase(data.begin(), data.begin() + offset - 4);
+
+ // remove the dicom fragment headers (in the concerned images they occur every 64k)
+ for (unsigned int i = 0; i < data.size(); i+= 64 * 1024)
+ {
+ data.erase(data.begin() + i, data.begin() + i + 8);
+ }
+
+ JlsParameters info;
+
+ JLS_ERROR error = JpegLsReadHeader(&data[0], data.size(), &info);
+
+
+// 0xFE, 0xFF, 0x00, 0xE0, 0x00, 0x00, 0x01, 0x00
+ std::vector<BYTE> dataUnc;
+ dataUnc.resize(info.bytesperline * info.height);
+
+ error = JpegLsDecode(&dataUnc[0], dataUnc.size(), &data[0], data.size(), NULL);
+ ASSERT(error == OK);
+ std::cout << ".";
+}
+
+void TestDicomWG4Images()
+{
+ TestDicomSampleImage("test/compsamples_jpegls/IMAGES/JLSL/XA1_JLSL");
+ TestDicomSampleImage("test/compsamples_jpegls/IMAGES/JLSL/CT2_JLSL");
+ TestDicomSampleImage("test/compsamples_jpegls/IMAGES/JLSL/MG1_JLSL");
+ TestDicomSampleImage("test/compsamples_jpegls/IMAGES/JLSL/MR1_JLSL");
+ TestDicomSampleImage("test/compsamples_jpegls/IMAGES/JLSL/MR2_JLSL");
+ TestDicomSampleImage("test/compsamples_jpegls/IMAGES/JLSL/MR3_JLSL");
+ TestDicomSampleImage("test/compsamples_jpegls/IMAGES/JLSL/MR4_JLSL");
+ TestDicomSampleImage("test/compsamples_jpegls/IMAGES/JLSL/NM1_JLSL");
+ TestDicomSampleImage("test/compsamples_jpegls/IMAGES/JLSL/RG1_JLSL");
+ TestDicomSampleImage("test/compsamples_jpegls/IMAGES/JLSL/RG2_JLSL");
+ TestDicomSampleImage("test/compsamples_jpegls/IMAGES/JLSL/RG3_JLSL");
+ TestDicomSampleImage("test/compsamples_jpegls/IMAGES/JLSL/SC1_JLSL");
+}
diff --git a/test/main.cpp b/test/main.cpp
index 7345087..2e3a11c 100644
--- a/test/main.cpp
+++ b/test/main.cpp
@@ -1,263 +1,568 @@
-//
-// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
-//
-
-
-#include "config.h"
-#include <iostream>
-#include <vector>
-
-#include "../interface.h"
-#include "../util.h"
-#include "../defaulttraits.h"
-#include "../losslesstraits.h"
-#include "../colortransform.h"
-#include "../streams.h"
-#include "../processline.h"
-
-#include "util.h"
-
-typedef const char* SZC;
-
-
-bool ScanFile(SZC strNameEncoded, std::vector<BYTE>* rgbyteFile, JlsParameters* info)
-{
- if (!ReadFile(strNameEncoded, rgbyteFile))
- {
- assert(false);
- return false;
- }
-
- JLS_ERROR err = JpegLsReadHeader(&((*rgbyteFile)[0]), rgbyteFile->size(), info);
- assert(err == OK);
- return err == OK;
-}
-
-
-
-
-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));
- }
-}
-
-
-void TestNoiseImage()
-{
- srand(21344);
- Size size2 = Size(1024, 1024);
- std::vector<BYTE> rgbyteNoise(size2.cx * size2.cy);
-
- for (int line = 0; line<size2.cy; ++line)
- {
- for (int icol= 0; icol<size2.cx; ++icol)
- {
- BYTE val = BYTE(rand());
- rgbyteNoise[line*size2.cx + icol] = BYTE(val & 0x7F);// < line ? val : 0;
- }
- }
-
- TestRoundTrip("noise", rgbyteNoise, size2, 7, 1);
-}
-
-
-
-void TestBgra()
-{
- char rgbyteTest[] = "RGBARGBARGBARGBA1234";
- char rgbyteComp[] = "BGRABGRABGRABGRA1234";
- TransformRgbToBgr(rgbyteTest, 4, 4);
- assert(strcmp(rgbyteTest, rgbyteComp) == 0);
-}
-
-
-void TestBgr()
-{
- JlsParameters info;
- std::vector<BYTE> rgbyteEncoded;
- ScanFile("test/conformance/T8C2E3.JLS", &rgbyteEncoded, &info);
- std::vector<BYTE> rgbyteDecoded(info.width * info.height * info.components);
-
- info.outputBgr = true;
-
- JLS_ERROR err = JpegLsDecode(&rgbyteDecoded[0], rgbyteDecoded.size(), &rgbyteEncoded[0], rgbyteEncoded.size(), &info);
- assert(err == OK);
-
- assert(rgbyteDecoded[0] == 0x69);
- assert(rgbyteDecoded[1] == 0x77);
- assert(rgbyteDecoded[2] == 0xa1);
- assert(rgbyteDecoded[info.width * 6 + 3] == 0x2d);
- assert(rgbyteDecoded[info.width * 6 + 4] == 0x43);
- assert(rgbyteDecoded[info.width * 6 + 5] == 0x4d);
-
-}
-
-
-void TestTooSmallOutputBuffer()
-{
- std::vector<BYTE> rgbyteCompressed;
- if (!ReadFile("test/lena8b.jls", &rgbyteCompressed, 0))
- return;
-
- std::vector<BYTE> rgbyteOut(512 * 511);
- JLS_ERROR error = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), &rgbyteCompressed[0], int(rgbyteCompressed.size()), NULL);
-
- assert(error == UncompressedBufferTooSmall);
-}
-
-
-void TestDecodeRect()
-{
- std::vector<BYTE> rgbyteCompressed;
- JlsParameters info;
- if (!ScanFile("test/lena8b.jls", &rgbyteCompressed, &info))
- return;
-
- std::vector<BYTE> rgbyteOutFull(info.width*info.height*info.components);
- JLS_ERROR error = JpegLsDecode(&rgbyteOutFull[0], rgbyteOutFull.size(), &rgbyteCompressed[0], int(rgbyteCompressed.size()), NULL);
- assert(error == OK);
-
- JlsRect rect = { 128, 128, 256, 1 };
- std::vector<BYTE> rgbyteOut(rect.Width * rect.Height);
- rgbyteOut.push_back(0x1f);
- error = JpegLsDecodeRect(&rgbyteOut[0], rgbyteOut.size(), &rgbyteCompressed[0], int(rgbyteCompressed.size()), rect, NULL);
- assert(error == OK);
-
- assert(memcmp(&rgbyteOutFull[rect.X + rect.Y*512], &rgbyteOut[0], rect.Width * rect.Height) == 0);
- assert(rgbyteOut[rect.Width * rect.Height] == 0x1f);
-}
-
-
-void TestColorTransforms_HpImages();
-void TestConformance();
-void TestSampleAnnexH3();
-void PerformanceTests();
-void DamagedBitstreamTests();
-void TestDicomWG4Images();
-
-void UnitTest()
-{
- TestDecodeRect();
-
- printf("Test Traits\r\n");
- TestTraits16bit();
- TestTraits8bit();
-
- printf("Windows bitmap BGR/BGRA output\r\n");
- TestBgr();
- TestBgra();
-
- printf("Test Small buffer\r\n");
- TestTooSmallOutputBuffer();
-
- printf("Test Conformance\r\n");
- TestConformance();
-
- printf("Test Color transform equivalence on HP images\r\n");
- TestColorTransforms_HpImages();
-
- printf("Test Annex H3\r\n");
- TestSampleAnnexH3();
-
- TestNoiseImage();
-}
-
-
-int main(int argc, char* argv[])
-{
- if (argc == 1)
- {
- printf("CharLS test runner.\r\nOptions: -unittest, -bitstreamdamage, -performance, -dontwait\r\n");
- return 0;
- }
-
- bool wait = true;
- for (int i = 1; i < argc; ++i)
- {
- std::string str = argv[i];
- if (str.compare("-unittest") == 0)
- {
- UnitTest();
- continue;
- }
-
- if (str.compare("-bitstreamdamage") == 0)
- {
- DamagedBitstreamTests();
- continue;
- }
-
- if (str.compare("-performance") == 0)
- {
- PerformanceTests();
- continue;
- }
-
- if (str.compare("-dicom") == 0)
- {
- TestDicomWG4Images();
- continue;
- }
-
- if (str.compare("-dontwait") == 0)
- {
- wait = false;
- continue;
- }
-
- printf("Option not understood: %s\r\n", argv[i]);
- break;
-
- }
-
- if (wait)
- {
- char c;
- std::cin >> c;
- return 0;
- }
-}
-
+//
+// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
+
+
+#include "config.h"
+#include <sstream>
+#include <fstream>
+#include <vector>
+#include "../src/interface.h"
+#include "../src/util.h"
+#include "../src/header.h"
+#include "../src/defaulttraits.h"
+#include "../src/losslesstraits.h"
+#include "../src/colortransform.h"
+#include "../src/jpegmarker.h"
+#include "../src/processline.h"
+
+#include "util.h"
+
+typedef const char* SZC;
+
+const std::ios_base::openmode mode_input = std::ios_base::in | std::ios::binary;
+const std::ios_base::openmode mode_output = std::ios_base::out | std::ios::binary;
+
+
+bool ScanFile(SZC strNameEncoded, std::vector<BYTE>* rgbyteFile, JlsParameters* info)
+{
+ if (!ReadFile(strNameEncoded, rgbyteFile))
+ {
+ ASSERT(false);
+ return false;
+ }
+ std::basic_filebuf<char> jlsFile;
+ jlsFile.open(strNameEncoded, mode_input);
+
+ ByteStreamInfo rawStreamInfo = {&jlsFile, NULL, 0};
+
+ JLS_ERROR err = JpegLsReadHeaderStream(rawStreamInfo, info);
+ ASSERT(err == OK);
+ return err == OK;
+}
+
+
+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));
+ }
+}
+
+
+std::vector<BYTE> MakeSomeNoise(int length, int bitcount, int seed)
+{
+ srand(seed);
+ std::vector<BYTE> rgbyteNoise(length);
+ BYTE mask = (1 << bitcount) - 1;
+ for (int icol= 0; icol<length; ++icol)
+ {
+ BYTE val = BYTE(rand());
+ rgbyteNoise[icol] = BYTE(val & mask);
+ }
+ return rgbyteNoise;
+}
+
+
+void TestNoiseImage()
+{
+ Size size2 = Size(512, 512);
+
+ for (int bitDepth = 8; bitDepth >=2; --bitDepth)
+ {
+ std::stringstream label;
+ label << "noise, bitdepth: " << bitDepth;
+
+ std::vector<BYTE> noiseBytes = MakeSomeNoise(size2.cx * size2.cy, bitDepth, 21344);
+ TestRoundTrip(label.str().c_str(), noiseBytes, size2, bitDepth, 1);
+ }
+}
+
+
+void TestFailOnTooSmallOutputBuffer()
+{
+ Size size = Size(8, 8);
+ std::vector<BYTE> rgbyteRaw = MakeSomeNoise(8 * 8, 8, 21344);
+
+ std::vector<BYTE> rgbyteCompressed(1);
+
+ JlsParameters info = JlsParameters();
+ info.components = 1;
+ info.bitspersample = 8;
+ info.height = size.cy;
+ info.width = size.cx;
+
+ size_t compressedLength;
+ JLS_ERROR err = JpegLsEncode(&rgbyteCompressed[0], rgbyteCompressed.size(), &compressedLength, &rgbyteRaw[0], rgbyteRaw.size(), &info);
+ ASSERT(err == CompressedBufferTooSmall);
+}
+
+
+void TestBgra()
+{
+ char rgbyteTest[] = "RGBARGBARGBARGBA1234";
+ char rgbyteComp[] = "BGRABGRABGRABGRA1234";
+ TransformRgbToBgr(rgbyteTest, 4, 4);
+ ASSERT(strcmp(rgbyteTest, rgbyteComp) == 0);
+}
+
+
+void TestBgr()
+{
+ JlsParameters info;
+ std::vector<BYTE> rgbyteEncoded;
+ ScanFile("test/conformance/T8C2E3.JLS", &rgbyteEncoded, &info);
+ std::vector<BYTE> rgbyteDecoded(info.width * info.height * info.components);
+
+ info.outputBgr = true;
+
+ JLS_ERROR err = JpegLsDecode(&rgbyteDecoded[0], rgbyteDecoded.size(), &rgbyteEncoded[0], rgbyteEncoded.size(), &info);
+ ASSERT(err == OK);
+
+ ASSERT(rgbyteDecoded[0] == 0x69);
+ ASSERT(rgbyteDecoded[1] == 0x77);
+ ASSERT(rgbyteDecoded[2] == 0xa1);
+ ASSERT(rgbyteDecoded[info.width * 6 + 3] == 0x2d);
+ ASSERT(rgbyteDecoded[info.width * 6 + 4] == 0x43);
+ ASSERT(rgbyteDecoded[info.width * 6 + 5] == 0x4d);
+}
+
+
+void TestTooSmallOutputBuffer()
+{
+ std::vector<BYTE> rgbyteCompressed;
+ if (!ReadFile("test/lena8b.jls", &rgbyteCompressed, 0))
+ return;
+
+ std::vector<BYTE> rgbyteOut(512 * 511);
+ JLS_ERROR error = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), &rgbyteCompressed[0], int(rgbyteCompressed.size()), NULL);
+
+ ASSERT(error == UncompressedBufferTooSmall);
+}
+
+
+void TestBadImage()
+{
+ std::vector<BYTE> rgbyteCompressed;
+ if (!ReadFile("test/BadCompressedStream.jls", &rgbyteCompressed, 0))
+ return;
+
+ std::vector<BYTE> rgbyteOut(2500 * 3000 * 2);
+ JLS_ERROR error = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), &rgbyteCompressed[0], int(rgbyteCompressed.size()), NULL);
+
+ ASSERT(error == UncompressedBufferTooSmall);
+}
+
+
+void TestDecodeBitStreamWithNoMarkerStart()
+{
+ BYTE encodedData[2] = { 0x33, 0x33 };
+ BYTE output[1000];
+
+ JLS_ERROR error = JpegLsDecode(output, 1000, encodedData, 2, NULL);
+ ASSERT(error == MissingJpegMarkerStart);
+}
+
+
+void TestDecodeBitStreamWithUnsupportedEncoding()
+{
+ BYTE encodedData[6] = { 0xFF, 0xD8, // Start Of Image (JPEG_SOI)
+ 0xFF, 0xC3, // Start Of Frame (lossless, huffman) (JPEG_SOF_3)
+ 0x00, 0x00 // Lenght of data of the marker
+ };
+ BYTE output[1000];
+
+ JLS_ERROR error = JpegLsDecode(output, 1000, encodedData, 6, NULL);
+ ASSERT(error == UnsupportedEncoding);
+}
+
+
+void TestDecodeBitStreamWithUnknownJpegMarker()
+{
+ BYTE encodedData[6] = { 0xFF, 0xD8, // Start Of Image (JPEG_SOI)
+ 0xFF, 0x01, // Undefined marker
+ 0x00, 0x00 // Lenght of data of the marker
+ };
+ BYTE output[1000];
+
+ JLS_ERROR error = JpegLsDecode(output, 1000, encodedData, 6, NULL);
+ ASSERT(error == UnknownJpegMarker);
+}
+
+
+void TestDecodeRect()
+{
+ std::vector<BYTE> rgbyteCompressed;
+ JlsParameters info;
+ if (!ScanFile("test/lena8b.jls", &rgbyteCompressed, &info))
+ return;
+
+ std::vector<BYTE> rgbyteOutFull(info.width*info.height*info.components);
+ JLS_ERROR error = JpegLsDecode(&rgbyteOutFull[0], rgbyteOutFull.size(), &rgbyteCompressed[0], int(rgbyteCompressed.size()), NULL);
+ ASSERT(error == OK);
+
+ JlsRect rect = { 128, 128, 256, 1 };
+ std::vector<BYTE> rgbyteOut(rect.Width * rect.Height);
+ rgbyteOut.push_back(0x1f);
+ error = JpegLsDecodeRect(&rgbyteOut[0], rgbyteOut.size(), &rgbyteCompressed[0], int(rgbyteCompressed.size()), rect, NULL);
+ ASSERT(error == OK);
+
+ ASSERT(memcmp(&rgbyteOutFull[rect.X + rect.Y*512], &rgbyteOut[0], rect.Width * rect.Height) == 0);
+ ASSERT(rgbyteOut[rect.Width * rect.Height] == 0x1f);
+}
+
+
+void TestEncodeFromStream(const char* file, int offset, int width, int height, int bpp, int ccomponent, int ilv, size_t expectedLength)
+{
+ std::basic_filebuf<char> myFile; // On the stack
+ myFile.open(file, mode_input);
+ ASSERT(myFile.is_open());
+
+ myFile.pubseekoff(std::streamoff(offset), std::ios_base::cur);
+ ByteStreamInfo rawStreamInfo = {&myFile, NULL, 0};
+
+ BYTE* compressed = new BYTE[width * height * ccomponent * 2];
+ JlsParameters params = JlsParameters();
+ params.height = height;
+ params.width = width;
+ params.components = ccomponent;
+ params.bitspersample= bpp;
+ params.ilv = (interleavemode) ilv;
+ size_t bytesWritten = 0;
+
+ JpegLsEncodeStream(FromByteArray(compressed, width * height * ccomponent * 2), &bytesWritten, rawStreamInfo, ¶ms);
+ ASSERT(bytesWritten == expectedLength);
+
+ delete[] compressed;
+ myFile.close();
+}
+
+
+bool DecodeToPnm(std::istream& jlsFile, std::ostream& pnmFile)
+{
+ ByteStreamInfo compressedByteStream = {jlsFile.rdbuf(), NULL, 0};
+
+ JlsParameters info = JlsParameters();
+ JLS_ERROR err = JpegLsReadHeaderStream(compressedByteStream, &info);
+ if (err != OK)
+ return false;
+ jlsFile.seekg(0);
+
+ int maxval = (1 << info.bitspersample) - 1;
+
+ int bytesPerSample = maxval > 255 ? 2 : 1;
+ std::vector<BYTE> outputBuffer(info.width * info.height * bytesPerSample);
+ ByteStreamInfo outputInfo = FromByteArray(outputBuffer.data(), outputBuffer.size());
+ JpegLsDecodeStream(outputInfo, compressedByteStream, &info);
+
+ // PNM format requires most significant byte first (big endian).
+ if (bytesPerSample == 2)
+ {
+ for (std::vector<BYTE>::iterator i = outputBuffer.begin(); i != outputBuffer.end(); i += 2)
+ {
+ std::iter_swap(i, i + 1);
+ }
+ }
+
+ int magicNumber = info.components == 3 ? 6 : 5;
+ pnmFile << 'P' << magicNumber << std::endl << info.width << ' ' << info.height << std::endl << maxval << std::endl;
+ pnmFile.write(reinterpret_cast<char*>(&outputBuffer[0]), outputBuffer.size());
+
+ return true;
+}
+
+
+std::vector<int> readPnmHeader(std::istream& pnmFile)
+{
+ std::vector<int> readValues;
+
+ char first = (char) pnmFile.get();
+
+ if (first != 'P')
+ return readValues;
+
+ while (readValues.size() < 4)
+ {
+ std::string bytes;
+ std::getline(pnmFile, bytes);
+ std::stringstream line(bytes);
+
+ while (readValues.size() < 4)
+ {
+ int value = -1;
+ line >> value;
+ if (value <= 0)
+ break;
+
+ readValues.push_back(value);
+ }
+ }
+ return readValues;
+}
+
+
+bool EncodePnm(std::istream& pnmFile, std::ostream& jlsFileStream)
+{
+ std::vector<int> readValues = readPnmHeader(pnmFile);
+
+ if (readValues.size() !=4)
+ return false;
+
+ ByteStreamInfo rawStreamInfo = {pnmFile.rdbuf(), NULL, 0};
+ ByteStreamInfo jlsStreamInfo = {jlsFileStream.rdbuf(), NULL, 0};
+
+ JlsParameters params = JlsParameters();
+ int componentCount = readValues[0] == 6 ? 3 : 1;
+ params.width = readValues[1];
+ params.height = readValues[2];
+ params.components = componentCount;
+ params.bitspersample= log_2(readValues[3]+1);
+ params.ilv = componentCount == 3 ? ILV_LINE : ILV_NONE;
+ params.colorTransform = XFORM_BIGENDIAN;
+ size_t bytesWritten = 0;
+
+ JpegLsEncodeStream(jlsStreamInfo, &bytesWritten, rawStreamInfo, ¶ms);
+ return true;
+}
+
+
+void TestDecodeFromStream(const char* strNameEncoded)
+{
+ std::basic_filebuf<char> jlsFile;
+ jlsFile.open(strNameEncoded, mode_input);
+ ASSERT(jlsFile.is_open());
+ ByteStreamInfo compressedByteStream = {&jlsFile, NULL, 0};
+
+ JlsParameters info = JlsParameters();
+ JLS_ERROR err = JpegLsReadHeaderStream(compressedByteStream, &info);
+
+ jlsFile.pubseekpos(std::ios::beg, std::ios_base::in);
+
+ std::basic_stringbuf<char> buf;
+ ByteStreamInfo rawStreamInfo = {&buf, NULL, 0};
+
+ err = JpegLsDecodeStream(rawStreamInfo, compressedByteStream, NULL);
+ ////size_t outputCount = buf.str().size();
+
+ ASSERT(err == OK);
+ //ASSERT(outputCount == 512 * 512);
+}
+
+
+JLS_ERROR DecodeRaw(const char* strNameEncoded, const char* strNameOutput)
+{
+ std::fstream jlsFile(strNameEncoded, mode_input);
+ ByteStreamInfo compressedByteStream = {jlsFile.rdbuf(), NULL, 0};
+
+ std::fstream rawFile(strNameOutput, mode_output);
+ ByteStreamInfo rawStream = {rawFile.rdbuf(), NULL, 0};
+
+ JLS_ERROR value = JpegLsDecodeStream(rawStream, compressedByteStream, NULL);
+ jlsFile.close();
+ rawFile.close();
+
+ return value;
+}
+
+
+void TestEncodeFromStream()
+{
+ ////TestDecodeFromStream("test/user_supplied/output.jls");
+
+ TestEncodeFromStream("test/0015.RAW", 0, 1024, 1024, 8, 1,0, 0x3D3ee);
+ //TestEncodeFromStream("test/MR2_UNC", 1728, 1024, 1024, 16, 1,0, 0x926e1);
+ TestEncodeFromStream("test/conformance/TEST8.PPM", 15, 256, 256, 8,3,2, 99734);
+ TestEncodeFromStream("test/conformance/TEST8.PPM", 15, 256, 256, 8,3,1, 100615);
+}
+
+
+void TestColorTransforms_HpImages();
+void TestConformance();
+void TestSampleAnnexH3();
+void PerformanceTests(int loopCount);
+void DamagedBitstreamTests();
+void TestDicomWG4Images();
+
+void UnitTest()
+{
+// TestBadImage();
+
+ printf("Test Conformance\r\n");
+ TestEncodeFromStream();
+ TestConformance();
+
+ TestDecodeRect();
+
+ printf("Test Traits\r\n");
+ TestTraits16bit();
+ TestTraits8bit();
+
+ printf("Windows bitmap BGR/BGRA output\r\n");
+ TestBgr();
+ TestBgra();
+
+ printf("Test Small buffer\r\n");
+ TestTooSmallOutputBuffer();
+
+ TestFailOnTooSmallOutputBuffer();
+
+ printf("Test Color transform equivalence on HP images\r\n");
+ TestColorTransforms_HpImages();
+
+ printf("Test Annex H3\r\n");
+ TestSampleAnnexH3();
+
+ TestNoiseImage();
+
+ printf("Test robustness\r\n");
+ TestDecodeBitStreamWithNoMarkerStart();
+ TestDecodeBitStreamWithUnsupportedEncoding();
+ TestDecodeBitStreamWithUnknownJpegMarker();
+}
+
+
+int main(int argc, char* argv[])
+{
+ if (argc == 1)
+ {
+ printf("CharLS test runner.\r\nOptions: -unittest, -bitstreamdamage, -performance[:loop count], -dontwait -decoderaw -encodepnm -decodetopnm \r\n");
+ return 0;
+ }
+
+ bool wait = true;
+ for (int i = 1; i < argc; ++i)
+ {
+ std::string str = argv[i];
+ if (str.compare("-unittest") == 0)
+ {
+ UnitTest();
+ continue;
+ }
+
+ if (str.compare("-decoderaw") == 0)
+ {
+ if (i != 1 || argc != 4)
+ {
+ printf("Syntax: -decoderaw inputfile outputfile \r\n");
+ return 0;
+ }
+ return DecodeRaw(argv[2],argv[3]);
+ }
+
+ if (str.compare("-decodetopnm") == 0)
+ {
+ if (i != 1 || argc != 4)
+ {
+ printf("Syntax: -decodetopnm inputfile outputfile \r\n");
+ return 0;
+ }
+ std::fstream pnmFile(argv[3], mode_output);
+ std::fstream jlsFile(argv[2], mode_input);
+
+ return DecodeToPnm(jlsFile, pnmFile);
+ }
+
+ if (str.compare("-encodepnm") == 0)
+ {
+ if (i != 1 || argc != 4)
+ {
+ printf("Syntax: -encodepnm inputfile outputfile \r\n");
+ return 0;
+ }
+ std::fstream pnmFile(argv[2], mode_input);
+ std::fstream jlsFile(argv[3], mode_output);
+
+ return EncodePnm(pnmFile,jlsFile);
+ }
+
+ if (str.compare("-bitstreamdamage") == 0)
+ {
+ DamagedBitstreamTests();
+ continue;
+ }
+
+ if (str.compare(0, 12, "-performance") == 0)
+ {
+ int loopCount = 1;
+
+ // Extract the optional loop count from the command line. Longer running tests make the measurements more reliable.
+ size_t index = str.find(':');
+ if (index != std::string::npos)
+ {
+ loopCount = atoi(str.substr(++index).c_str());
+ if (loopCount < 1)
+ {
+ printf("Loop count not understood or invalid: %s\r\n", str.c_str());
+ break;
+ }
+ }
+
+ PerformanceTests(loopCount);
+ continue;
+ }
+
+ if (str.compare("-dicom") == 0)
+ {
+ TestDicomWG4Images();
+ continue;
+ }
+
+ if (str.compare("-dontwait") == 0)
+ {
+ wait = false;
+ continue;
+ }
+
+ printf("Option not understood: %s\r\n", argv[i]);
+ break;
+ }
+
+ if (wait)
+ {
+ char c;
+ std::cin >> c;
+ return 0;
+ }
+}
diff --git a/test/performance.cpp b/test/performance.cpp
index 983fe89..a2c7570 100644
--- a/test/performance.cpp
+++ b/test/performance.cpp
@@ -1,93 +1,87 @@
-//
-// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
-//
-
-
-#include "config.h"
-#include <iostream>
-#include <vector>
-
-#include "../interface.h"
-#include "../util.h"
-#include "../defaulttraits.h"
-#include "../losslesstraits.h"
-#include "../colortransform.h"
-#include "../streams.h"
-#include "../processline.h"
-
-#include "util.h"
-
-
-
-void TestFile16BitAs12(SZC strName, int ioffs, Size size2, int ccomp, bool littleEndianFile)
-{
- std::vector<BYTE> rgbyteUncompressed;
- if (!ReadFile(strName, &rgbyteUncompressed, ioffs))
- return;
-
- FixEndian(&rgbyteUncompressed, littleEndianFile);
-
- USHORT* pushort = (USHORT*)&rgbyteUncompressed[0];
-
- for (int i = 0; i < (int)rgbyteUncompressed.size()/2; ++i)
- {
- pushort[i] = pushort[i] >> 4;
- }
-
- TestRoundTrip(strName, rgbyteUncompressed, size2, 12, ccomp);
-}
-
-
-
-void TestPerformance()
-{
- TestFile("test/bad.raw", 0, Size(512, 512), 8, 1);
-
- // RGBA image (This is a common PNG sample)
- TestFile("test/alphatest.raw", 0, Size(380, 287), 8, 4);
-
- Size size1024 = Size(1024, 1024);
- Size size512 = Size(512, 512);
-
- // 16 bit mono
- TestFile("test/MR2_UNC", 1728, size1024, 16, 1, true);
-
- // 8 bit mono
- TestFile("test/0015.raw", 0, size1024, 8, 1);
- TestFile("test/lena8b.raw", 0, size512, 8, 1);
-
-
- // 8 bit color
- TestFile("test/desktop.ppm", 40, Size(1280,1024), 8, 3);
-
- // 12 bit RGB
- TestFile("test/SIEMENS-MR-RGB-16Bits.dcm", -1, Size(192,256), 12, 3, true);
- TestFile16BitAs12("test/DSC_5455.raw", 142949, Size(300,200), 3, true);
-
- // 16 bit RGB
- TestFile("test/DSC_5455.raw", 142949, Size(300,200), 16, 3, true);
-}
-
-
-void TestLargeImagePerformance()
-{
-
- TestFile("test/rgb8bit/artificial.ppm", 17, Size(3072,2048), 8, 3);
- TestFile("test/rgb8bit/bridge.ppm", 17, Size(2749,4049), 8, 3);
- TestFile("test/rgb8bit/flower_foveon.ppm", 17, Size(2268,1512), 8, 3);
- //TestFile("test/rgb8bit/big_building.ppm", 17, Size(7216,5412), 8, 3);
- // TestFile("test/rgb16bit/bridge.ppm", 19, Size(2749,4049), 16, 3, true);
-}
-
-
-void PerformanceTests()
-{
- printf("Test Perf\r\n");
- TestPerformance();
-
-#ifndef _DEBUG
- printf("Test Large Images Performance\r\n");
- TestLargeImagePerformance();
-#endif
-
-}
\ No newline at end of file
+//
+// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
+
+
+#include "config.h"
+#include <iostream>
+#include <vector>
+
+#include "../src/interface.h"
+#include "../src/util.h"
+#include "../src/colortransform.h"
+#include "../src/jpegmarker.h"
+#include "../src/processline.h"
+
+#include "util.h"
+
+
+
+void TestFile16BitAs12(SZC strName, int ioffs, Size size2, int ccomp, bool littleEndianFile)
+{
+ std::vector<BYTE> rgbyteUncompressed;
+ if (!ReadFile(strName, &rgbyteUncompressed, ioffs))
+ return;
+
+ FixEndian(&rgbyteUncompressed, littleEndianFile);
+
+ USHORT* pushort = (USHORT*)&rgbyteUncompressed[0];
+
+ for (int i = 0; i < (int)rgbyteUncompressed.size()/2; ++i)
+ {
+ pushort[i] = pushort[i] >> 4;
+ }
+
+ TestRoundTrip(strName, rgbyteUncompressed, size2, 12, ccomp);
+}
+
+
+void TestPerformance(int loopCount)
+{
+ ////TestFile("test/bad.raw", 0, Size(512, 512), 8, 1);
+
+ // RGBA image (This is a common PNG sample)
+ TestFile("test/alphatest.raw", 0, Size(380, 287), 8, 4, false, loopCount);
+
+ Size size1024 = Size(1024, 1024);
+ Size size512 = Size(512, 512);
+
+ // 16 bit mono
+ TestFile("test/MR2_UNC", 1728, size1024, 16, 1, true, loopCount);
+
+ // 8 bit mono
+ TestFile("test/0015.raw", 0, size1024, 8, 1, false, loopCount);
+ TestFile("test/lena8b.raw", 0, size512, 8, 1, false, loopCount);
+
+ // 8 bit color
+ TestFile("test/desktop.ppm", 40, Size(1280, 1024), 8, 3, false, loopCount);
+
+ // 12 bit RGB
+ TestFile("test/SIEMENS-MR-RGB-16Bits.dcm", -1, Size(192, 256), 12, 3, true, loopCount);
+ TestFile16BitAs12("test/DSC_5455.raw", 142949, Size(300, 200), 3, true);
+
+ // 16 bit RGB
+ TestFile("test/DSC_5455.raw", 142949, Size(300, 200), 16, 3, true, loopCount);
+}
+
+
+void TestLargeImagePerformance(int loopCount)
+{
+ TestFile("test/rgb8bit/artificial.ppm", 17, Size(3072, 2048), 8, 3, false, loopCount);
+ TestFile("test/rgb8bit/bridge.ppm", 17, Size(2749, 4049), 8, 3, false, loopCount);
+ TestFile("test/rgb8bit/flower_foveon.ppm", 17, Size(2268, 1512), 8, 3, false, loopCount);
+ //TestFile("test/rgb8bit/big_building.ppm", 17, Size(7216,5412), 8, 3);
+ // TestFile("test/rgb16bit/bridge.ppm", 19, Size(2749,4049), 16, 3, true);
+}
+
+
+void PerformanceTests(int loopCount)
+{
+ printf("Test Perf (with loop count %i)\r\n", loopCount);
+ TestPerformance(loopCount);
+
+#ifndef _DEBUG
+ printf("Test Large Images Performance\r\n");
+ TestLargeImagePerformance(loopCount);
+#endif
+}
diff --git a/test/test.vcproj b/test/test.vcproj
deleted file mode 100644
index bec453c..0000000
--- a/test/test.vcproj
+++ /dev/null
@@ -1,415 +0,0 @@
-<?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"
- />
- <Platform
- Name="x64"
- />
- </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="0"
- WarningLevel="4"
- Detect64BitPortabilityProblems="false"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- OutputFile="$(OutDir)/test.exe"
- LinkIncremental="2"
- AdditionalLibraryDirectories="$(OutDir)"
- 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="Debug|x64"
- OutputDirectory="..\$(PlatformName)\$(ConfigurationName)"
- IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
- ConfigurationType="1"
- InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
- CharacterSet="2"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- TargetEnvironment="3"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="1"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="false"
- DebugInformationFormat="3"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- OutputFile="$(OutDir)/test.exe"
- LinkIncremental="2"
- AdditionalLibraryDirectories="$(OutDir)"
- GenerateDebugInformation="true"
- ProgramDatabaseFile="$(OutDir)/test.pdb"
- SubSystem="1"
- RandomizedBaseAddress="1"
- DataExecutionPrevention="0"
- TargetMachine="17"
- />
- <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;_CONSOLE"
- StringPooling="true"
- RuntimeLibrary="0"
- EnableFunctionLevelLinking="true"
- UsePrecompiledHeader="0"
- WarningLevel="4"
- Detect64BitPortabilityProblems="false"
- DebugInformationFormat="3"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- OutputFile="$(OutDir)/test.exe"
- LinkIncremental="1"
- AdditionalLibraryDirectories="$(OutDir)"
- GenerateDebugInformation="true"
- SubSystem="1"
- OptimizeReferences="1"
- 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>
- <Configuration
- Name="Release|x64"
- OutputDirectory="..\$(PlatformName)\$(ConfigurationName)"
- IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
- ConfigurationType="1"
- InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
- CharacterSet="2"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- TargetEnvironment="3"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="2"
- InlineFunctionExpansion="2"
- OmitFramePointers="true"
- PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
- StringPooling="true"
- RuntimeLibrary="0"
- EnableFunctionLevelLinking="true"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="false"
- DebugInformationFormat="3"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- OutputFile="$(OutDir)/test.exe"
- LinkIncremental="1"
- AdditionalLibraryDirectories="$(OutDir)"
- GenerateDebugInformation="true"
- SubSystem="1"
- OptimizeReferences="1"
- EnableCOMDATFolding="2"
- RandomizedBaseAddress="1"
- DataExecutionPrevention="0"
- TargetMachine="17"
- />
- <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=".\bitstreamdamage.cpp"
- >
- </File>
- <File
- RelativePath=".\compliance.cpp"
- >
- </File>
- <File
- RelativePath=".\dicomsamples.cpp"
- >
- </File>
- <File
- RelativePath=".\main.cpp"
- >
- </File>
- <File
- RelativePath=".\performance.cpp"
- >
- </File>
- <File
- RelativePath=".\time.cpp"
- >
- </File>
- <File
- RelativePath=".\util.cpp"
- >
- </File>
- </Filter>
- <Filter
- Name="Header Files"
- Filter="h;hpp;hxx;hm;inl;inc"
- >
- <File
- RelativePath=".\config.h"
- >
- </File>
- <File
- RelativePath=".\time.h"
- >
- </File>
- <File
- RelativePath=".\util.h"
- >
- </File>
- </Filter>
- <File
- RelativePath=".\CMakeLists.txt"
- >
- </File>
- <File
- RelativePath="lena8b.jls"
- >
- </File>
- <File
- RelativePath="conformance\T16E0.JLS"
- >
- </File>
- <File
- RelativePath="conformance\TEST16.PGM"
- >
- </File>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
diff --git a/test/time.cpp b/test/time.cpp
index e205a30..f8a028e 100644
--- a/test/time.cpp
+++ b/test/time.cpp
@@ -1,39 +1,38 @@
-//
-// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
-//
-
-
-// for best accuracy, getTime is implemented platform dependent.
-// to avoid a global include of windows.h, this is a separete file.
-
-
-#include "config.h"
-
-#if defined(_WIN32)
-
-#include <windows.h>
-
-
-double getTime()
-{
- LARGE_INTEGER time;
- ::QueryPerformanceCounter(&time);
- LARGE_INTEGER freq;
- ::QueryPerformanceFrequency(&freq);
-
- return double(time.LowPart) * 1000.0/double(freq.LowPart);
-}
-
-#else
-
-#include <sys/time.h>
-double getTime()
-{
-
- timeval t;
- gettimeofday(&t, 0);
-
- return (t.tv_sec * 1000000.0 + t.tv_usec) / 1000.0;
-}
-
-#endif
+//
+// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
+
+
+// for best accuracy, getTime is implemented platform dependent.
+// to avoid a global include of windows.h, this is a separate file.
+
+
+#include "config.h"
+
+#if defined(_WIN32)
+
+#include <windows.h>
+
+// returns a point in time in milli seconds (can only be used for time differences, not an absolute time)
+double getTime()
+{
+ LARGE_INTEGER time;
+ ::QueryPerformanceCounter(&time);
+ LARGE_INTEGER freq;
+ ::QueryPerformanceFrequency(&freq);
+
+ return (double(time.LowPart) * 1000.0) / double(freq.LowPart);
+}
+
+#else
+
+#include <sys/time.h>
+double getTime()
+{
+ timeval t;
+ gettimeofday(&t, 0);
+
+ return (t.tv_sec * 1000000.0 + t.tv_usec) / 1000.0;
+}
+
+#endif
diff --git a/test/time.h b/test/time.h
index daf9535..17ddda5 100644
--- a/test/time.h
+++ b/test/time.h
@@ -1,10 +1,10 @@
-//
-// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
-//
-
-#ifndef TEST_TIME
-#define TEST_TIME
-
-double getTime();
-
-#endif
+//
+// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
+
+#ifndef TEST_TIME
+#define TEST_TIME
+
+double getTime();
+
+#endif
diff --git a/test/util.cpp b/test/util.cpp
index 0e2e5d4..b1855b0 100644
--- a/test/util.cpp
+++ b/test/util.cpp
@@ -1,148 +1,154 @@
-//
-// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
-//
-
-
-#include "config.h"
-#include <iostream>
-#include <vector>
-
-#include "../interface.h"
-#include "../util.h"
-#include "../streams.h"
-
-#include "util.h"
-#include "time.h"
-
-
-bool IsMachineLittleEndian()
-{
- int a = 0xFF000001;
- char* chars = reinterpret_cast<char*>(&a);
- return chars[0] == 0x01;
-}
-
-
-void FixEndian(std::vector<BYTE>* rgbyte, bool littleEndianData)
-{
- if (littleEndianData == IsMachineLittleEndian())
- return;
-
- for (size_t i = 0; i < rgbyte->size()-1; i += 2)
- {
- std::swap((*rgbyte)[i], (*rgbyte)[i + 1]);
- }
-}
-
-
-
-bool ReadFile(SZC strName, std::vector<BYTE>* pvec, int ioffs, int bytes)
-{
- FILE* pfile = fopen(strName, "rb");
- if( !pfile )
- {
- fprintf( stderr, "Could not open %s\n", strName );
- return false;
- }
-
- fseek(pfile, 0, SEEK_END);
- int cbyteFile = ftell(pfile);
- if (ioffs < 0)
- {
- assert(bytes != 0);
- ioffs = cbyteFile - bytes;
- }
- if (bytes == 0)
- {
- bytes = cbyteFile -ioffs;
- }
-
- fseek(pfile, ioffs, SEEK_SET);
- pvec->resize(bytes);
- size_t bytesRead = fread(&(*pvec)[0],1, pvec->size(), pfile);
- fclose(pfile);
- return bytesRead == pvec->size();
-}
-
-
-void WriteFile(SZC strName, std::vector<BYTE>& vec)
-{
- FILE* pfile = fopen(strName, "wb");
- if( !pfile )
- {
- fprintf( stderr, "Could not open %s\n", strName );
- return;
- }
-
- fwrite(&vec[0],1, vec.size(), pfile);
- fclose(pfile);
-}
-
-
-void TestRoundTrip(const char* strName, std::vector<BYTE>& rgbyteRaw, Size size, int cbit, int ccomp)
-{
- std::vector<BYTE> rgbyteCompressed(size.cx *size.cy * ccomp * cbit / 4);
-
- std::vector<BYTE> rgbyteOut(size.cx * size.cy * ((cbit + 7) / 8) * ccomp);
-
- double dblstart = getTime();
-
- JlsParameters info = JlsParameters();
- info.components = ccomp;
- info.bitspersample = cbit;
- info.height = size.cy;
- info.width = size.cx;
-
- if (ccomp == 4)
- {
- info.ilv = ILV_LINE;
- }
- else if (ccomp == 3)
- {
- info.ilv = ILV_LINE;
- info.colorTransform = COLORXFORM_HP1;
- }
-
- size_t compressedLength;
- JLS_ERROR err = JpegLsEncode(&rgbyteCompressed[0], rgbyteCompressed.size(), &compressedLength, &rgbyteRaw[0], rgbyteOut.size(), &info);
- assert(err == OK);
-
- double dwtimeEncodeComplete = getTime();
-
- err = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), &rgbyteCompressed[0], int(compressedLength), NULL);
- assert(err == OK);
-
- double bitspersample = compressedLength * 8 * 1.0 / (ccomp *size.cy * size.cx);
- double dwtimeDecodeComplete = getTime();
- std::cout << "RoundTrip test for: " << strName << "\n\r";
- double decodeTime = dwtimeDecodeComplete - dwtimeEncodeComplete;
- double symbolRate = (ccomp *size.cy * size.cx)/(1000.0 * decodeTime);
- printf("Size:%4ldx%4ld Encode:%7.2f Decode:%7.2f Bps:%5.2f Decode rate:%5.1f M/s \n\r", size.cx, size.cy, dwtimeEncodeComplete - dblstart, dwtimeDecodeComplete - dwtimeEncodeComplete, bitspersample, symbolRate);
- BYTE* pbyteOut = &rgbyteOut[0];
- for (size_t i = 0; i < rgbyteOut.size(); ++i)
- {
- if (rgbyteRaw[i] != pbyteOut[i])
- {
- assert(false);
- break;
- }
- }
-}
-
-
-void TestFile(SZC strName, int ioffs, Size size2, int cbit, int ccomp, bool littleEndianFile)
-{
- int byteCount = size2.cx * size2.cy * ccomp * ((cbit + 7)/8);
- std::vector<BYTE> rgbyteUncompressed;
-
- if (!ReadFile(strName, &rgbyteUncompressed, ioffs, byteCount))
- return;
-
- if (cbit > 8)
- {
- FixEndian(&rgbyteUncompressed, littleEndianFile);
- }
-
- TestRoundTrip(strName, rgbyteUncompressed, size2, cbit, ccomp);
-}
-
+//
+// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
+
+
+#include "config.h"
+#include <iostream>
+#include <vector>
+
+#include "../src/interface.h"
+#include "../src/util.h"
+#include "../src/jpegmarker.h"
+
+#include "util.h"
+#include "time.h"
+
+
+bool IsMachineLittleEndian()
+{
+ int a = 0xFF000001;
+ char* chars = reinterpret_cast<char*>(&a);
+ return chars[0] == 0x01;
+}
+
+
+void FixEndian(std::vector<BYTE>* rgbyte, bool littleEndianData)
+{
+ if (littleEndianData == IsMachineLittleEndian())
+ return;
+
+ for (size_t i = 0; i < rgbyte->size()-1; i += 2)
+ {
+ std::swap((*rgbyte)[i], (*rgbyte)[i + 1]);
+ }
+}
+
+
+
+bool ReadFile(SZC strName, std::vector<BYTE>* pvec, int ioffs, int bytes)
+{
+ FILE* pfile = fopen(strName, "rb");
+ if( !pfile )
+ {
+ fprintf( stderr, "Could not open %s\n", strName );
+ return false;
+ }
+
+ fseek(pfile, 0, SEEK_END);
+ int cbyteFile = ftell(pfile);
+ if (ioffs < 0)
+ {
+ ASSERT(bytes != 0);
+ ioffs = cbyteFile - bytes;
+ }
+ if (bytes == 0)
+ {
+ bytes = cbyteFile -ioffs;
+ }
+
+ fseek(pfile, ioffs, SEEK_SET);
+ pvec->resize(bytes);
+ size_t bytesRead = fread(&(*pvec)[0],1, pvec->size(), pfile);
+ fclose(pfile);
+ return bytesRead == pvec->size();
+}
+
+
+void WriteFile(SZC strName, std::vector<BYTE>& vec)
+{
+ FILE* pfile = fopen(strName, "wb");
+ if( !pfile )
+ {
+ fprintf( stderr, "Could not open %s\n", strName );
+ return;
+ }
+
+ fwrite(&vec[0],1, vec.size(), pfile);
+ fclose(pfile);
+}
+
+
+void TestRoundTrip(const char* strName, std::vector<BYTE>& rgbyteRaw, Size size, int cbit, int ccomp, int loopCount)
+{
+ std::vector<BYTE> rgbyteCompressed(size.cx *size.cy * ccomp * cbit / 4);
+
+ std::vector<BYTE> rgbyteOut(size.cx * size.cy * ((cbit + 7) / 8) * ccomp);
+
+ JlsParameters info = JlsParameters();
+ info.components = ccomp;
+ info.bitspersample = cbit;
+ info.height = size.cy;
+ info.width = size.cx;
+
+ if (ccomp == 4)
+ {
+ info.ilv = ILV_LINE;
+ }
+ else if (ccomp == 3)
+ {
+ info.ilv = ILV_LINE;
+ info.colorTransform = COLORXFORM_HP1;
+ }
+
+ size_t compressedLength = 0;
+ double dwtimeEncodeStart = getTime();
+ for (int i = 0; i < loopCount; ++i)
+ {
+ JLS_ERROR err = JpegLsEncode(&rgbyteCompressed[0], rgbyteCompressed.size(), &compressedLength, &rgbyteRaw[0], rgbyteOut.size(), &info);
+ ASSERT(err == OK);
+ }
+ double dwtimeEncodeComplete = getTime();
+
+ double dwtimeDecodeStart = getTime();
+ for (int i = 0; i < loopCount; ++i)
+ {
+ JLS_ERROR err = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), &rgbyteCompressed[0], int(compressedLength), NULL);
+ ASSERT(err == OK);
+ }
+ double dwtimeDecodeComplete = getTime();
+
+ double bitspersample = compressedLength * 8 * 1.0 / (ccomp *size.cy * size.cx);
+ std::cout << "RoundTrip test for: " << strName << "\n\r";
+ double encodeTime = (dwtimeEncodeComplete - dwtimeEncodeStart) / loopCount;
+ double decodeTime = (dwtimeDecodeComplete - dwtimeDecodeStart) / loopCount;
+ double symbolRate = (ccomp * size.cy * size.cx) / (1000.0 * decodeTime);
+ printf("Size:%4ldx%4ld, Encode time:%7.2f ms, Decode time:%7.2f ms, Bits per sample:%5.2f, Decode rate:%5.1f M/s \n\r", size.cx, size.cy, encodeTime, decodeTime, bitspersample, symbolRate);
+ BYTE* pbyteOut = &rgbyteOut[0];
+ for (size_t i = 0; i < rgbyteOut.size(); ++i)
+ {
+ if (rgbyteRaw[i] != pbyteOut[i])
+ {
+ ASSERT(false);
+ break;
+ }
+ }
+}
+
+
+void TestFile(SZC strName, int ioffs, Size size2, int cbit, int ccomp, bool littleEndianFile, int loopCount)
+{
+ int byteCount = size2.cx * size2.cy * ccomp * ((cbit + 7)/8);
+ std::vector<BYTE> rgbyteUncompressed;
+
+ if (!ReadFile(strName, &rgbyteUncompressed, ioffs, byteCount))
+ return;
+
+ if (cbit > 8)
+ {
+ FixEndian(&rgbyteUncompressed, littleEndianFile);
+ }
+
+ TestRoundTrip(strName, rgbyteUncompressed, size2, cbit, ccomp, loopCount);
+}
+
diff --git a/test/util.h b/test/util.h
index 62bb941..092455e 100644
--- a/test/util.h
+++ b/test/util.h
@@ -1,20 +1,20 @@
-//
-// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
-//
-
-#ifndef TEST_UTIL
-#define TEST_UTIL
-
-#include "../util.h"
-
-typedef const char* SZC;
-
-void FixEndian(std::vector<BYTE>* rgbyte, bool littleEndianData);
-bool ReadFile(SZC strName, std::vector<BYTE>* pvec, int ioffs = 0, int bytes = 0);
-void TestFile(SZC strName, int ioffs, Size size2, int cbit, int ccomp, bool littleEndianFile = false);
-void TestRoundTrip(const char* strName, std::vector<BYTE>& rgbyteRaw, Size size, int cbit, int ccomp);
-
-void WriteFile(SZC strName, std::vector<BYTE>& vec);
-void DecompressFile(SZC strNameEncoded, SZC strNameRaw, int ioffs, bool bcheckEncode = true);
-
-#endif
+//
+// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
+
+#ifndef TEST_UTIL
+#define TEST_UTIL
+
+#include "../src/util.h"
+
+typedef const char* SZC;
+
+void FixEndian(std::vector<BYTE>* rgbyte, bool littleEndianData);
+bool ReadFile(SZC strName, std::vector<BYTE>* pvec, int ioffs = 0, int bytes = 0);
+void TestFile(SZC strName, int ioffs, Size size2, int cbit, int ccomp, bool littleEndianFile = false, int loopCount = 1);
+void TestRoundTrip(const char* strName, std::vector<BYTE>& rgbyteRaw, Size size, int cbit, int ccomp, int loopCount = 1);
+
+void WriteFile(SZC strName, std::vector<BYTE>& vec);
+void DecompressFile(SZC strNameEncoded, SZC strNameRaw, int ioffs, bool bcheckEncode = true);
+
+#endif
diff --git a/unittest/JpegStreamWriterTest.cpp b/unittest/JpegStreamWriterTest.cpp
new file mode 100644
index 0000000..60cda0c
--- /dev/null
+++ b/unittest/JpegStreamWriterTest.cpp
@@ -0,0 +1,29 @@
+//
+// (C) CharLS Team 2014, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
+
+#include "stdafx.h"
+#include "CppUnitTest.h"
+
+#include "..\src\jpegstreamwriter.h"
+
+using namespace Microsoft::VisualStudio::CppUnitTestFramework;
+
+namespace CharLSUnitTest
+{
+ TEST_CLASS(JpegStreamWriterTest)
+ {
+ public:
+ TEST_METHOD(LengthWillbeZeroAfterCreate)
+ {
+ JfifParameters jfifParameters;
+
+ Size size(100, 100);
+ LONG bitsPerSample = 1;
+ LONG ccomp = 0;
+
+ JpegStreamWriter writer(jfifParameters, size, bitsPerSample, ccomp);
+ Assert::AreEqual(static_cast<size_t>(0), writer.GetLength());
+ }
+ };
+}
\ No newline at end of file
diff --git a/unittest/jpegmarkersegmenttest.cpp b/unittest/jpegmarkersegmenttest.cpp
new file mode 100644
index 0000000..44b7520
--- /dev/null
+++ b/unittest/jpegmarkersegmenttest.cpp
@@ -0,0 +1,47 @@
+//
+// (C) CharLS Team 2014, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
+
+#include "stdafx.h"
+#include "CppUnitTest.h"
+
+#include "..\src\jpegmarkersegment.h"
+
+using namespace Microsoft::VisualStudio::CppUnitTestFramework;
+
+namespace CharLSUnitTest
+{
+ TEST_CLASS(JpegMarkerSegmentTest)
+ {
+ public:
+ TEST_METHOD(CreateStartOfFrameMarker)
+ {
+ // TODO
+ //static JpegMarkerSegment* CreateStartOfFrameMarker(Size size, LONG bitsPerSample, LONG ccomp);
+ }
+
+ TEST_METHOD(CreateJpegFileInterchangeFormatMarker)
+ {
+ // TODO
+ //static JpegMarkerSegment* CreateJpegFileInterchangeFormatMarker(const JfifParameters& jfif);
+ }
+
+ TEST_METHOD(CreateJpegLSExtendedParametersMarker)
+ {
+ // TODO
+ //static JpegMarkerSegment* CreateJpegLSExtendedParametersMarker(const JlsCustomParameters& pcustom);
+ }
+
+ TEST_METHOD(CreateColorTransformMarker)
+ {
+ // TODO
+ //static JpegMarkerSegment* CreateColorTransformMarker(int i);
+ }
+
+ TEST_METHOD(CreateStartOfScanMarker)
+ {
+ // TODO
+ //static JpegMarkerSegment* CreateStartOfScanMarker(const JlsParameters* pparams, LONG icomponent);
+ }
+ };
+}
\ No newline at end of file
diff --git a/unittest/stdafx.cpp b/unittest/stdafx.cpp
new file mode 100644
index 0000000..0b6f21b
--- /dev/null
+++ b/unittest/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// UnitTest1.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
diff --git a/unittest/stdafx.h b/unittest/stdafx.h
new file mode 100644
index 0000000..43280fc
--- /dev/null
+++ b/unittest/stdafx.h
@@ -0,0 +1,13 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include "targetver.h"
+
+// Headers for CppUnitTest
+#include "CppUnitTest.h"
+
+// TODO: reference additional headers your program requires here
diff --git a/unittest/targetver.h b/unittest/targetver.h
new file mode 100644
index 0000000..87c0086
--- /dev/null
+++ b/unittest/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include <SDKDDKVer.h>
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/charls.git
More information about the debian-med-commit
mailing list