summaryrefslogtreecommitdiff
path: root/jpegxr
diff options
context:
space:
mode:
Diffstat (limited to 'jpegxr')
-rw-r--r--jpegxr/APP.rc103
-rw-r--r--jpegxr/APP.vcproj246
-rw-r--r--jpegxr/COPYRIGHT.txt40
-rw-r--r--jpegxr/DLL.rc103
-rw-r--r--jpegxr/DLL.vcproj289
-rw-r--r--jpegxr/JPEG-XR.sln29
-rw-r--r--jpegxr/Makefile63
-rw-r--r--jpegxr/README.txt478
-rw-r--r--jpegxr/algo.c1774
-rw-r--r--jpegxr/api.c1206
-rw-r--r--jpegxr/app_resource.h14
-rw-r--r--jpegxr/cr_parse.c1423
-rw-r--r--jpegxr/cw_emit.c677
-rw-r--r--jpegxr/dll_resource.h14
-rw-r--r--jpegxr/dllmain.c75
-rw-r--r--jpegxr/file.c3082
-rw-r--r--jpegxr/file.h72
-rw-r--r--jpegxr/flags.c155
-rw-r--r--jpegxr/init.c504
-rw-r--r--jpegxr/io.c542
-rw-r--r--jpegxr/jpegxr.c1754
-rw-r--r--jpegxr/jpegxr.h794
-rw-r--r--jpegxr/jpegxr_pixelformat.c156
-rw-r--r--jpegxr/jxr_priv.h821
-rw-r--r--jpegxr/my_getopt-1.5/LICENSE22
-rw-r--r--jpegxr/my_getopt-1.5/getopt.h56
-rw-r--r--jpegxr/my_getopt-1.5/my_getopt.c281
-rw-r--r--jpegxr/my_getopt-1.5/my_getopt.h72
-rw-r--r--jpegxr/qp.tab.c1909
-rw-r--r--jpegxr/qp.tab.h87
-rw-r--r--jpegxr/qp_lexor.c1869
-rw-r--r--jpegxr/qp_lexor.lex87
-rw-r--r--jpegxr/qp_parse.y308
-rw-r--r--jpegxr/r_parse.c3378
-rw-r--r--jpegxr/r_strip.c2774
-rw-r--r--jpegxr/r_tile_frequency.c699
-rw-r--r--jpegxr/r_tile_spatial.c380
-rw-r--r--jpegxr/sample.qp96
-rw-r--r--jpegxr/stdint_minimal.h71
-rw-r--r--jpegxr/versions-windows.txt11
-rw-r--r--jpegxr/w_emit.c3307
-rw-r--r--jpegxr/w_strip.c3348
-rw-r--r--jpegxr/w_tile_frequency.c306
-rw-r--r--jpegxr/w_tile_spatial.c306
-rw-r--r--jpegxr/x_strip.c86
45 files changed, 33867 insertions, 0 deletions
diff --git a/jpegxr/APP.rc b/jpegxr/APP.rc
new file mode 100644
index 000000000..96f5b915b
--- /dev/null
+++ b/jpegxr/APP.rc
@@ -0,0 +1,103 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "app_resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "app_resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 0,1,2008,324
+ PRODUCTVERSION 0,1,2008,324
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "Comments", "JPEG-XR Sample Application"
+ VALUE "CompanyName", "Microsoft Corporation"
+ VALUE "FileDescription", "JPEG-XR Sample Application"
+ VALUE "FileVersion", "0, 1, 2008, 0324"
+ VALUE "InternalName", "JPEGXR-EXE"
+ VALUE "LegalCopyright", "Copyright (C) 2008 Microsoft Corporation. All rights reserved."
+ VALUE "OriginalFilename", "jpegxr.exe"
+ VALUE "ProductName", "JPEG-XR Sample Application"
+ VALUE "ProductVersion", "0, 1, 2008, 0324"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/jpegxr/APP.vcproj b/jpegxr/APP.vcproj
new file mode 100644
index 000000000..8009e8f62
--- /dev/null
+++ b/jpegxr/APP.vcproj
@@ -0,0 +1,246 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="APP"
+ ProjectGUID="{FA1F4A8C-4C1F-4560-9750-351432EE6D8A}"
+ RootNamespace="APP"
+ 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"
+ Description="generate qp C code if necessary"
+ CommandLine=""
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="my_getopt-1.5"
+ PreprocessorDefinitions="DETAILED_DEBUG;_CRT_SECURE_NO_WARNINGS;WIN32;_WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ WarnAsError="false"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ CompileAs="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="jpegxr.lib"
+ OutputFile="$(OutDir)\jpegxr.exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="$(OutDir)"
+ 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"
+ Description="generate qp C code if necessary"
+ CommandLine=""
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="my_getopt-1.5"
+ PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS;WIN32;_WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ CompileAs="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="jpegxr.lib"
+ OutputFile="$(OutDir)\jpegxr.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="$(OutDir)"
+ 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>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\file.c"
+ >
+ </File>
+ <File
+ RelativePath=".\jpegxr.c"
+ >
+ </File>
+ <File
+ RelativePath=".\my_getopt-1.5\my_getopt.c"
+ >
+ </File>
+ <File
+ RelativePath=".\qp.tab.c"
+ >
+ </File>
+ <File
+ RelativePath=".\qp_lexor.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\file.h"
+ >
+ </File>
+ <File
+ RelativePath=".\my_getopt-1.5\getopt.h"
+ >
+ </File>
+ <File
+ RelativePath=".\my_getopt-1.5\my_getopt.h"
+ >
+ </File>
+ <File
+ RelativePath=".\qp.tab.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\APP.rc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/jpegxr/COPYRIGHT.txt b/jpegxr/COPYRIGHT.txt
new file mode 100644
index 000000000..df46e6594
--- /dev/null
+++ b/jpegxr/COPYRIGHT.txt
@@ -0,0 +1,40 @@
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+***********************************************************************/
diff --git a/jpegxr/DLL.rc b/jpegxr/DLL.rc
new file mode 100644
index 000000000..1aeb5bfb0
--- /dev/null
+++ b/jpegxr/DLL.rc
@@ -0,0 +1,103 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "dll_resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "dll_resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 0,1,2008,324
+ PRODUCTVERSION 0,1,2008,324
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "Comments", "JPEG-XR Dynamic Link Library"
+ VALUE "CompanyName", "Microsoft Corporation"
+ VALUE "FileDescription", "JPEG-XR Dynamic Link Library"
+ VALUE "FileVersion", "0, 1, 2008, 0324"
+ VALUE "InternalName", "JPEGXR-DLL"
+ VALUE "LegalCopyright", "Copyright (C) 2008 Microsoft Corporation. All rights reserved."
+ VALUE "OriginalFilename", "jpegxr.dll"
+ VALUE "ProductName", "JPEG-XR Dynamic Link Library"
+ VALUE "ProductVersion", "0, 1, 2008, 0324"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/jpegxr/DLL.vcproj b/jpegxr/DLL.vcproj
new file mode 100644
index 000000000..08373556b
--- /dev/null
+++ b/jpegxr/DLL.vcproj
@@ -0,0 +1,289 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="DLL"
+ ProjectGUID="{969C2750-EF0E-428F-9A85-20256796BC5C}"
+ RootNamespace="DLL"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="DETAILED_DEBUG;JXR_DLL_EXPORTS;WIN32;_DEBUG;_WINDOWS;_USRDLL;DLL_EXPORTS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ WarnAsError="false"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ CompileAs="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ ShowProgress="0"
+ OutputFile="$(OutDir)\jpegxr_dll.dll"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ GenerateMapFile="true"
+ MapExports="true"
+ SubSystem="2"
+ ImportLibrary="$(TargetDir)jpegxr.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="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ 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="JXR_DLL_EXPORTS;WIN32;NDEBUG;_WINDOWS;_USRDLL;DLL_EXPORTS"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ CompileAs="2"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)\jpegxr.dll"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ ImportLibrary="$(TargetDir)jpegxr.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\algo.c"
+ >
+ </File>
+ <File
+ RelativePath=".\api.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cr_parse.c"
+ >
+ </File>
+ <File
+ RelativePath=".\cw_emit.c"
+ >
+ </File>
+ <File
+ RelativePath=".\dllmain.c"
+ >
+ </File>
+ <File
+ RelativePath=".\flags.c"
+ >
+ </File>
+ <File
+ RelativePath=".\init.c"
+ >
+ </File>
+ <File
+ RelativePath=".\io.c"
+ >
+ </File>
+ <File
+ RelativePath=".\jpegxr_pixelformat.c"
+ >
+ </File>
+ <File
+ RelativePath=".\r_parse.c"
+ >
+ </File>
+ <File
+ RelativePath=".\r_strip.c"
+ >
+ </File>
+ <File
+ RelativePath=".\r_tile_frequency.c"
+ >
+ </File>
+ <File
+ RelativePath=".\r_tile_spatial.c"
+ >
+ </File>
+ <File
+ RelativePath=".\w_emit.c"
+ >
+ </File>
+ <File
+ RelativePath=".\w_strip.c"
+ >
+ </File>
+ <File
+ RelativePath=".\w_tile_frequency.c"
+ >
+ </File>
+ <File
+ RelativePath=".\w_tile_spatial.c"
+ >
+ </File>
+ <File
+ RelativePath=".\x_strip.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\jpegxr.h"
+ >
+ </File>
+ <File
+ RelativePath=".\jxr_priv.h"
+ >
+ </File>
+ <File
+ RelativePath=".\stdint_minimal.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\DLL.rc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/jpegxr/JPEG-XR.sln b/jpegxr/JPEG-XR.sln
new file mode 100644
index 000000000..d43de8ee4
--- /dev/null
+++ b/jpegxr/JPEG-XR.sln
@@ -0,0 +1,29 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DLL", "DLL.vcproj", "{969C2750-EF0E-428F-9A85-20256796BC5C}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "APP", "APP.vcproj", "{FA1F4A8C-4C1F-4560-9750-351432EE6D8A}"
+ ProjectSection(ProjectDependencies) = postProject
+ {969C2750-EF0E-428F-9A85-20256796BC5C} = {969C2750-EF0E-428F-9A85-20256796BC5C}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {969C2750-EF0E-428F-9A85-20256796BC5C}.Debug|Win32.ActiveCfg = Debug|Win32
+ {969C2750-EF0E-428F-9A85-20256796BC5C}.Debug|Win32.Build.0 = Debug|Win32
+ {969C2750-EF0E-428F-9A85-20256796BC5C}.Release|Win32.ActiveCfg = Release|Win32
+ {969C2750-EF0E-428F-9A85-20256796BC5C}.Release|Win32.Build.0 = Release|Win32
+ {FA1F4A8C-4C1F-4560-9750-351432EE6D8A}.Debug|Win32.ActiveCfg = Debug|Win32
+ {FA1F4A8C-4C1F-4560-9750-351432EE6D8A}.Debug|Win32.Build.0 = Debug|Win32
+ {FA1F4A8C-4C1F-4560-9750-351432EE6D8A}.Release|Win32.ActiveCfg = Release|Win32
+ {FA1F4A8C-4C1F-4560-9750-351432EE6D8A}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/jpegxr/Makefile b/jpegxr/Makefile
new file mode 100644
index 000000000..75f4fa667
--- /dev/null
+++ b/jpegxr/Makefile
@@ -0,0 +1,63 @@
+
+# Change these to suit.
+#CFLAGS = -Wall -g -DDETAILED_DEBUG
+#CFLAGS = -Wall -O
+CFLAGS = -g
+
+# The "jpegxr" command is build as a demonstration for the
+# libjpegxr library.
+O = jpegxr.o file.o qp.tab.o qp_lexor.o
+
+jpegxr: $O libjpegxr.a
+
+qp.tab.o: qp.tab.c jpegxr.h
+qp_lexor.o: qp_lexor.c qp.tab.h jpegxr.h
+
+jpegxr.o: jpegxr.c jpegxr.h file.h
+file.o: file.c file.h
+
+qp_c_code: qp.tab.c qp.tab.h qp_lexor.c
+
+# Use this rule (i.e. make dist_files) to pre-generate the C files
+# for distribution to systems that do not have a working bison/flex.
+dist_files: qp.tab.c qp.tab.h qp_lexor.c
+ sed -e "/<unistd.h>/ c /* #include <unistd.h> ...is not needed */" qp_lexor.c > tmp.c
+ mv tmp.c qp_lexor.c
+
+qp.tab.c qp.tab.h: qp_parse.y
+ bison -d -p qp_ -b qp qp_parse.y
+
+qp_lexor.c: qp_lexor.lex
+ flex -oqp_lexor.c -Pqp_ qp_lexor.lex
+
+# The library files are here. Note that it is the library that is
+# the reference code for JPEG XR. The "jpegxr" command that is
+# built above (and the source files that go into it) is only an
+# example program that demonstrates this library.
+L = algo.o api.o w_emit.o flags.o init.o io.o cr_parse.o cw_emit.o r_parse.o jpegxr_pixelformat.o\
+r_strip.o r_tile_spatial.o r_tile_frequency.o w_strip.o w_tile_spatial.o w_tile_frequency.o x_strip.o
+libjpegxr.a: $L
+ -rm -f $@
+ ar cq $@ $L
+
+
+algo.o: algo.c jxr_priv.h jpegxr.h
+api.o: api.c jxr_priv.h jpegxr.h
+w_emit.o: w_emit.c jxr_priv.h jpegxr.h
+flags.o: flags.c jxr_priv.h jpegxr.h
+init.o: init.c jxr_priv.h jpegxr.h
+io.o: io.c jxr_priv.h jpegxr.h
+r_parse.o: r_parse.c jxr_priv.h jpegxr.h
+r_strip.o: r_strip.c jxr_priv.h jpegxr.h
+w_strip.o: w_strip.c jxr_priv.h jpegxr.h
+x_strip.o: x_strip.c jxr_priv.h jpegxr.h
+jpegxr_pixelformat.o: jpegxr_pixelformat.c jxr_priv.h
+cr_parse.o: cr_parse.c jxr_priv.h jpegxr.h
+cw_emit.o: cw_emit.c jxr_priv.h jpegxr.h
+
+r_tile_frequency.o: r_tile_frequency.c jxr_priv.h jpegxr.h
+r_tile_spatial.o: r_tile_spatial.c jxr_priv.h jpegxr.h
+w_tile_spatial.o: w_tile_spatial.c jxr_priv.h jpegxr.h
+w_tile_frequency.o: w_tile_frequency.c jxr_priv.h jpegxr.h
+
+
diff --git a/jpegxr/README.txt b/jpegxr/README.txt
new file mode 100644
index 000000000..dadaf51d9
--- /dev/null
+++ b/jpegxr/README.txt
@@ -0,0 +1,478 @@
+ITU-T Rec. T.835 (ex T.JXR-5) | ISO/IEC 29199-5
+
+"Information technology – JPEG XR image coding system – Reference software"
+
+==============
+ READ-ME FILE
+==============
+
+*********************************************************************
+* *
+* NOTE: the software in folder my_getopt-1.5 is used solely for *
+* facilitating handling of the command line interface paramenters, *
+* and it is not part of the algorithimic implementation of JPEG-XR. *
+* *
+*********************************************************************
+
+JPEG XR reference software 1.8 (September 2009)
+-------------------------------------------------------------------
+
+This version constitutes changes to the encoder only. Two bugs were fixed:
+1. Fix a crashing bug for tiling.
+2. Fix a bug in the overlap operators. Overlap code was using row indices relative to the tile instead of relative to the image.
+
+No changes were made to the usage text.
+
+JPEG XR reference software 1.7 (July 2009)
+-------------------------------------------------------------------
+
+This version constitutes a change to the encoder only. A bug related to using a detailed quantization information file
+without specifying tile sizes (or without tiling) was fixed.
+
+No changes were made to the usage text.
+
+JPEG XR reference software 1.6 (29 May 2009)
+-------------------------------------------------------------------
+
+This version constitutes several improvements to both the sample
+encoder and reference decoder.
+
+
+Changes related to the decoder are as follows:
+1. Add support for upsampling for non zero values of CHROMA_CENTERING_X and CHROMA_CENTERING_Y
+2. Enhance container handling to test conformance relationship of tag based container format and codestream
+3. Add fix by Thomas Richter for issue caused by some compilers treating unsigned long as 64 bit data
+4. Fix a bug in decoding of interleaved YCC/CMYKDIRECT formats
+
+Changes related to the encoder are as follows:
+1. Add support for separate alpha image plane
+2. Add support for YCC OUTPUT_CLR_FMT (YUV444, YUV422, YUV420)
+3. Add support for CMYKDIRECT
+4. Add support for WINDOWING_FLAG
+5. Add support for the following pixel formats - 24bppBGR, 32bppBGRA, 32bppBGR, 32bppPGBGRA, 64bppPRGBA, 128bppPRGBA
+6. Add code to write IFD tags in the image container. The code for optional tags are in a macro which is disabled by default.
+7. Fix a bug related to encoding 40bppCMYKA and 80bppCMYKA using interleaved alpha mode
+
+
+
+New usage text:
+Usage: Debug\jpegxr.exe <flags> <input_file.jxr>
+Usage: e:\rjsourcedepot\multimedia\dmd\CodecDSP\jxrRefCode\current\Debug\jpegxr.exe <flags> <input_file.jxr>
+ DECODER FLAGS:
+ [-o <path>] [-w] [-P 44|55|66|111] [-L 4|8|16|32|64|128|255]
+
+ -o: selects output file name (.raw/.tif/.pnm)
+ (PNM output can be used only for 24bpp RGB and 8bpp gray Output)
+ (TIF output can be used for all formats except the following:
+ N channels, BGR, RGBE, YCC, CMYKDirect & Premultiplied RGB)
+ (RAW output can be used for all formats)
+ -w: tests whether LONG_WORD_FLAG needs to be equal to TRUE
+ (will still decode the image)
+ -P: selects the maximum accepted profile value
+ (44:Sub-Baseline|55:Baseline|66:Main|111:Advanced)
+ -L: selects the maximum accepted level value
+ (4|8|16|32|64|128)
+
+ ENCODER FLAGS: (Temporary (.tmp) files may be used in encoding)
+ -c [-o <path>] [-b ALL|NOFLEXBITS|NOHIGHPASS|DCONLY] [-a 0|1|2] [-p]
+ [-f YUV444|YUV422|YUV420] [-F bits] [-h] [-m] [-l 0|1|2]
+ [-q q1[:q2[:q3]]] [-Q <path>] [-d] [-w] [-U rows:columns]
+ [-C width1[:width2>[:width3...]]] [-R height1[:height2[:height3...]]]
+ [-P 44|55|66|111] [-L 4|8|16|32|64|128|255] [-s top|left|bottom|right]
+ [-r -W width -H height -M 3|4|...|18 [-B 8|16]]
+
+ -c: selects encoding instead of decoding
+ this flag is necessary for encoding
+ -o: selects the output file name (.jxr)
+ -b: selects the bands to encode
+ (ALL<Default>|NOFLEXBITS|NOHIGHPASS|DCONLY)
+ -a: selects encoder alpha mode
+ (0: no alpha|1:interleaved alpha|2:separate alpha)
+ Default: For tif input files, based on the information in the
+ PhotometricInterpretation and SamplesPerPixel tags in the container,
+ the encoder chooses an input pixel format. If the number
+ of components is 4 and photometric is 2, RGBA input is inferred and
+ the encoder assumes the presence of an alpha channel while encoding.
+ If the number of components is 5 and photometric is 5, CMYKA input is
+ inferred. In both these cases, the encoder infers a pixel format with
+ an alpha channel. In such cases, the default alpha encoder mode is 2.
+ For raw input files, when the -M parameter specified by the user is
+ 9, 10, 11, 12 13, 14, 23, 24, 25, 26 or 28,
+ the default alpha encoder mode is 2
+ In all other cases, the default alpha encoder mode is 0.
+ -p: selects an input pixel format with a padding channel
+ With tif input, when the encoder infers that the input file has an
+ alpha channel (see explanation for -a), this flag causes the encoder
+ to treat the alpha channel as a padding channel instead
+ -f: selects the internal color format
+ (YUV444<Default>|YUV422|YUV420)
+ -F: selects the number of flexbits to trim
+ (0<default> - 15)
+ -h: selects hard tile boundaries
+ (soft tile boundaries by default)
+ -m: encode in frequency order codestream
+ (spatial order by default)
+ -l: selects the overlapped block filtering
+ (0:off|1:HP only<Default>|2:all)
+
+ -q: sets the quantization values separately, or one per band
+ (0<default, lossless> - 255)
+ -Q: specifies a file containing detailed quantization information
+ See sample.qp
+ -d: selects quantization for U/V channels derived from Y channel
+
+ -U: selects uniform tile sizes
+ -C: selects the number of tile columns and the width of each
+ -R: selects the number of tile rows and the height of each
+
+ -w: sets LONG_WORD_FLAG equal to FALSE
+ -P: selects the profile value
+ (44:Sub-Baseline|55:Baseline|66:Main|111:Advanced)
+ -L: selects the level value
+ (4|8|16|32|64|128)
+ -s: sets the top, left, bottom, and right margins
+
+ -r: selects encoding with RAW images
+ must also specify -W, -H and -M, optional -B
+ -W: RAW image width when encoding with RAW images
+ -H: RAW image height when encoding with RAW images
+ -M: RAW image format when encoding with RAW images
+ 3: 3-channel
+ 4: 4-channel
+ 5: 5-channel
+ 6: 6-channel
+ 7: 7-channel
+ 8: 8-channel
+ 9: 3-channel Alpha
+ 10: 4-channel Alpha
+ 11: 5-channel Alpha
+ 12: 6-channel Alpha
+ 13: 7-channel Alpha
+ 14: 8-channel Alpha
+ 15: 32bppRGBE
+ 16: 16bppBGR555
+ 17: 16bppBGR565
+ 18: 32bppBGR101010
+ 19: YCC420
+ 20: YCC422
+ 21: YCC444
+ 22: YCC444 Fixed Point
+ 23: YCC420 Alpha
+ 24: YCC422 Alpha
+ 25: YCC444 Alpha
+ 26: YCC444 Fixed Point Alpha
+ 27: CMYKDIRECT
+ 28: CMYKDIRECT Alpha
+ 29: 24bppBGR
+ 30: 32bppBGR
+ 31: 32bppBGRA
+ 32: 32bppPBGRA
+ 33: 64bppPRGBA
+ 34: 128bppPRGBAFloat
+ -B: RAW image bit/channel when encoding with RAW images
+ 8: 8-bit/channel (default)
+ 10: 10-bit/channel
+ 16: 16-bit/channel
+
+
+Raw File Description:
+The raw file makes it possible to store the results of the output formatting process . The raw file output consists of either interleaved or sequential data from each of the channels in the image, without any header information. Buffers are stored in a raster scan order.
+If OUTPUT_CLR_FMT is equal to YUV_420, YUV_422, YUV_444 or CMYKDirect, the buffer for each channel is stored sequentially. For example, when OUTPUT_CLR_FMT equals YUV_444 all Y samples are stored in the output file, followed by all U samples, followed by all V samples. If OUTPUT_CLR_FMT is equal to YUV422, half as many bytes used for the Y channel will be used to store the U and V channels. Otherwise, uf OUTPUT_CLR_FMT is equal to YUV420, one quarter as many bytes as used for the Y channel will be used to store the U and V channels. If OUTPUT_CLR_FMT is equal to YUV444 or YUV422 and OUTPUT_BITDEPTH is equal to BD10, 2 bytes are used per sample, and the 10 bits are stored in the LSBs of each 2 byte pair. Samples decoded from the alpha image plane (when present), are concatenated with the output obtained from the primary image.
+Otherwise, if OUTPUT_CLR_FMT is not equal to YUV_420, YUV_422, YUV_444 or CMYKDirect, the raw file output consists of interleaved data from each channel. The number of bytes used to store each sample is contingent upon the value of OUTPUT_BITDEPTH and whether the format is a packed output format or not. The samples decoded from the image alpha plane (when present), are interleaved with the samples decoded from the primary image.
+
+
+JPEG XR reference software 1.5 (13 Apr 2009)
+-------------------------------------------------------------------
+
+This version constitutes several improvements to both the sample
+encoder and reference decoder.
+
+Decoder changes:
+-Add support for fixed point formats
+-Add support for floating point formats
+-Add support for half formats
+-Add support for separate alpha image plane
+-Add support for interleaved alpha image plane
+-Add support for YCC OUTPUT_CLR_FMT (YUV444, YUV422, YUV420)
+-Add support for CMYKDIRECT
+-Add support for n-Component formats
+-Add support for RGBE format
+-Add support for packed output formats
+-Add support for LONG_WORD_FLAG
+-Add support for Profiles/Levels
+-Fix a bug related to USE_DC_QP_FLAG and USE_LP_QP_FLAG
+-Add support for raw image buffer output file format
+-Add support for WINDOWING_FLAG
+-Fix a bug with respect to the index table and spatial ordered
+ bitstreams
+-Improve usage text
+
+Encoder changes:
+-Fix a bug with CMYK encoding
+-Add support for frequency mode
+-Add support for tiling
+-Add support for fixed point formats
+-Add support for floating point formats
+-Add support for half formats
+-Add support for interleaved alpha image plane
+-Add support for n-Component formats
+-Add support for RGBE format
+-Add support for packed output formats
+-Add support for LONG_WORD_FLAG
+-Add support for Profiles/Levels
+-Improve usage text
+
+New usage text:
+Usage: Release\jpegxr.exe <flags> <input_file.jxr>
+ DECODER FLAGS:
+ [-o <path>] [-w] [-P 44|55|66|111] [-L 4|8|16|32|64|128|255]
+
+ -o: selects output file name (.raw/.tif/.pnm)
+ -w: tests whether LONG_WORD_FLAG needs to be equal to TRUE
+ (will still decode the image)
+ -P: selects the maximum accepted profile value
+ (44:Sub-Baseline|55:Baseline|66:Main|111:Advanced)
+ -L: selects the maximum accepted level value
+ (4|8|16|32|64|128)
+
+ ENCODER FLAGS: (Temporary (.tmp) files may be used in encoding)
+ -c [-o <path>] [-b ALL|NOFLEXBITS|NOHIGHPASS|DCONLY] [-a 0|1|2]
+ [-f YUV444|YUV422|YUV420] [-F bits] [-h] [-m] [-l 0|1|2]
+ [-q q1[:q2[:q3]]] [-Q <path>] [-d] [-w] [-U rows:columns]
+ [-C width1[:width2>[:width3...]]] [-R height1[:height2[:height3...]]]
+ [-P 44|55|66|111] [-L 4|8|16|32|64|128|255]
+ [-r -W width -H height -M 3|4|5|6|7|8|15|16|17|18 [-B 8|16]]
+
+ -c: selects encoding instead of decoding
+ this flag is necessary for encoding
+ -o: selects the output file name (.jxr)
+ -b: selects the bands to encode
+ (ALL<Default>|NOFLEXBITS|NOHIGHPASS|DCONLY)
+ -a: selects encoder alpha mode
+ (0:no alpha|1:interleaved alpha|2:separate alpha)
+ -f: selects the internal color format
+ (YUV444<Default>|YUV422|YUV420)
+ -F: selects the number of flexbits to trim
+ (0<default> - 15)
+ -h: selects hard tile boundaries
+ (soft tile boundaries by default)
+ -m: encode in frequency order codestream
+ (spatial order by default)
+ -l: selects the overlapped block filtering
+ (0:off|1:HP only<Default>|2:all)
+
+ -q: sets the quantization values separately, or one per band
+ (0<default, lossless> - 255)
+ -Q: specifies a file containing detailed quantization information
+ See sample.qp
+ -d: selects quantization for U/V channels derived from Y channel
+
+ -U: selects uniform tile sizes
+ -C: selects the number of tile columns and the width of each
+ -R: selects the number of tile rows and the height of each
+
+ -w: sets LONG_WORD_FLAG equal to FALSE
+ -P: selects the profile value
+ (44:Sub-Baseline|55:Baseline|66:Main|111:Advanced)
+ -L: selects the level value
+ (4|8|16|32|64|128)
+
+ -r: selects encoding with RAW images
+ must also specify -W, -H and -M, optional -B
+ -W: RAW image width when encoding with RAW images
+ -H: RAW image height when encoding with RAW images
+ -M: RAW image format when encoding with RAW images
+ 3: 3-channel
+ 4: 4-channel
+ 5: 5-channel
+ 6: 6-channel
+ 7: 7-channel
+ 8: 8-channel
+ 9: 3-channel Alpha
+ 10: 4-channel Alpha
+ 11: 5-channel Alpha
+ 12: 6-channel Alpha
+ 13: 7-channel Alpha
+ 14: 8-channel Alpha
+ 15: 32bppRGBE
+ 16: 16bppBGR555
+ 17: 16bppBGR565
+ 18: 32bppBGR101010
+ -B: RAW image bit/channel when encoding with RAW images
+ 8: 8-bit/channel (default)
+ 16: 16-bit/channel
+
+Raw File Description:
+The raw file makes it possible to store the results of the output formatting process . The raw file output consists of either interleaved or sequential data from each of the channels in the image, without any header information. Buffers are stored in a raster scan order.
+If OUTPUT_CLR_FMT is equal to YUV_420, YUV_422, YUV_444 or CMYKDirect, the buffer for each channel is stored sequentially. For example, when OUTPUT_CLR_FMT equals YUV_444 all Y samples are stored in the output file, followed by all U samples, followed by all V samples. If OUTPUT_CLR_FMT is equal to YUV422, half as many bytes used for the Y channel will be used to store the U and V channels. Otherwise, uf OUTPUT_CLR_FMT is equal to YUV420, one quarter as many bytes as used for the Y channel will be used to store the U and V channels. If OUTPUT_CLR_FMT is equal to YUV444 or YUV422 and OUTPUT_BITDEPTH is equal to BD10, 2 bytes are used per sample, and the 10 bits are stored in the LSBs of each 2 byte pair. Samples decoded from the alpha image plane (when present), are concatenated with the output obtained from the primary image.
+Otherwise, if OUTPUT_CLR_FMT is not equal to YUV_420, YUV_422, YUV_444 or CMYKDirect, the raw file output consists of interleaved data from each channel. The number of bytes used to store each sample is contingent upon the value of OUTPUT_BITDEPTH and whether the format is a packed output format or not. The samples decoded from the image alpha plane (when present), are interleaved with the samples decoded from the primary image.
+
+
+JPEG XR reference software 1.4 (31 Dec 2008)
+-------------------------------------------------------------------
+
+This version contains a bug fix and integrates the hard tile proposal.
+Indentations have been reformatted. It fixes a bug related to decoding of
+multiple tile images with quantization step sizes varying across tiles.
+
+JPEG XR reference software 1.3 (30 Sept 2008)
+-------------------------------------------------------------------
+
+This version was circulated for CD ballot. In has the same
+technical design as the 1.2 version. Some renaming of
+variables and strings was performed to replace references to
+"HD Photo" (and "hdp") with references to "JPEG XR" (and "jxr").
+Some minor header reformatting was performed.
+
+JPEG XR reference software 1.2
+-------------------------------------------------------------------
+
+This version integrates the fixed POT filter proposed by
+Microsoft. To enable or disable this filter, edit the
+line setting FIXED_POT in jxr_priv.h. It is by default enabled
+now.
+
+JPEG XR reference software 1.1
+-------------------------------------------------------------------
+
+This is an updated/modified version of the 1.0 release of the
+reference software, originally provided by Microsoft and Picture
+Elements. Modifications for release 1.1 were made by the University
+of Stuttgart (Thomas Richter), and are provided under the same
+licence terms as release 1.0.
+
+The following modifications have been made for this release:
+
+- The main program prints a summary of its command line arguments
+if an input file is missing.
+
+- A new flag "-d" has been added that derives the quantization
+parameter for the color planes in the same way the DPK software
+derived its quantization parameters from the Y plane. This makes the
+reference software backwards compatible to the DPK.
+
+
+
+JPEG XR reference software 1.0
+-------------------------------------------------------------------
+
+
+SUMMARY
+
+The jpegxr program is an example program that uses the jpegxr.h
+compression/decompression API.
+
+USAGE
+
+jpegxr <flags> <input-file>
+
+FLAGS
+
+* -c
+
+Compress. Normally, jpegxr decompresses the input file. This flag
+requests compression instead.
+
+* -b ALL|NOFLEXBITS|NOHIGHPASS|DCONLY
+
+When compressing, this flag selects the subbands to use. The names are
+taken from the JPEG XR standard. The default is '-b ALL'. This is
+only useful for compression.
+
+* -f <flag>
+
+Set various encode/decode options.
+
+* -F <bits>
+
+Enable FLEXBIT trimming. If FLEXBITS are enabled (-b ALL) then the
+<bits> value is the number of bits to trim. The useful value ranges
+from 0 to 15 inclusive. -F 0 keeps the most FLEXBITS, and -F 15 keeps
+the fewest bits. This is only useful for compression.
+
+* -l [0|1|2]
+
+Enable overlap pre-filtering. The default is '-l 0' which turns off
+filtering. Values 1 and 2 enable first pass only or first and second
+pass filters respectively.
+
+* -o <path>
+
+Give the output file destination. If comression is enabled (-c) then
+this is the path to the output compressed file. Otherwise, this is the
+path where image data is written.
+
+* -q q1:q2:q3...
+
+Give the quantization code for each channel. If only 1 value is
+given, then use the same quantization value for all channels. if
+multiple values are given, separated by a ':', then each is assigned
+to a channel. If fewer values are given then there are channels, then
+the last value is used for all the remaining channels. For example,
+one can use '-q 2:4' to specify Q=2 for Y and Q=4 for U and V channels
+of a color image. The default is '-q 0', which along with '-b ALL'
+makes compression lossless. The useful range for this value is 0..255.
+
+* -d
+
+Derived quantization. If this parameter is specified, only one argument
+for -q is required and the code derives more suitable quantization values
+for the Cb and Cr chroma components itself, similar to the DPK code.
+This option improves coding efficency noticably whenever the color
+transformation is run.
+
+* -Q <path>
+
+Give an ASCII source file that contains detailed information about the
+quantization to use, down to a macroblock level.
+
+
+ENCODE/DECODE OPTIONS
+
+The -f argument can take any of a variety of options that control
+encode decode. The -f flag can appear as often as needed, with one
+flag at a time. The currently supported flags are:
+
+ YUV444 -- Encode full color, with no subsampling of UV planes.
+
+ YUV422 -- Encode color by subsampling the UV planes of YUV444.
+
+ YUV420 -- Encode color by subsampling the UV planes of YUV444.
+
+QP_FILE SYNTAX
+
+Comments start with a '#' character and continue to the end of the
+line. A comment can start anywhere in the line.
+
+The keywords are:
+
+ DC, LP, HP
+ channel
+ independent
+ separate
+ tile
+ uniform
+
+A NUMBER is an unsigned decimal value.
+
+A file consists of a number of tile descriptors, one tile descriptor
+for each expected tile in the image. A tile descripter is:
+
+ tile ( <n>, <n> ) { tile_comp_mode tile_body }
+
+A tile_comp_mode is one of the keywords: uniform, separate, or
+independent. The tile_body is an unordered list of tile_items:
+
+ channel <n> { channel_body }
+ LP [ map_list ]
+ HP [ map_list ]
+
+The channel_body gives channel-specific information. How many channels
+depends on the number of channels and the tile_comp_mode. A channel
+body is one each of these channel items:
+
+ DC { <n> }
+ LP { <n>... }
+ HP { <n>... }
+
+--END \ No newline at end of file
diff --git a/jpegxr/algo.c b/jpegxr/algo.c
new file mode 100644
index 000000000..28c1522f7
--- /dev/null
+++ b/jpegxr/algo.c
@@ -0,0 +1,1774 @@
+/*
+**
+** $Id: algo.c,v 1.3 2008-05-13 13:47:11 thor Exp $
+**
+**
+*/
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+***********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: algo.c,v 1.3 2008-05-13 13:47:11 thor Exp $")
+#else
+#ident "$Id: algo.c,v 1.3 2008-05-13 13:47:11 thor Exp $"
+#endif
+
+/*
+* This file contains many common algorithms of JPEGXR processing.
+*/
+
+# include "jxr_priv.h"
+# include <stdio.h>
+# include <stdlib.h>
+# include <limits.h>
+# include <assert.h>
+
+static void InitVLCTable2(jxr_image_t image, int vlc_select);
+
+const int _jxr_hp_scan_map[16] = { 0, 1, 4, 5,
+2, 3, 6, 7,
+8, 9,12,13,
+10,11,14,15 };
+
+static const unsigned ScanTotals[15] ={32, 30, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4};
+static int long_word_flag = 0;
+
+/*
+* These two functions implemented floor(x/2) and ceil(x/2). Note that
+* in C/C++ x/2 is NOT the same as floor(x/2) if x<0. It may be on
+* some systems, but not in general. So we do all arithmetic with
+* positive values and get the floor/ceil right by manipulating signs
+* and rounding afterwards. The YUV444 --> RGB transform must get this
+* rounding exactly right or there may be losses in the lossless transform.
+*/
+int _jxr_floor_div2(int x)
+{
+ if (x >= 0)
+ return x/2;
+ else
+ return -((-x+1)/2);
+}
+
+int _jxr_ceil_div2(int x)
+{
+ if (x >= 0)
+ return (x+1)/2;
+ else
+ return -((-x)/2);
+}
+
+int _jxr_quant_map(jxr_image_t image, int x, int shift)
+{
+ int man, exp;
+
+ if (x == 0)
+ return 1;
+
+ if (image->scaled_flag) {
+ if (x < 16) {
+ man = x;
+ exp = shift;
+ } else {
+ man = 16 + (x%16);
+ exp = ((x>>4) - 1) + shift;
+ }
+ } else {
+ if (x < 32) {
+ man = (x + 3) >> 2;
+ exp = 0;
+ } else if (x < 48) {
+ man = (16 + (x%16) + 1) >> 1;
+ exp = (x>>4) - 2;
+ } else {
+ man = 16 + (x%16);
+ exp = (x>>4) - 3;
+ }
+ }
+
+ return man << exp;
+}
+
+int _jxr_vlc_select(int band, int chroma_flag)
+{
+ int vlc_select = 0;
+
+ /* Based on the band and the chroma flag, select the vlc table
+ that we want to use for the ABSLEVEL_INDEX decoder. */
+ switch (band) {
+ case 0: /* DC */
+ if (chroma_flag)
+ vlc_select = AbsLevelIndDCChr;
+ else
+ vlc_select = AbsLevelIndDCLum;
+ break;
+ case 1: /* LP */
+ if (chroma_flag)
+ vlc_select = AbsLevelIndLP1;
+ else
+ vlc_select = AbsLevelIndLP0;
+ break;
+ case 2: /* HP */
+ if (chroma_flag)
+ vlc_select = AbsLevelIndHP1;
+ else
+ vlc_select = AbsLevelIndHP0;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ return vlc_select;
+}
+
+void _jxr_InitVLCTable(jxr_image_t image, int vlc_select)
+{
+ struct adaptive_vlc_s*table = image->vlc_table + vlc_select;
+ table->table = 0;
+ table->deltatable = 0;
+ table->discriminant = 0;
+}
+
+static void InitVLCTable2(jxr_image_t image, int vlc_select)
+{
+ struct adaptive_vlc_s*table = image->vlc_table + vlc_select;
+ table->table = 1;
+ table->deltatable = 0;
+ table->delta2table = 1;
+ table->discriminant = 0;
+ table->discriminant2 = 0;
+}
+
+/*
+* This function is for running the adapt for VLC machines that have
+* only 2 tables. In this case, only the table and discriminant
+* members are used, and the table is 0 or 1.
+*/
+void _jxr_AdaptVLCTable(jxr_image_t image, int vlc_select)
+{
+ const int cLowerBound = -8;
+ const int cUpperBound = 8;
+
+ struct adaptive_vlc_s*table = image->vlc_table + vlc_select;
+ const int max_index = 1; /* Only 2 code tables. */
+
+ table->deltatable = 0;
+ if ((table->discriminant < cLowerBound) && (table->table != 0)) {
+ table->table -= 1;
+ table->discriminant = 0;
+ } else if ((table->discriminant > cUpperBound) && (table->table != max_index)) {
+ table->table += 1;
+ table->discriminant = 0;
+ } else {
+ if (table->discriminant < -64) table->discriminant = -64;
+ if (table->discriminant > 64) table->discriminant = 64;
+ }
+}
+
+static void AdaptVLCTable2(jxr_image_t image, int vlc_select, int max_index)
+{
+ const int LOWER_BOUND = -8;
+ const int UPPER_BOUND = 8;
+
+ struct adaptive_vlc_s*table = image->vlc_table + vlc_select;
+
+ int disc_lo = table->discriminant;
+ int disc_hi = table->discriminant2;
+
+ int change_flag = 0;
+
+ if (disc_lo < LOWER_BOUND && table->table > 0) {
+ table->table -= 1;
+ change_flag = 1;
+
+ } else if (disc_hi > UPPER_BOUND && table->table < max_index) {
+ table->table += 1;
+ change_flag = 1;
+ }
+
+
+ if (change_flag) {
+ table->discriminant = 0;
+ table->discriminant2 = 0;
+
+ if (table->table == max_index) {
+ table->deltatable = table->table - 1;
+ table->delta2table = table->table - 1;
+ } else if (table->table == 0) {
+ table->deltatable = table->table;
+ table->delta2table = table->table;
+ } else {
+ table->deltatable = table->table - 1;
+ table->delta2table = table->table;
+ }
+
+ } else {
+ if (table->discriminant < -64) table->discriminant = -64;
+ if (table->discriminant > 64) table->discriminant = 64;
+ if (table->discriminant2 < -64) table->discriminant2 = -64;
+ if (table->discriminant2 > 64) table->discriminant2 = 64;
+ }
+}
+
+void _jxr_AdaptLP(jxr_image_t image)
+{
+ AdaptVLCTable2(image, DecFirstIndLPLum, 4);
+ AdaptVLCTable2(image, DecIndLPLum0, 3);
+ AdaptVLCTable2(image, DecIndLPLum1, 3);
+ AdaptVLCTable2(image, DecFirstIndLPChr, 4);
+ AdaptVLCTable2(image, DecIndLPChr0, 3);
+ AdaptVLCTable2(image, DecIndLPChr1, 3);
+
+ _jxr_AdaptVLCTable(image, AbsLevelIndLP0);
+ _jxr_AdaptVLCTable(image, AbsLevelIndLP1);
+
+ DEBUG(" AdaptLP: DecFirstIndLPLum=%d\n", image->vlc_table[DecFirstIndLPLum].table);
+ DEBUG(" : DecIndLPLum0=%d\n", image->vlc_table[DecIndLPLum0].table);
+ DEBUG(" : DecIndLPLum1=%d\n", image->vlc_table[DecIndLPLum1].table);
+ DEBUG(" : DecFirstIndLPChr=%d\n", image->vlc_table[DecFirstIndLPChr].table);
+ DEBUG(" : DecIndLPChr0=%d\n", image->vlc_table[DecIndLPChr0].table);
+ DEBUG(" : DecIndLPChr1=%d\n", image->vlc_table[DecIndLPChr1].table);
+}
+
+void _jxr_AdaptHP(jxr_image_t image)
+{
+ AdaptVLCTable2(image, DecFirstIndHPLum, 4);
+ AdaptVLCTable2(image, DecIndHPLum0, 3);
+ AdaptVLCTable2(image, DecIndHPLum1, 3);
+ AdaptVLCTable2(image, DecFirstIndHPChr, 4);
+ AdaptVLCTable2(image, DecIndHPChr0, 3);
+ AdaptVLCTable2(image, DecIndHPChr1, 3);
+
+ _jxr_AdaptVLCTable(image, AbsLevelIndHP0);
+ _jxr_AdaptVLCTable(image, AbsLevelIndHP1);
+
+ _jxr_AdaptVLCTable(image, DecNumCBP);
+ _jxr_AdaptVLCTable(image, DecNumBlkCBP);
+}
+
+/*
+* Despite the name, this function doesn't actually reset a
+* context. It uses the tx (X position of the time) and mx (X position
+* of the macroblock in the tile) to calculate true or false that the
+* caller should invoke a context reset.
+*/
+int _jxr_InitContext(jxr_image_t image, unsigned tx, unsigned ty,
+ unsigned mx, unsigned my)
+{
+ if (mx == 0 && my == 0)
+ return 1;
+ else
+ return 0;
+}
+
+/*
+* This function guards Adapt?? functions that are called during the
+* parse. At the end of a MB where this function returns true, the
+* processing function will call the Adapt?? function.
+*
+* NOTE: It is *correct* that this function is true for the first and
+* the last macroblock. This allows some far right context of a tile
+* to inform the first column of the next line, but also allows crazy
+* differences to be adapted away.
+*/
+int _jxr_ResetContext(jxr_image_t image, unsigned tx, unsigned mx)
+{
+ assert(tx < image->tile_columns);
+ assert(image->tile_column_width);
+ /* Return true for every 16 macroblocks in the tile. */
+ if (mx%16 == 0)
+ return 1;
+ /* Return true for the final macroblock in the tile. */
+ if (image->tile_column_width[tx] == mx+1)
+ return 1;
+
+ return 0;
+}
+
+int _jxr_ResetTotals(jxr_image_t image, unsigned mx)
+{
+ if (mx%16 == 0)
+ return 1;
+ else return 0;
+}
+
+void _jxr_InitializeModelMB(struct model_s*model, int band)
+{
+ assert(band <= 2);
+
+ model->state[0] = 0;
+ model->state[1] = 0;
+ model->bits[0] = (2-band) * 4;
+ model->bits[1] = (2-band) * 4;
+}
+
+void _jxr_UpdateModelMB(jxr_image_t image, int lap_mean[2], struct model_s*model, int band)
+{
+ const int modelweight = 70;
+ static const int weight0[3] = { 240, 12, 1 };
+ static const int weight1[3][MAX_CHANNELS] = {
+ {0,240,120,80, 60,48,40,34, 30,27,24,22, 20,18,17,16 },
+ {0,12,6,4, 3,2,2,2, 2,1,1,1, 1,1,1,1 },
+ {0,16,8,5, 4,3,3,2, 2,2,2,1, 1,1,1,1 }
+ };
+ static const int weight2[6] = { 120,37,2, 120,18,1 };
+ int j;
+
+ assert(band < 3);
+
+ lap_mean[0] *= weight0[band];
+ switch (image->use_clr_fmt) {
+ case 1: /* YUV420 */
+ lap_mean[1] *= weight2[band];
+ break;
+ case 2: /* YUV422 */
+ lap_mean[1] *= weight2[3+band];
+ break;
+ default:
+ lap_mean[1] *= weight1[band][image->num_channels-1];
+ if (band == 2 /*HP*/)
+ lap_mean[1] >>= 4;
+ break;
+ }
+
+ for (j = 0; j < 2; j += 1) {
+ int ms = model->state[j];
+ int delta = (lap_mean[j] - modelweight) >> 2;
+
+ if (delta <= -8) {
+ delta += 4;
+ if (delta < -16)
+ delta = -16;
+ ms += delta;
+ if (ms < -8) {
+ if (model->bits[j] == 0) {
+ ms = -8;
+ } else {
+ ms = 0;
+ model->bits[j] -= 1;
+ }
+ }
+ } else if (delta >= 8) {
+ delta -= 4;
+ if (delta > 15)
+ delta = 15;
+ ms += delta;
+ if (ms > 8) {
+ if (model->bits[j] >= 15) {
+ model->bits[j] = 15;
+ ms = 8;
+ } else {
+ ms = 0;
+ model->bits[j] += 1;
+ }
+ }
+ }
+ model->state[j] = ms;
+ /* If clr_fmt == YONLY, then we really only want to do
+ this loop once, for j==0. */
+ if (image->use_clr_fmt == 0/*YONLY*/)
+ break;
+ }
+}
+
+void _jxr_InitializeCountCBPLP(jxr_image_t image)
+{
+ image->count_max_CBPLP = 1;
+ image->count_zero_CBPLP = 1;
+}
+
+void _jxr_UpdateCountCBPLP(jxr_image_t image, int cbplp, int max)
+{
+ image->count_zero_CBPLP += 1;
+ if (cbplp == 0)
+ image->count_zero_CBPLP -= 4;
+ if (image->count_zero_CBPLP > 7)
+ image->count_zero_CBPLP = 7;
+ if (image->count_zero_CBPLP < -8)
+ image->count_zero_CBPLP = -8;
+
+ image->count_max_CBPLP += 1;
+ if (cbplp == max)
+ image->count_max_CBPLP -= 4;
+ if (image->count_max_CBPLP > 7)
+ image->count_max_CBPLP = 7;
+ if (image->count_max_CBPLP < -8)
+ image->count_max_CBPLP = -8;
+}
+
+void _jxr_InitLPVLC(jxr_image_t image)
+{
+ DEBUG(" ... InitLPVLC\n");
+ InitVLCTable2(image, DecFirstIndLPLum);
+ InitVLCTable2(image, DecIndLPLum0);
+ InitVLCTable2(image, DecIndLPLum1);
+ InitVLCTable2(image, DecFirstIndLPChr);
+ InitVLCTable2(image, DecIndLPChr0);
+ InitVLCTable2(image, DecIndLPChr1);
+
+ _jxr_InitVLCTable(image, AbsLevelIndLP0);
+ _jxr_InitVLCTable(image, AbsLevelIndLP1);
+}
+
+void _jxr_InitializeAdaptiveScanLP(jxr_image_t image)
+{
+ static const int ScanOrderLP[15] = { 4, 1, 5,
+ 8, 2, 9, 6,
+ 12, 3, 10, 13,
+ 7, 14, 11, 15};
+ int idx;
+ for (idx = 0 ; idx < 15 ; idx += 1) {
+ image->lopass_scanorder[idx] = ScanOrderLP[idx];
+ image->lopass_scantotals[idx] = ScanTotals[idx];
+ }
+}
+
+/*
+*/
+void _jxr_InitializeAdaptiveScanHP(jxr_image_t image)
+{
+ static const unsigned ScanOrderHor[15] ={ 4, 1, 5,
+ 8, 2, 9, 6,
+ 12, 3, 10, 13,
+ 7, 14, 11, 15};
+ static const unsigned ScanOrderVer[15] ={ 1, 2, 5,
+ 4, 3, 6, 9,
+ 8, 7, 12, 15,
+ 13, 10, 11, 14};
+ int idx;
+ for (idx = 0 ; idx < 15 ; idx += 1) {
+ image->hipass_hor_scanorder[idx] = ScanOrderHor[idx];
+ image->hipass_hor_scantotals[idx] = ScanTotals[idx];
+ image->hipass_ver_scanorder[idx] = ScanOrderVer[idx];
+ image->hipass_ver_scantotals[idx] = ScanTotals[idx];
+ }
+}
+
+void _jxr_InitializeCBPModel(jxr_image_t image)
+{
+ image->hp_cbp_model.state[0] = 0;
+ image->hp_cbp_model.state[1] = 0;
+ image->hp_cbp_model.count0[0] = -4;
+ image->hp_cbp_model.count0[1] = -4;
+ image->hp_cbp_model.count1[0] = 4;
+ image->hp_cbp_model.count1[1] = 4;
+}
+
+void _jxr_InitHPVLC(jxr_image_t image)
+{
+ InitVLCTable2(image, DecFirstIndHPLum);
+ InitVLCTable2(image, DecIndHPLum0);
+ InitVLCTable2(image, DecIndHPLum1);
+ InitVLCTable2(image, DecFirstIndHPChr);
+ InitVLCTable2(image, DecIndHPChr0);
+ InitVLCTable2(image, DecIndHPChr1);
+
+ _jxr_InitVLCTable(image, AbsLevelIndHP0);
+ _jxr_InitVLCTable(image, AbsLevelIndHP1);
+
+ /* _jxr_InitVLCTable(image, DecNumCBP); */
+ /* _jxr_InitVLCTable(image, DecNumBlkCBP); */
+}
+
+void _jxr_InitCBPVLC(jxr_image_t image)
+{
+ _jxr_InitVLCTable(image, DecNumCBP);
+ _jxr_InitVLCTable(image, DecNumBlkCBP);
+}
+
+static int num_ones(int val)
+{
+ int cnt = 0;
+
+ assert(val >= 0);
+
+ while (val > 0) {
+ if (val&1) cnt += 1;
+ val >>= 1;
+ }
+ return cnt;
+}
+
+# define SAT(x) do { if ((x) > 15) (x)=15 ; else if ((x) < -16) (x)=-16; } while(0);
+
+static void update_cbp_model(jxr_image_t image, int c1, int norig)
+{
+ const int ndiff = 3;
+
+ struct cbp_model_s*hp_cbp_model = & (image->hp_cbp_model);
+
+ hp_cbp_model->count0[c1] += norig - ndiff;
+ SAT(hp_cbp_model->count0[c1]);
+
+ hp_cbp_model->count1[c1] += 16 - norig - ndiff;
+ SAT(hp_cbp_model->count1[c1]);
+
+ if (hp_cbp_model->count0[c1] < 0) {
+ if (hp_cbp_model->count0[c1] < hp_cbp_model->count1[c1])
+ hp_cbp_model->state[c1] = 1;
+ else
+ hp_cbp_model->state[c1] = 2;
+
+ } else if (hp_cbp_model->count1[c1] < 0) {
+ hp_cbp_model->state[c1] = 2;
+
+ } else {
+ hp_cbp_model->state[c1] = 0;
+ }
+}
+
+int _jxr_PredCBP444(jxr_image_t image, int*diff_cbp,
+ int channel, unsigned tx,
+ unsigned mx, unsigned my)
+{
+ int chroma_flag = 0;
+ int cbp;
+ int norig;
+
+ if (channel > 0)
+ chroma_flag = 1;
+
+ DEBUG(" PredCBP444: Prediction mode = %d\n", image->hp_cbp_model.state[chroma_flag]);
+ cbp = diff_cbp[channel];
+ if (image->hp_cbp_model.state[chroma_flag] == 0) {
+ if (mx == 0) {
+ if (my == 0)
+ cbp ^= 1;
+ else
+ cbp ^= (MACROBLK_UP1_HPCBP(image, channel, tx, mx)>>10)&1;
+ } else {
+ cbp ^= (MACROBLK_CUR_HPCBP(image, channel, tx, mx-1)>>5)&1;
+ }
+
+ cbp ^= 0x02 & (cbp<<1);
+ cbp ^= 0x10 & (cbp<<3);
+ cbp ^= 0x20 & (cbp<<1);
+ cbp ^= (cbp&0x33) << 2;
+ cbp ^= (cbp&0xcc) << 6;
+ cbp ^= (cbp&0x3300) << 2;
+
+ } else if (image->hp_cbp_model.state[chroma_flag] == 2) {
+ cbp ^= 0xffff;
+ }
+
+ norig = num_ones(cbp);
+ DEBUG(" PredCBP444: NOrig=%d, CBPModel.Count0/1[%d]= %d/%d\n", norig, chroma_flag,
+ image->hp_cbp_model.count0[chroma_flag],
+ image->hp_cbp_model.count1[chroma_flag]);
+ update_cbp_model(image, chroma_flag, norig);
+ DEBUG(" PredCBP444: ...becomes CBPModel.Count0/1[%d]= %d/%d, new state=%d\n",
+ chroma_flag, image->hp_cbp_model.count0[chroma_flag],
+ image->hp_cbp_model.count1[chroma_flag], image->hp_cbp_model.state[chroma_flag]);
+ return cbp;
+}
+
+void _jxr_w_PredCBP444(jxr_image_t image, int ch, unsigned tx, unsigned mx, int my)
+{
+ int chroma_flag = 0;
+ int cbp;
+ int norig;
+ if (ch > 0)
+ chroma_flag = 1;
+
+ DEBUG(" PredCBP444: Prediction mode = %d\n", image->hp_cbp_model.state[chroma_flag]);
+ cbp = MACROBLK_UP1_HPCBP(image,ch,tx,mx);
+ norig = num_ones(cbp);
+
+ DEBUG(" PredCBP444: ... cbp starts as 0x%x\n", cbp);
+
+ if (image->hp_cbp_model.state[chroma_flag] == 0) {
+
+ cbp ^= (cbp&0x3300) << 2;
+ cbp ^= (cbp&0xcc) << 6;
+ cbp ^= (cbp&0x33) << 2;
+ cbp ^= 0x20 & (cbp<<1);
+ cbp ^= 0x10 & (cbp<<3);
+ cbp ^= 0x02 & (cbp<<1);
+
+ if (mx == 0) {
+ if (my == 0)
+ cbp ^= 1;
+ else
+ cbp ^= (MACROBLK_CUR_HPCBP(image,ch, tx, mx)>>10)&1;
+ } else {
+ cbp ^= (MACROBLK_UP1_HPCBP(image,ch, tx, mx-1)>>5)&1;
+ }
+
+
+ } else if (image->hp_cbp_model.state[chroma_flag] == 2){
+ cbp ^= 0xffff;
+ }
+
+ DEBUG(" PredCBP444: ... diff_cbp 0x%04x\n", cbp);
+ MACROBLK_UP1(image,ch,tx,mx).hp_diff_cbp = cbp;
+
+ update_cbp_model(image, chroma_flag, norig);
+}
+
+int _jxr_PredCBP422(jxr_image_t image, int*diff_cbp,
+ int channel, unsigned tx,
+ unsigned mx, unsigned my)
+{
+ int cbp;
+ int norig;
+
+ assert(channel > 0);
+ DEBUG(" PredCBP422: Prediction mode = %d, channel=%d, cbp_mode.State[1]=%d\n",
+ image->hp_cbp_model.state[1], channel, image->hp_cbp_model.state[1]);
+ cbp = diff_cbp[channel];
+
+ if (image->hp_cbp_model.state[1] == 0) {
+ if (mx == 0) {
+ if (my == 0)
+ cbp ^= 1;
+ else
+ cbp ^= (MACROBLK_UP1_HPCBP(image, channel, tx, mx)>>6)&1;
+ } else {
+ cbp ^= (MACROBLK_CUR_HPCBP(image, channel, tx, mx-1)>>1)&1;
+ }
+
+ cbp ^= 0x02 & (cbp<<1);
+ cbp ^= 0x0c & (cbp<<2);
+ cbp ^= 0x30 & (cbp<<2);
+ cbp ^= 0xc0 & (cbp<<2);
+ } else if (image->hp_cbp_model.state[1] == 2) {
+ cbp ^= 0xff;
+ }
+
+ norig = num_ones(cbp) * 2;
+ update_cbp_model(image, 1, norig);
+
+ return cbp;
+}
+
+void _jxr_w_PredCBP422(jxr_image_t image, int ch, unsigned tx, unsigned mx, int my)
+{
+ int cbp;
+ int norig;
+
+ assert(ch > 0);
+ DEBUG(" PredCBP422: Prediction mode = %d\n", image->hp_cbp_model.state[1]);
+ cbp = MACROBLK_UP1_HPCBP(image,ch,tx,mx);
+ norig = num_ones(cbp) * 2;
+
+ DEBUG(" PredCBP422: ... cbp[%d] starts as 0x%x\n", ch, cbp);
+
+ if (image->hp_cbp_model.state[1] == 0) {
+
+ cbp ^= 0xc0 & (cbp<<2);
+ cbp ^= 0x30 & (cbp<<2);
+ cbp ^= 0x0c & (cbp<<2);
+ cbp ^= 0x02 & (cbp<<1);
+
+ if (mx == 0) {
+ if (my == 0)
+ cbp ^= 1;
+ else
+ cbp ^= (MACROBLK_CUR_HPCBP(image, ch, tx, mx)>>6)&1;
+ } else {
+ cbp ^= (MACROBLK_UP1_HPCBP(image, ch, tx, mx-1)>>1)&1;
+ }
+
+ } else if (image->hp_cbp_model.state[1] == 2) {
+ cbp ^= 0xff;
+ }
+
+ DEBUG(" PredCBP422: ... diff_cbp 0x%04x\n", cbp);
+ MACROBLK_UP1(image,ch,tx,mx).hp_diff_cbp = cbp;
+
+ update_cbp_model(image, 1, norig);
+}
+
+
+int _jxr_PredCBP420(jxr_image_t image, int*diff_cbp,
+ int channel, unsigned tx,
+ unsigned mx, unsigned my)
+{
+ int cbp;
+ int norig;
+ assert(channel > 0);
+ DEBUG(" PredCBP420: Prediction mode = %d, channel=%d, cbp_mode.State[1]=%d\n",
+ image->hp_cbp_model.state[1], channel, image->hp_cbp_model.state[1]);
+ cbp = diff_cbp[channel];
+
+ if (image->hp_cbp_model.state[1] == 0) {
+ if (mx == 0) {
+ if (my == 0)
+ cbp ^= 1;
+ else
+ cbp ^= (MACROBLK_UP1_HPCBP(image, channel, tx, mx)>>2)&1;
+ } else {
+ cbp ^= (MACROBLK_CUR_HPCBP(image, channel, tx, mx-1)>>1)&1;
+ }
+
+ cbp ^= 0x02 & (cbp<<1);
+ cbp ^= 0x0c & (cbp<<2);
+ } else if (image->hp_cbp_model.state[1] == 2) {
+ cbp ^= 0xf;
+ }
+
+ norig = num_ones(cbp) * 4;
+ update_cbp_model(image, 1, norig);
+
+ return cbp;
+}
+
+void _jxr_w_PredCBP420(jxr_image_t image, int ch, unsigned tx, unsigned mx, int my)
+{
+ int cbp;
+ int norig;
+ assert(ch > 0);
+ DEBUG(" PredCBP420: Prediction mode = %d\n", image->hp_cbp_model.state[1]);
+ cbp = MACROBLK_UP1_HPCBP(image,ch,tx,mx);
+ norig = num_ones(cbp) * 4;
+
+ DEBUG(" PredCBP420: ... cbp[%d] starts as 0x%x\n", ch, cbp);
+
+ if (image->hp_cbp_model.state[1] == 0) {
+
+ cbp ^= 0x0c & (cbp<<2);
+ cbp ^= 0x02 & (cbp<<1);
+
+ if (mx == 0) {
+ if (my == 0)
+ cbp ^= 1;
+ else
+ cbp ^= (MACROBLK_CUR_HPCBP(image, ch, tx, mx)>>2)&1;
+ } else {
+ cbp ^= (MACROBLK_UP1_HPCBP(image, ch, tx, mx-1)>>1)&1;
+ }
+
+ } else if (image->hp_cbp_model.state[1] == 2) {
+ cbp ^= 0xf;
+ }
+
+ DEBUG(" PredCBP420: ... diff_cbp 0x%04x\n", cbp);
+ MACROBLK_UP1(image,ch,tx,mx).hp_diff_cbp = cbp;
+
+ update_cbp_model(image, 1, norig);
+}
+
+void _jxr_ResetTotalsAdaptiveScanLP(jxr_image_t image)
+{
+ int idx;
+ for (idx = 0 ; idx < 15 ; idx += 1) {
+ image->lopass_scantotals[idx] = ScanTotals[idx];
+ }
+}
+
+void _jxr_ResetTotalsAdaptiveScanHP(jxr_image_t image)
+{
+ int idx;
+ for (idx = 0 ; idx < 15 ; idx += 1) {
+ image->hipass_hor_scantotals[idx] = ScanTotals[idx];
+ image->hipass_ver_scantotals[idx] = ScanTotals[idx];
+ }
+}
+
+static int
+calculate_mbdc_mode(jxr_image_t image, int tx, int mx, int my)
+{
+ long left;
+ long top;
+ long topleft;
+ long strhor;
+ long strvert;
+
+ if (mx == 0 && my == 0)
+ return 3; /* No prediction. */
+
+ if (mx == 0)
+ return 1; /* Predictions from top only. */
+
+ if (my == 0)
+ return 0; /* prediction from left only */
+
+ left = MACROBLK_CUR_DC(image, 0, tx, mx-1);
+ top = MACROBLK_UP_DC(image, 0, tx, mx);
+ topleft = MACROBLK_UP_DC(image, 0, tx, mx-1);
+
+ strhor = 0;
+ strvert = 0;
+ if (image->use_clr_fmt==0 || image->use_clr_fmt==6) {/* YONLY or NCOMPONENT */
+
+ strhor = labs(topleft - left);
+ strvert = labs(topleft - top);
+ } else {
+ long left_u = MACROBLK_CUR_DC(image, 1, tx, mx-1);
+ long top_u = MACROBLK_UP_DC(image, 1, tx, mx);
+ long topleft_u = MACROBLK_UP_DC(image, 1, tx, mx-1);
+ long left_v = MACROBLK_CUR_DC(image, 2, tx, mx-1);
+ long top_v = MACROBLK_UP_DC(image, 2, tx, mx);
+ long topleft_v = MACROBLK_UP_DC(image, 2, tx, mx-1);
+
+ long scale = 2;
+ if (image->use_clr_fmt == 2 /*YUV422*/)
+ scale = 4;
+ if (image->use_clr_fmt == 1 /*YUV420*/)
+ scale = 8;
+
+ strhor = labs(topleft - left)*scale + labs(topleft_u - left_u) + labs(topleft_v - left_v);
+ strvert = labs(topleft - top)*scale + labs(topleft_u - top_u) + labs(topleft_v - top_v);
+ }
+
+ if ((strhor*4) < strvert)
+ return 1;
+
+ if ((strvert*4) < strhor)
+ return 0;
+
+ return 2;
+}
+
+static void predict_lp444(jxr_image_t image, int tx, int mx, int my, int ch, int mblp_mode);
+static void predict_lp422(jxr_image_t image, int tx, int mx, int my, int ch, int mblp_mode, int mbdc_mode);
+static void predict_lp420(jxr_image_t image, int tx, int mx, int my, int ch, int mblp_mode);
+
+void _jxr_complete_cur_dclp(jxr_image_t image, int tx, int mx, int my)
+{
+ /* Calculate the mbcd prediction mode. This mode is used for
+ all the planes of DC data. */
+ int mbdc_mode = calculate_mbdc_mode(image, tx, mx, image->cur_my);
+ int mblp_mode;
+ /* Now process all the planes of DC data. */
+ int ch;
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ long left = mx>0? MACROBLK_CUR_DC(image,ch,tx,mx-1) : 0;
+ long top = MACROBLK_UP_DC(image,ch,tx,mx);
+
+ DEBUG(" MBDC_MODE=%d for TX=%d, MBx=%d, MBy=%d (cur_my=%d), ch=%d, left=0x%lx, top=0x%lx, cur=0x%x\n",
+ mbdc_mode, tx, mx, my, image->cur_my, ch, left, top, MACROBLK_CUR_DC(image,ch,tx,mx));
+
+ MACROBLK_CUR(image,ch,tx,mx).pred_dclp[0] = MACROBLK_CUR_DC(image,ch,tx,mx);
+ CHECK1(image->lwf_test, MACROBLK_CUR_DC(image,ch,tx,mx));
+ switch (mbdc_mode) {
+ case 0: /* left */
+ MACROBLK_CUR_DC(image,ch,tx,mx) += left;
+ break;
+ case 1: /* top */
+ MACROBLK_CUR_DC(image,ch,tx,mx) += top;
+ break;
+ case 2:/* top and left */
+ /* Note that we really MEAN >>1 and NOT /2. in
+ particular, if the sum is -1, we want the
+ result to also be -1. That extra stuff after
+ the "|" is there to make sure the sign bit is
+ not lost. Also, the chroma planes for YUV42X
+ formats round *up* the mean, where all other
+ planes round down. */
+ if (ch>0 && (image->use_clr_fmt==1/*YUV420*/||image->use_clr_fmt==2/*YUV422*/))
+ MACROBLK_CUR_DC(image,ch,tx,mx) += (left+top+1) >> 1 | ((left+top+1)&~INT_MAX);
+ else
+ MACROBLK_CUR_DC(image,ch,tx,mx) += (left+top) >> 1 | ((left+top)&~INT_MAX);
+ break;
+ default:
+ break;
+ }
+ }
+
+ mblp_mode = 0;
+ if (mbdc_mode==0 && MACROBLK_CUR_LP_QUANT(image,0,tx,mx) == MACROBLK_CUR_LP_QUANT(image,0,tx,mx-1)) {
+ mblp_mode = 0;
+ } else if (mbdc_mode==1 && MACROBLK_CUR_LP_QUANT(image,0,tx,mx) == MACROBLK_UP1_LP_QUANT(image,0,tx,mx)) {
+ mblp_mode = 1;
+
+ } else {
+ mblp_mode = 2;
+ }
+
+ DEBUG(" MBLP_MODE=%d for MBx=%d, MBy=%d (lp_quant=%d,lp_quant_ctx=%d)\n", mblp_mode, mx, image->cur_my,
+ MACROBLK_CUR_LP_QUANT(image,0,tx,mx),
+ mbdc_mode==0? MACROBLK_CUR_LP_QUANT(image,0,tx,mx-1) : mbdc_mode==1 ? MACROBLK_UP1_LP_QUANT(image,0,tx,mx) : -1);
+
+ predict_lp444(image, tx, mx, my, 0, mblp_mode);
+ for (ch = 1 ; ch < image->num_channels ; ch += 1) {
+ switch (image->use_clr_fmt) {
+ case 1: /* YUV420 */
+ predict_lp420(image, tx, mx, my, ch, mblp_mode);
+ break;
+ case 2: /* YUV422 */
+ predict_lp422(image, tx, mx, my, ch, mblp_mode, mbdc_mode);
+ break;
+ default:
+ predict_lp444(image,tx, mx, my, ch, mblp_mode);
+ break;
+ }
+ }
+}
+
+static void predict_lp444(jxr_image_t image, int tx, int mx, int my, int ch, int mblp_mode)
+{
+#if defined(DETAILED_DEBUG)
+ {
+ int jdx;
+ DEBUG(" DC/LP (strip=%3d, mbx=%4d, ch=%d) Difference:", my, mx, ch);
+ DEBUG(" 0x%08x", MACROBLK_CUR(image,ch,tx,mx).pred_dclp[0]);
+ for (jdx = 0; jdx < 15 ; jdx += 1) {
+ DEBUG(" 0x%08x", MACROBLK_CUR_LP(image,ch,tx,mx,jdx));
+ if ((jdx+1)%4 == 3 && jdx != 14)
+ DEBUG("\n%*s:", 46, "");
+ }
+ DEBUG("\n");
+ }
+#endif
+
+ switch (mblp_mode) {
+ case 0: /* left */
+ CHECK3(image->lwf_test, MACROBLK_CUR_LP(image,ch,tx,mx,3), MACROBLK_CUR_LP(image,ch,tx,mx,7), MACROBLK_CUR_LP(image,ch,tx,mx,11));
+ MACROBLK_CUR_LP(image,ch,tx,mx,3) += MACROBLK_CUR(image,ch,tx,mx-1).pred_dclp[4];
+ MACROBLK_CUR_LP(image,ch,tx,mx,7) += MACROBLK_CUR(image,ch,tx,mx-1).pred_dclp[5];
+ MACROBLK_CUR_LP(image,ch,tx,mx,11)+= MACROBLK_CUR(image,ch,tx,mx-1).pred_dclp[6];
+ break;
+ case 1: /* up */
+ CHECK3(image->lwf_test, MACROBLK_CUR_LP(image,ch,tx,mx,0), MACROBLK_CUR_LP(image,ch,tx,mx,1), MACROBLK_CUR_LP(image,ch,tx,mx,2));
+ MACROBLK_CUR_LP(image,ch,tx,mx,0) += MACROBLK_UP1(image,ch,tx,mx).pred_dclp[1];
+ MACROBLK_CUR_LP(image,ch,tx,mx,1) += MACROBLK_UP1(image,ch,tx,mx).pred_dclp[2];
+ MACROBLK_CUR_LP(image,ch,tx,mx,2) += MACROBLK_UP1(image,ch,tx,mx).pred_dclp[3];
+ break;
+ case 2:
+ break;
+ }
+
+#if defined(DETAILED_DEBUG)
+ {
+ int jdx;
+ DEBUG(" DC/LP (strip=%3d, mbx=%4d, ch=%d) Predicted:", my, mx, ch);
+ DEBUG(" 0x%08x", MACROBLK_CUR_DC(image,ch,tx,mx));
+ for (jdx = 0; jdx < 15 ; jdx += 1) {
+ DEBUG(" 0x%08x", MACROBLK_CUR_LP(image,ch,tx,mx,jdx));
+ if ((jdx+1)%4 == 3 && jdx != 14)
+ DEBUG("\n%*s:", 45, "");
+ }
+ DEBUG("\n");
+ }
+#endif
+
+ MACROBLK_CUR(image,ch,tx,mx).pred_dclp[1] = MACROBLK_CUR_LP(image,ch,tx,mx,0);
+ MACROBLK_CUR(image,ch,tx,mx).pred_dclp[2] = MACROBLK_CUR_LP(image,ch,tx,mx,1);
+ MACROBLK_CUR(image,ch,tx,mx).pred_dclp[3] = MACROBLK_CUR_LP(image,ch,tx,mx,2);
+ MACROBLK_CUR(image,ch,tx,mx).pred_dclp[4] = MACROBLK_CUR_LP(image,ch,tx,mx,3);
+ MACROBLK_CUR(image,ch,tx,mx).pred_dclp[5] = MACROBLK_CUR_LP(image,ch,tx,mx,7);
+ MACROBLK_CUR(image,ch,tx,mx).pred_dclp[6] = MACROBLK_CUR_LP(image,ch,tx,mx,11);
+}
+
+static void predict_lp422(jxr_image_t image, int tx, int mx, int my, int ch, int mblp_mode, int mbdc_mode)
+{
+#if defined(DETAILED_DEBUG)
+ {
+ int jdx;
+ DEBUG(" DC/LP (strip=%3d, tx=%d, mbx=%4d, ch=%d) Difference:", my, tx, mx, ch);
+ DEBUG(" 0x%08x", MACROBLK_CUR(image,ch,tx,mx).pred_dclp[0]);
+ for (jdx = 0; jdx < 7 ; jdx += 1) {
+ DEBUG(" 0x%08x", MACROBLK_CUR_LP(image,ch,tx,mx,jdx));
+ if ((jdx+1)%4 == 3 && jdx != 6)
+ DEBUG("\n%*s:", 52, "");
+ }
+ DEBUG("\n");
+ }
+#endif
+
+ switch (mblp_mode) {
+case 0: /* left */
+ CHECK3(image->lwf_test, MACROBLK_CUR_LP(image,ch,tx,mx,3), MACROBLK_CUR_LP(image,ch,tx,mx,1), MACROBLK_CUR_LP(image,ch,tx,mx,5));
+ MACROBLK_CUR_LP(image,ch,tx,mx,3) += MACROBLK_CUR(image,ch,tx,mx-1).pred_dclp[4];
+ MACROBLK_CUR_LP(image,ch,tx,mx,1) += MACROBLK_CUR(image,ch,tx,mx-1).pred_dclp[2];
+ MACROBLK_CUR_LP(image,ch,tx,mx,5) += MACROBLK_CUR(image,ch,tx,mx-1).pred_dclp[6];
+ break;
+case 1: /* up */
+ CHECK3(image->lwf_test, MACROBLK_CUR_LP(image,ch,tx,mx,3), MACROBLK_CUR_LP(image,ch,tx,mx,0), MACROBLK_CUR_LP(image,ch,tx,mx,4));
+ MACROBLK_CUR_LP(image,ch,tx,mx,3) += MACROBLK_UP1(image,ch,tx,mx).pred_dclp[4];
+ MACROBLK_CUR_LP(image,ch,tx,mx,0) += MACROBLK_UP1(image,ch,tx,mx).pred_dclp[5];
+ MACROBLK_CUR_LP(image,ch,tx,mx,4) += MACROBLK_CUR_LP(image,ch,tx,mx,0);
+ break;
+case 2:
+ if (mbdc_mode == 1)
+ {
+ CHECK1(image->lwf_test, MACROBLK_CUR_LP(image,ch,tx,mx,4));
+ MACROBLK_CUR_LP(image,ch,tx,mx,4) += MACROBLK_CUR_LP(image,ch,tx,mx,0);
+ }
+ break;
+ }
+
+#if defined(DETAILED_DEBUG)
+ {
+ int jdx;
+ DEBUG(" DC/LP (strip=%3d, tx=%d, mbx=%4d, ch=%d) Predicted:", my, tx, mx, ch);
+ DEBUG(" 0x%08x", MACROBLK_CUR_DC(image,ch,tx,mx));
+ for (jdx = 0; jdx < 7 ; jdx += 1) {
+ DEBUG(" 0x%08x", MACROBLK_CUR_LP(image,ch,tx,mx,jdx));
+ if ((jdx+1)%4 == 3 && jdx != 6)
+ DEBUG("\n%*s:", 51, "");
+ }
+ DEBUG("\n");
+ }
+#endif
+
+ MACROBLK_CUR(image,ch,tx,mx).pred_dclp[1] = MACROBLK_CUR_LP(image,ch,tx,mx,0);
+ MACROBLK_CUR(image,ch,tx,mx).pred_dclp[2] = MACROBLK_CUR_LP(image,ch,tx,mx,1);
+ MACROBLK_CUR(image,ch,tx,mx).pred_dclp[4] = MACROBLK_CUR_LP(image,ch,tx,mx,3);
+ MACROBLK_CUR(image,ch,tx,mx).pred_dclp[5] = MACROBLK_CUR_LP(image,ch,tx,mx,4);
+ MACROBLK_CUR(image,ch,tx,mx).pred_dclp[6] = MACROBLK_CUR_LP(image,ch,tx,mx,5);
+}
+
+static void predict_lp420(jxr_image_t image, int tx, int mx, int my, int ch, int mblp_mode)
+{
+ switch (mblp_mode) {
+ case 0: /* left */
+ CHECK1(image->lwf_test, MACROBLK_CUR_LP(image,ch,tx,mx,1));
+ MACROBLK_CUR_LP(image,ch,tx,mx,1) += MACROBLK_CUR(image,ch,tx,mx-1).pred_dclp[2];
+ break;
+ case 1: /* up */
+ CHECK1(image->lwf_test, MACROBLK_CUR_LP(image,ch,tx,mx,0));
+ MACROBLK_CUR_LP(image,ch,tx,mx,0) += MACROBLK_UP1(image,ch,tx,mx).pred_dclp[1];
+ break;
+ }
+
+#if defined(DETAILED_DEBUG)
+ {
+ int jdx;
+ DEBUG(" DC/LP (strip=%3d, tx=%d, mbx=%4d, ch=%d) Predicted:", tx, my, mx, ch);
+ DEBUG(" 0x%08x", MACROBLK_CUR_DC(image,ch,tx,mx));
+ for (jdx = 0; jdx < 3 ; jdx += 1) {
+ DEBUG(" 0x%08x", MACROBLK_CUR_LP(image,ch,tx,mx,jdx));
+ }
+ DEBUG("\n");
+ }
+#endif
+
+ MACROBLK_CUR(image,ch,tx,mx).pred_dclp[1] = MACROBLK_CUR_LP(image,ch,tx,mx,0);
+ MACROBLK_CUR(image,ch,tx,mx).pred_dclp[2] = MACROBLK_CUR_LP(image,ch,tx,mx,1);
+}
+
+/*
+* TRANSFORM functions, forward and inverse.
+*/
+static void _InvPermute(int*coeff)
+{
+ static const int inverse[16] = {0, 8, 4, 13,
+ 2, 15, 3, 14,
+ 1, 12, 5, 9,
+ 7, 11, 6, 10};
+ int t[16];
+ int idx;
+
+ for (idx = 0 ; idx < 16 ; idx += 1)
+ t[inverse[idx]] = coeff[idx];
+ for (idx = 0 ; idx < 16 ; idx += 1)
+ coeff[idx] = t[idx];
+}
+
+static void _FwdPermute(int*coeff)
+{
+ static const int fwd[16] = {0, 8, 4, 6,
+ 2, 10, 14, 12,
+ 1, 11, 15, 13,
+ 9, 3, 7, 5};
+
+ int t[16];
+ int idx;
+ for (idx = 0 ; idx < 16 ; idx += 1)
+ t[fwd[idx]] = coeff[idx];
+ for (idx = 0 ; idx < 16 ; idx += 1)
+ coeff[idx] = t[idx];
+}
+
+static void _2x2T_h(int*a, int*b, int*c, int*d, int R_flag)
+{
+ int t1;
+ int t2;
+ *a += *d;
+ *b -= *c;
+
+ t1 = ((*a - *b + R_flag) >> 1);
+ t2 = *c;
+
+ *c = t1 - *d;
+ *d = t1 - t2;
+ CHECK5(long_word_flag, *a, *b, t1, *c, *d);
+ *a -= *d;
+ *b += *c;
+ CHECK2(long_word_flag, *a, *b);
+}
+
+static void _2x2T_h_POST(int*a, int*b, int*c, int*d)
+{
+ int t1;
+ *b -= *c;
+ *a += (*d * 3 + 4) >> 3;
+ *d -= *b >> 1;
+ t1 = ((*a - *b) >> 1) - *c;
+ CHECK4(long_word_flag, *b, *a, *d, t1);
+ *c = *d;
+ *d = t1;
+ *a -= *d;
+ *b += *c;
+ CHECK2(long_word_flag, *a, *b);
+}
+
+static void _2x2T_h_Enc(int*a, int*b, int*c, int*d)
+{
+ int t1;
+ int t2;
+ *a += *d;
+ *b -= *c;
+ CHECK2(long_word_flag, *a, *b);
+ t1 = *d;
+ t2 = *c;
+ *c = ((*a - *b) >> 1) - t1;
+ *d = t2 + (*b >> 1);
+ *b += *c;
+ *a -= (*d * 3 + 4) >> 3;
+ CHECK4(long_word_flag, *c, *d, *b, *a);
+}
+
+static void _InvT_odd(int*a, int*b, int*c, int*d)
+{
+ *b += *d;
+ *a -= *c;
+ *d -= *b >> 1;
+ *c += (*a + 1) >> 1;
+ CHECK4(long_word_flag, *a, *b, *c, *d);
+
+ *a -= ((*b)*3 + 4) >> 3;
+ *b += ((*a)*3 + 4) >> 3;
+ *c -= ((*d)*3 + 4) >> 3;
+ *d += ((*c)*3 + 4) >> 3;
+ CHECK4(long_word_flag, *a, *b, *c, *d);
+
+ *c -= (*b + 1) >> 1;
+ *d = ((*a + 1) >> 1) - *d;
+ *b += *c;
+ *a -= *d;
+ CHECK4(long_word_flag, *a, *b, *c, *d);
+}
+
+static void _InvT_odd_odd(int*a, int*b, int*c, int*d)
+{
+ int t1, t2;
+ *d += *a;
+ *c -= *b;
+ t1 = *d >> 1;
+ t2 = *c >> 1;
+ *a -= t1;
+ *b += t2;
+ CHECK4(long_word_flag, *a, *b, *c, *d);
+
+ *a -= ((*b)*3 + 3) >> 3;
+ *b += ((*a)*3 + 3) >> 2;
+ CHECK2(long_word_flag, *a, *b);
+ *a -= ((*b)*3 + 4) >> 3;
+
+ *b -= t2;
+ CHECK2(long_word_flag, *a, *b);
+ *a += t1;
+ *c += *b;
+ *d -= *a;
+
+ *b = -*b;
+ *c = -*c;
+ CHECK4(long_word_flag, *a, *b, *c, *d);
+}
+
+static void _InvT_odd_odd_POST(int*a, int*b, int*c, int*d)
+{
+ int t1, t2;
+
+ *d += *a;
+ *c -= *b;
+ t1 = *d >> 1;
+ t2 = *c >> 1;
+ *a -= t1;
+ *b += t2;
+ CHECK4(long_word_flag, *d, *c, *a, *b);
+
+ *a -= (*b * 3 + 6) >> 3;
+ *b += (*a * 3 + 2) >> 2;
+ CHECK2(long_word_flag, *a, *b);
+ *a -= (*b * 3 + 4) >> 3;
+
+ *b -= t2;
+ CHECK2(long_word_flag, *a, *b);
+ *a += t1;
+ *c += *b;
+ *d -= *a;
+ CHECK3(long_word_flag, *a, *c, *d);
+}
+
+static void _T_odd(int*a, int*b, int*c, int*d)
+{
+ *b -= *c;
+ *a += *d;
+ *c += (*b + 1) >> 1;
+ *d = ((*a + 1) >> 1) - *d;
+ CHECK4(long_word_flag, *b, *a, *c, *d);
+
+ *b -= (*a * 3 + 4) >> 3;
+ *a += (*b * 3 + 4) >> 3;
+ *d -= (*c * 3 + 4) >> 3;
+ *c += (*d * 3 + 4) >> 3;
+ CHECK4(long_word_flag, *b, *a, *d, *c);
+
+ *d += *b >> 1;
+ *c -= (*a + 1) >> 1;
+ *b -= *d;
+ *a += *c;
+ CHECK4(long_word_flag, *d, *c, *b, *a);
+}
+
+static void _T_odd_odd(int*a, int*b, int*c, int*d)
+{
+ int t1;
+ int t2;
+ *b = -*b;
+ *c = -*c;
+ CHECK2(long_word_flag, *b, *c);
+
+ *d += *a;
+ *c -= *b;
+ t1 = *d >> 1;
+ t2 = *c >> 1;
+ *a -= t1;
+ *b += t2;
+ CHECK4(long_word_flag, *d, *c, *a, *b);
+
+ *a += (*b * 3 + 4) >> 3;
+ *b -= (*a * 3 + 3) >> 2;
+ CHECK2(long_word_flag, *a, *b);
+ *a += (*b * 3 + 3) >> 3;
+
+ *b -= t2;
+ CHECK2(long_word_flag, *a, *b);
+ *a += t1;
+ *c += *b;
+ *d -= *a;
+ CHECK3(long_word_flag, *a, *c, *d);
+}
+
+void _jxr_InvPermute2pt(int*a, int*b)
+{
+ int t1 = *a;
+ *a = *b;
+ *b = t1;
+}
+
+void _jxr_2ptT(int*a, int*b)
+{
+ *a -= (*b + 1) >> 1;
+ *b += *a;
+ CHECK2(long_word_flag, *a, *b);
+}
+
+/* This is the inverse of the 2ptT function */
+void _jxr_2ptFwdT(int*a, int*b)
+{
+ *b -= *a;
+ *a += (*b + 1) >> 1;
+ CHECK2(long_word_flag, *b, *a);
+}
+
+void _jxr_2x2IPCT(int*coeff)
+{
+ _2x2T_h(coeff+0, coeff+1, coeff+2, coeff+3, 0);
+ /* _2x2T_h(coeff+0, coeff+2, coeff+1, coeff+3, 0); */
+}
+
+void _jxr_4x4IPCT(int*coeff)
+{
+ /* Permute */
+ _InvPermute(coeff);
+
+#if defined(DETAILED_DEBUG) && 0
+ {
+ int idx;
+ DEBUG(" InvPermute:\n%*s", 4, "");
+ for (idx = 0 ; idx < 16 ; idx += 1) {
+ DEBUG(" 0x%08x", coeff[idx]);
+ if (idx%4 == 3 && idx != 15)
+ DEBUG("\n%*s", 4, "");
+ }
+ DEBUG("\n");
+ }
+#endif
+ _2x2T_h (coeff+0, coeff+ 1, coeff+4, coeff+ 5, 1);
+ _InvT_odd(coeff+2, coeff+ 3, coeff+6, coeff+ 7);
+ _InvT_odd(coeff+8, coeff+12, coeff+9, coeff+13);
+ _InvT_odd_odd(coeff+10, coeff+11, coeff+14, coeff+15);
+#if defined(DETAILED_DEBUG) && 0
+ {
+ int idx;
+ DEBUG(" stage 1:\n%*s", 4, "");
+ for (idx = 0 ; idx < 16 ; idx += 1) {
+ DEBUG(" 0x%08x", coeff[idx]);
+ if (idx%4 == 3 && idx != 15)
+ DEBUG("\n%*s", 4, "");
+ }
+ DEBUG("\n");
+ }
+#endif
+
+ _2x2T_h(coeff+0, coeff+3, coeff+12, coeff+15, 0);
+ _2x2T_h(coeff+5, coeff+6, coeff+ 9, coeff+10, 0);
+ _2x2T_h(coeff+1, coeff+2, coeff+13, coeff+14, 0);
+ _2x2T_h(coeff+4, coeff+7, coeff+ 8, coeff+11, 0);
+}
+
+void _jxr_4x4PCT(int*coeff)
+{
+ _2x2T_h(coeff+0, coeff+3, coeff+12, coeff+15, 0);
+ _2x2T_h(coeff+5, coeff+6, coeff+ 9, coeff+10, 0);
+ _2x2T_h(coeff+1, coeff+2, coeff+13, coeff+14, 0);
+ _2x2T_h(coeff+4, coeff+7, coeff+ 8, coeff+11, 0);
+
+ _2x2T_h (coeff+0, coeff+ 1, coeff+4, coeff+ 5, 1);
+ _T_odd(coeff+2, coeff+ 3, coeff+6, coeff+ 7);
+ _T_odd(coeff+8, coeff+12, coeff+9, coeff+13);
+ _T_odd_odd(coeff+10, coeff+11, coeff+14, coeff+15);
+
+ _FwdPermute(coeff);
+}
+
+static void _InvRotate(int*a, int*b)
+{
+ *a -= (*b + 1) >> 1;
+ *b += (*a + 1) >> 1;
+ CHECK2(long_word_flag, *a, *b);
+}
+
+static void _InvScale(int*a, int*b)
+{
+ *a += *b;
+ *b = (*a >> 1) - *b;
+ CHECK2(long_word_flag, *a, *b);
+ *a += (*b * 3 + 0) >> 3;
+ *b -= *a >> 10;
+ CHECK2(long_word_flag, *a, *b);
+ *b += *a >> 7;
+ *b += (*a * 3 + 0) >> 4;
+ CHECK1(long_word_flag, *b);
+}
+
+void _jxr_4x4OverlapFilter(int*a, int*b, int*c, int*d,
+ int*e, int*f, int*g, int*h,
+ int*i, int*j, int*k, int*l,
+ int*m, int*n, int*o, int*p)
+{
+ _2x2T_h(a, d, m, p, 0);
+ _2x2T_h(b, c, n, o, 0);
+ _2x2T_h(e, h, i, l, 0);
+ _2x2T_h(f, g, j, k, 0);
+
+ _InvRotate(n, m);
+ _InvRotate(j, i);
+ _InvRotate(h, d);
+ _InvRotate(g, c);
+ _InvT_odd_odd_POST(k, l, o, p);
+
+ _InvScale(a, p);
+ _InvScale(b, o);
+ _InvScale(e, l);
+ _InvScale(f, k);
+
+ _2x2T_h_POST(a, d, m, p);
+ _2x2T_h_POST(b, c, n, o);
+ _2x2T_h_POST(e, h, i, l);
+ _2x2T_h_POST(f, g, j, k);
+}
+
+void _jxr_4OverlapFilter(int*a, int*b, int*c, int*d)
+{
+ *a += *d;
+ *b += *c;
+ *d -= ((*a + 1) >> 1);
+ *c -= ((*b + 1) >> 1);
+ CHECK4(long_word_flag, *a, *b, *d, *c);
+ _InvScale(a, d);
+ _InvScale(b, c);
+ *a += ((*d * 3 + 4) >> 3);
+ *b += ((*c * 3 + 4) >> 3);
+ *d -= (*a >> 1);
+ *c -= (*b >> 1);
+ CHECK4(long_word_flag, *a, *b, *d, *c);
+ *a += *d;
+ *b += *c;
+ *d *= -1;
+ *c *= -1;
+ CHECK4(long_word_flag, *a, *b, *d, *c);
+ _InvRotate(c, d);
+ *d += ((*a + 1) >> 1);
+ *c += ((*b + 1) >> 1);
+ *a -= *d;
+ *b -= *c;
+ CHECK4(long_word_flag, *a, *b, *d, *c);
+}
+
+void _jxr_2x2OverlapFilter(int*a, int*b, int*c, int*d)
+{
+ *a += *d;
+ *b += *c;
+ *d -= (*a + 1) >> 1;
+ *c -= (*b + 1) >> 1;
+ CHECK4(long_word_flag, *a, *b, *d, *c);
+ *b += (*a + 2) >> 2;
+ *a += (*b + 1) >> 1;
+
+ *a += (*b >> 5);
+ *a += (*b >> 9);
+ *a += (*b >> 13);
+ CHECK2(long_word_flag, *a, *b);
+
+ *b += (*a + 2) >> 2;
+
+ *d += (*a + 1) >> 1;
+ *c += (*b + 1) >> 1;
+ *a -= *d;
+ CHECK4(long_word_flag, *a, *b, *d, *c);
+ *b -= *c;
+ CHECK1(long_word_flag, *b);
+}
+
+void _jxr_2OverlapFilter(int*a, int*b)
+{
+ *b += ((*a + 2) >> 2);
+ *a += ((*b + 1) >> 1);
+ *a += (*b >> 5);
+ *a += (*b >> 9);
+ CHECK2(long_word_flag, *a, *b);
+ *a += (*b >> 13);
+ *b += ((*a + 2) >> 2);
+ CHECK2(long_word_flag, *a, *b);
+}
+
+/* Prefiltering... */
+
+static void fwdT_Odd_Odd_PRE(int*a, int*b, int*c, int*d)
+{
+ int t1;
+ int t2;
+ *d += *a;
+ *c -= *b;
+ t1 = *d >> 1;
+ t2 = *c >> 1;
+ *a -= t1;
+ *b += t2;
+ CHECK4(long_word_flag, *d, *c, *a, *b);
+ *a += (*b * 3 + 4) >> 3;
+ *b -= (*a * 3 + 2) >> 2;
+ CHECK2(long_word_flag, *a, *b);
+ *a += (*b * 3 + 6) >> 3;
+ *b -= t2;
+ CHECK2(long_word_flag, *a, *b);
+ *a += t1;
+ *c += *b;
+ *d -= *a;
+ CHECK3(long_word_flag, *a, *c, *d);
+}
+
+static void fwdScale(int*a, int*b)
+{
+ *b -= (*a * 3 + 0) >> 4;
+ CHECK1(long_word_flag, *b);
+ *b -= *a >> 7;
+ CHECK1(long_word_flag, *b);
+ *b += *a >> 10;
+ *a -= (*b * 3 + 0) >> 3;
+ CHECK2(long_word_flag, *b, *a);
+ *b = (*a >> 1) - *b;
+ *a -= *b;
+ CHECK2(long_word_flag, *b, *a);
+}
+
+static void fwdRotate(int*a, int*b)
+{
+ *b -= (*a + 1) >> 1;
+ *a += (*b + 1) >> 1;
+ CHECK2(long_word_flag, *b, *a);
+}
+
+void _jxr_4x4PreFilter(int*a, int*b, int*c, int*d,
+ int*e, int*f, int*g, int*h,
+ int*i, int*j, int*k, int*l,
+ int*m, int*n, int*o, int*p)
+{
+ _2x2T_h_Enc(a, d, m, p);
+ _2x2T_h_Enc(b, c, n, o);
+ _2x2T_h_Enc(e, h, i, l);
+ _2x2T_h_Enc(f, g, j, k);
+
+ fwdScale(a, p);
+ fwdScale(b, o);
+ fwdScale(e, l);
+ fwdScale(f, k);
+
+ fwdRotate(n, m);
+ fwdRotate(j, i);
+ fwdRotate(h, d);
+ fwdRotate(g, c);
+ fwdT_Odd_Odd_PRE(k, l, o, p);
+
+ _2x2T_h(a, m, d, p, 0);
+ _2x2T_h(b, c, n, o, 0);
+ _2x2T_h(e, h, i, l, 0);
+ _2x2T_h(f, g, j, k, 0);
+}
+
+void _jxr_4PreFilter(int*a, int*b, int*c, int*d)
+{
+ *a += *d;
+ *b += *c;
+ *d -= ((*a + 1) >> 1);
+ *c -= ((*b + 1) >> 1);
+ CHECK4(long_word_flag, *a, *b, *d, *c);
+ fwdRotate(c, d);
+ *d *= -1;
+ *c *= -1;
+ *a -= *d;
+ *b -= *c;
+ CHECK4(long_word_flag, *d, *c, *a, *b);
+ *d += (*a >> 1);
+ *c += (*b >> 1);
+ *a -= ((*d * 3 + 4) >> 3);
+ *b -= ((*c * 3 + 4) >> 3);
+ CHECK4(long_word_flag, *d, *c, *a, *b);
+ fwdScale(a, d);
+ fwdScale(b, c);
+ *d += ((*a + 1) >> 1);
+ *c += ((*b + 1) >> 1);
+ *a -= *d;
+ *b -= *c;
+ CHECK4(long_word_flag, *d, *c, *a, *b);
+}
+
+void _jxr_2x2PreFilter(int*a, int*b, int*c, int*d)
+{
+ *a += *d;
+ *b += *c;
+ *d -= ((*a + 1) >> 1);
+ *c -= ((*b + 1) >> 1);
+ CHECK4(long_word_flag, *a, *b, *d, *c);
+ *b -= ((*a + 2) >> 2);
+ *a -= (*b >> 5);
+ CHECK2(long_word_flag, *b, *a);
+ *a -= (*b >> 9);
+ CHECK1(long_word_flag, *a);
+ *a -= (*b >> 13);
+ CHECK1(long_word_flag, *a);
+ *a -= ((*b + 1) >> 1);
+ *b -= ((*a + 2) >> 2);
+ *d += ((*a + 1) >> 1);
+ *c += ((*b + 1) >> 1);
+ CHECK4(long_word_flag, *a, *b, *d, *c);
+ *a -= *d;
+ *b -= *c;
+ CHECK2(long_word_flag, *a, *b);
+}
+
+void _jxr_2PreFilter(int*a, int*b)
+{
+ *b -= ((*a + 2) >> 2);
+ *a -= (*b >> 13);
+ CHECK2(long_word_flag, *b, *a);
+ *a -= (*b >> 9);
+ CHECK1(long_word_flag, *a);
+ *a -= (*b >> 5);
+ CHECK1(long_word_flag, *a);
+ *a -= ((*b + 1) >> 1);
+ *b -= ((*a + 2) >> 2);
+ CHECK2(long_word_flag, *a, *b);
+}
+
+uint8_t _jxr_read_lwf_test_flag()
+{
+ return long_word_flag;
+}
+
+/*
+* $Log: algo.c,v $
+*
+* Revision 1.58 2009/05/29 12:00:00 microsoft
+* Reference Software v1.6 updates.
+*
+* Revision 1.57 2009/05/29 12:00:00 microsoft
+* Reference Software v1.6 updates.
+*
+* Revision 1.56 2009/04/13 12:00:00 microsoft
+* Reference Software v1.5 updates.
+*
+* Revision 1.55 2008-05-13 13:47:11 thor
+* Some experiments with a smarter selection for the quantization size,
+* does not yet compile.
+*
+* Revision 1.54 2008-05-09 19:57:48 thor
+* Reformatted for unix LF.
+*
+* Revision 1.53 2008-04-15 14:28:12 thor
+* Start of the repository for the jpegxr reference software.
+*
+* Revision 1.52 2008/03/20 18:11:50 steve
+* Clarify MBLPMode calculations.
+*
+* Revision 1.51 2008/03/14 00:54:08 steve
+* Add second prefilter for YUV422 and YUV420 encode.
+*
+* Revision 1.50 2008/03/13 22:32:26 steve
+* Fix CBP prediction for YUV422, mode==0.
+*
+* Revision 1.49 2008/03/13 17:49:31 steve
+* Fix problem with YUV422 CBP prediction for UV planes
+*
+* Add support for YUV420 encoding.
+*
+* Revision 1.48 2008/03/13 00:07:22 steve
+* Encode HP of YUV422
+*
+* Revision 1.47 2008/03/12 21:10:27 steve
+* Encode LP of YUV422
+*
+* Revision 1.46 2008/03/11 22:12:48 steve
+* Encode YUV422 through DC.
+*
+* Revision 1.45 2008/02/26 23:52:44 steve
+* Remove ident for MS compilers.
+*
+* Revision 1.44 2008/02/22 23:01:33 steve
+* Compress macroblock HP CBP packets.
+*
+* Revision 1.43 2008/02/01 22:49:52 steve
+* Handle compress of YUV444 color DCONLY
+*
+* Revision 1.42 2008/01/08 23:23:32 steve
+* Minor math error in overlap code.
+*
+* Revision 1.41 2008/01/08 01:06:20 steve
+* Add first pass overlap filtering.
+*
+* Revision 1.40 2008/01/04 17:07:35 steve
+* API interface for setting QP values.
+*
+* Revision 1.39 2008/01/01 01:08:23 steve
+* Compile warning.
+*
+* Revision 1.38 2008/01/01 01:07:25 steve
+* Add missing HP prediction.
+*
+* Revision 1.37 2007/12/30 00:16:00 steve
+* Add encoding of HP values.
+*
+* Revision 1.36 2007/12/17 23:02:57 steve
+* Implement MB_CBP encoding.
+*
+* Revision 1.35 2007/12/14 17:10:39 steve
+* HP CBP Prediction
+*
+* Revision 1.34 2007/12/12 00:36:46 steve
+* Use T_odd instead of InvT_odd for PCT transform.
+*
+* Revision 1.33 2007/12/06 23:12:40 steve
+* Stubs for LP encode operations.
+*
+* Revision 1.32 2007/11/26 01:47:15 steve
+* Add copyright notices per MS request.
+*
+* Revision 1.31 2007/11/21 23:24:09 steve
+* Account for tiles selecting LP_QUANT for pred math.
+*
+* Revision 1.30 2007/11/16 20:03:57 steve
+* Store MB Quant, not qp_index.
+*
+* Revision 1.29 2007/11/13 03:27:23 steve
+* Add Frequency mode LP support.
+*
+* Revision 1.28 2007/10/30 21:32:46 steve
+* Support for multiple tile columns.
+*
+* Revision 1.27 2007/10/23 00:34:12 steve
+* Level1 filtering for YUV422 and YUV420
+*
+* Revision 1.26 2007/10/22 21:52:37 steve
+* Level2 filtering for YUV420
+*
+* Revision 1.25 2007/10/19 22:07:11 steve
+* Prediction of YUV420 chroma planes.
+*
+* Revision 1.24 2007/10/19 16:20:21 steve
+* Parse YUV420 HP
+*
+* Revision 1.23 2007/10/17 23:43:19 steve
+* Add support for YUV420
+*
+* Revision 1.22 2007/10/04 00:30:47 steve
+* Fix prediction of HP CBP for YUV422 data.
+*
+* Revision 1.21 2007/10/02 20:36:29 steve
+* Fix YUV42X DC prediction, add YUV42X HP parsing.
+*
+* Revision 1.20 2007/10/01 20:39:33 steve
+* Add support for YUV422 LP bands.
+*
+* Revision 1.19 2007/09/20 18:04:10 steve
+* support render of YUV422 images.
+*
+* Revision 1.18 2007/09/13 23:12:34 steve
+* Support color HP bands.
+*
+* Revision 1.17 2007/09/11 00:40:06 steve
+* Fix rendering of chroma to add the missing *2.
+* Fix handling of the chroma LP samples
+* Parse some of the HP CBP data in chroma.
+*
+* Revision 1.16 2007/09/08 01:01:43 steve
+* YUV444 color parses properly.
+*
+* Revision 1.15 2007/09/04 19:10:46 steve
+* Finish level1 overlap filtering.
+*
+* Revision 1.14 2007/08/31 23:31:49 steve
+* Initialize CBP VLC tables at the right time.
+*
+* Revision 1.13 2007/08/28 21:58:52 steve
+* Rewrite filtering to match rewritten 4.7
+*
+* Revision 1.12 2007/08/14 23:39:56 steve
+* Fix UpdateModelMB / Add filtering functions.
+*
+* Revision 1.11 2007/08/04 00:10:51 steve
+* Fix subtle loss of -1 values during DC prediction.
+*/
+
diff --git a/jpegxr/api.c b/jpegxr/api.c
new file mode 100644
index 000000000..37f14d5a4
--- /dev/null
+++ b/jpegxr/api.c
@@ -0,0 +1,1206 @@
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+***********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: api.c,v 1.18 2008/03/21 18:05:53 steve Exp $")
+#else
+#ident "$Id: api.c,v 1.18 2008/03/21 18:05:53 steve Exp $"
+#endif
+
+# include "jxr_priv.h"
+# include <assert.h>
+# include <stdlib.h>
+
+void _jxr_send_mb_to_output(jxr_image_t image, int mx, int my, int*data)
+{
+ if (image->out_fun)
+ image->out_fun(image, mx, my, data);
+}
+
+void jxr_set_block_output(jxr_image_t image, block_fun_t fun)
+{
+ image->out_fun = fun;
+}
+
+void _jxr_get_mb_from_input(jxr_image_t image, int mx, int my, int*data)
+{
+ if (image->inp_fun)
+ image->inp_fun(image, mx, my, data);
+}
+
+void jxr_set_block_input(jxr_image_t image, block_fun_t fun)
+{
+ image->inp_fun = fun;
+}
+
+void jxr_set_user_data(jxr_image_t image, void*data)
+{
+ image->user_data = data;
+}
+
+void* jxr_get_user_data(jxr_image_t image)
+{
+ return image->user_data;
+}
+
+int jxr_get_IMAGE_CHANNELS(jxr_image_t image)
+{
+ return image->num_channels;
+}
+
+void jxr_set_INTERNAL_CLR_FMT(jxr_image_t image, jxr_color_fmt_t fmt, int channels)
+{
+ switch (fmt) {
+ case JXR_YONLY:
+ image->use_clr_fmt = fmt;
+ image->num_channels = 1;
+ break;
+ case JXR_YUV420:
+ case JXR_YUV422:
+ case JXR_YUV444:
+ image->use_clr_fmt = fmt;
+ image->num_channels = 3;
+ break;
+ case JXR_YUVK:
+ image->use_clr_fmt = fmt;
+ image->num_channels = 4;
+ break;
+ case JXR_OCF_NCOMPONENT:
+ image->use_clr_fmt = fmt;
+ image->num_channels = channels;
+ break;
+ default:
+ image->use_clr_fmt = fmt;
+ image->num_channels = channels;
+ break;
+ }
+}
+
+void jxr_set_OUTPUT_CLR_FMT(jxr_image_t image, jxr_output_clr_fmt_t fmt)
+{
+ image->output_clr_fmt = fmt;
+
+ switch (fmt) {
+ case JXR_OCF_YONLY: /* YONLY */
+ image->header_flags_fmt |= 0x00; /* OUTPUT_CLR_FMT==0 */
+ break;
+ case JXR_OCF_YUV420: /* YUV420 */
+ image->header_flags_fmt |= 0x10; /* OUTPUT_CLR_FMT==1 */
+ break;
+ case JXR_OCF_YUV422: /* YUV422 */
+ image->header_flags_fmt |= 0x20; /* OUTPUT_CLR_FMT==2 */
+ break;
+ case JXR_OCF_YUV444: /* YUV444 */
+ image->header_flags_fmt |= 0x30; /* OUTPUT_CLR_FMT==3 */
+ break;
+ case JXR_OCF_CMYK: /* CMYK */
+ image->header_flags_fmt |= 0x40; /* OUTPUT_CLR_FMT=4 (CMYK) */
+ break;
+ case JXR_OCF_CMYKDIRECT: /* CMYKDIRECT */
+ image->header_flags_fmt |= 0x50; /* OUTPUT_CLR_FMT=5 (CMYKDIRECT) */
+ break;
+ case JXR_OCF_RGB: /* RGB color */
+ image->header_flags_fmt |= 0x70; /* OUTPUT_CLR_FMT=7 (RGB) */
+ break;
+ case JXR_OCF_RGBE: /* RGBE color */
+ image->header_flags_fmt |= 0x80; /* OUTPUT_CLR_FMT=8 (RGBE) */
+ break;
+ case JXR_OCF_NCOMPONENT: /* N-channel color */
+ image->header_flags_fmt |= 0x60; /* OUTPUT_CLR_FMT=6 (NCOMPONENT) */
+ break;
+ default:
+ fprintf(stderr, "Unsupported external color format (%d)! \n", fmt);
+ break;
+ }
+}
+
+jxr_output_clr_fmt_t jxr_get_OUTPUT_CLR_FMT(jxr_image_t image)
+{
+ return image->output_clr_fmt;
+}
+
+
+jxr_bitdepth_t jxr_get_OUTPUT_BITDEPTH(jxr_image_t image)
+{
+ return (jxr_bitdepth_t) SOURCE_BITDEPTH(image);
+}
+
+void jxr_set_OUTPUT_BITDEPTH(jxr_image_t image, jxr_bitdepth_t bd)
+{
+ image->header_flags_fmt &= ~0x0f;
+ image->header_flags_fmt |= bd;
+}
+
+void jxr_set_BANDS_PRESENT(jxr_image_t image, jxr_bands_present_t bp)
+{
+ image->bands_present = bp;
+ image->bands_present_of_primary = image->bands_present;
+}
+
+void jxr_set_FREQUENCY_MODE_CODESTREAM_FLAG(jxr_image_t image, int flag)
+{
+ assert(flag >= 0 && flag <= 1);
+ image->header_flags1 &= ~0x40;
+ image->header_flags1 |= (flag << 6);
+
+ /* Enable INDEX_TABLE_PRESENT_FLAG */
+ if (flag) {
+ jxr_set_INDEX_TABLE_PRESENT_FLAG(image, 1);
+ }
+}
+
+void jxr_set_INDEX_TABLE_PRESENT_FLAG(jxr_image_t image, int flag)
+{
+ assert(flag >= 0 && flag <= 1);
+ image->header_flags1 &= ~0x04;
+ image->header_flags1 |= (flag << 2);
+}
+
+void jxr_set_ALPHA_IMAGE_PLANE_FLAG(jxr_image_t image, int flag)
+{
+ assert(flag == 0 || flag == 1);
+ if(flag == 1)
+ image->header_flags2 |= 0x01;
+ else
+ image->header_flags2 &= 0xfe;
+}
+
+void jxr_set_PROFILE_IDC(jxr_image_t image, int profile_idc)
+{
+ assert(profile_idc >= 0 && profile_idc <= 255);
+ image->profile_idc = (uint8_t) profile_idc;
+}
+
+void jxr_set_LEVEL_IDC(jxr_image_t image, int level_idc)
+{
+ assert(level_idc >= 0 && level_idc <= 255);
+ image->level_idc = (uint8_t) level_idc;
+}
+
+void jxr_set_LONG_WORD_FLAG(jxr_image_t image, int flag)
+{
+ assert(flag >= 0 && flag <= 1);
+ image->header_flags2 &= ~0x40;
+ image->header_flags2 |= (flag << 6);
+}
+
+int jxr_test_PROFILE_IDC(jxr_image_t image, int flag)
+{
+ /*
+ ** flag = 0 - encoder
+ ** flag = 1 - decoder
+ */
+ jxr_bitdepth_t obd = jxr_get_OUTPUT_BITDEPTH(image);
+ jxr_output_clr_fmt_t ocf = jxr_get_OUTPUT_CLR_FMT(image);
+
+ unsigned char profile = image->profile_idc;
+ /*
+ * For forward compatability
+ * Though only specified profiles are currently applicable, decoder shouldn't reject other profiles.
+ */
+ if (flag) {
+ if (profile <= 44)
+ profile = 44;
+ else if (profile <= 55)
+ profile = 55;
+ else if (profile <= 66)
+ profile = 66;
+ else if (profile <= 111)
+ profile = 111;
+ }
+
+ switch (profile) {
+ case 44:
+ if (OVERLAP_INFO(image) == 2)
+ return JXR_EC_BADFORMAT;
+ if (LONG_WORD_FLAG(image))
+ return JXR_EC_BADFORMAT;
+ if (image->num_channels != 1 && image->num_channels != 3)
+ return JXR_EC_BADFORMAT;
+ if (image->alpha)
+ return JXR_EC_BADFORMAT;
+ if ((obd == JXR_BD16) || (obd == JXR_BD16S) || (obd == JXR_BD16F) || (obd == JXR_BD32S) || (obd == JXR_BD32F))
+ return JXR_EC_BADFORMAT;
+ if ((ocf != JXR_OCF_RGB) && (ocf != JXR_OCF_YONLY))
+ return JXR_EC_BADFORMAT;
+ break;
+ case 55:
+ if (image->num_channels != 1 && image->num_channels != 3)
+ return JXR_EC_BADFORMAT;
+ if (image->alpha)
+ return JXR_EC_BADFORMAT;
+ if ((obd == JXR_BD16F) || (obd == JXR_BD32S) || (obd == JXR_BD32F))
+ return JXR_EC_BADFORMAT;
+ if ((ocf != JXR_OCF_RGB) && (ocf != JXR_OCF_YONLY))
+ return JXR_EC_BADFORMAT;
+ break;
+ case 66:
+ if ((ocf == JXR_OCF_CMYKDIRECT) || (ocf == JXR_OCF_YUV420) || (ocf == JXR_OCF_YUV422) || (ocf == JXR_OCF_YUV444))
+ return JXR_EC_BADFORMAT;
+ break;
+ case 111:
+ break;
+ default:
+ return JXR_EC_BADFORMAT;
+ break;
+ }
+
+ return JXR_EC_OK;
+}
+
+int jxr_test_LEVEL_IDC(jxr_image_t image, int flag)
+{
+ /*
+ ** flag = 0 - encoder
+ ** flag = 1 - decoder
+ */
+ unsigned tr = image->tile_rows - 1;
+ unsigned tc = image->tile_columns - 1;
+ uint64_t h = (uint64_t) image->extended_height - 1;
+ uint64_t w = (uint64_t) image->extended_width - 1;
+ uint64_t n = (uint64_t) image->num_channels;
+ uint64_t buf_size = 1;
+
+ unsigned i;
+ uint64_t max_tile_width = 0, max_tile_height = 0;
+ unsigned char level;
+ for (i = 0; i < image->tile_columns; i++)
+ max_tile_width = (uint64_t) (image->tile_column_width[i] > max_tile_width ? image->tile_column_width[i] : max_tile_width);
+ for (i = 0; i < image->tile_rows; i++)
+ max_tile_height = (uint64_t) (image->tile_row_height[i] > max_tile_height ? image->tile_row_height[i] : max_tile_height);
+
+ if (image->alpha)
+ n += 1;
+
+ switch (SOURCE_BITDEPTH(image)) {
+ case 1: /* BD8 */
+ buf_size = n * (h + 1) * (w + 1);
+ break;
+ case 2: /* BD16 */
+ case 3: /* BD16S */
+ case 4: /* BD16F */
+ buf_size = 2 * n * (h + 1) * (w + 1);
+ break;
+ case 6: /* BD32S */
+ case 7: /* BD32F */
+ buf_size = 4 * n * (h + 1) * (w + 1);
+ break;
+ case 0: /* BD1WHITE1 */
+ case 15: /* BD1BLACK1 */
+ buf_size = ((h + 8) >> 3) * ((w + 8) >> 3) * 8;
+ break;
+ case 8: /* BD5 */
+ case 10: /* BD565 */
+ buf_size = 2 * (h + 1) * (w + 1);
+ break;
+ case 9: /* BD10 */
+ if (image->output_clr_fmt == JXR_OCF_RGB)
+ buf_size = 4 * (h + 1) * (w + 1);
+ else
+ buf_size = 2 * n * (h + 1) * (w + 1);
+ break;
+ default: /* RESERVED */
+ return JXR_EC_BADFORMAT;
+ break;
+ }
+
+ level = image->level_idc;
+ /*
+ * For forward compatability
+ * Though only specified levels are currently applicable, decoder shouldn't reject other levels.
+ */
+ if (flag) {
+ if (level >= 255)
+ level = 255;
+ else if (level >= 128)
+ level = 128;
+ else if (level >= 64)
+ level = 64;
+ else if (level >= 32)
+ level = 32;
+ else if (level >= 16)
+ level = 16;
+ else if (level >= 8)
+ level = 8;
+ else if (level >= 4)
+ level = 4;
+ }
+
+ switch (level) {
+ case 4:
+ if ((w >> 10) || (h >> 10) || (tc >> 4) || (tr >> 4) || (max_tile_width >> 10) || (max_tile_height >> 10) || (buf_size >> 22))
+ return JXR_EC_BADFORMAT;
+ break;
+ case 8:
+ if ((w >> 11) || (h >> 11) || (tc >> 5) || (tr >> 5) || (max_tile_width >> 11) || (max_tile_height >> 11) || (buf_size >> 24))
+ return JXR_EC_BADFORMAT;
+ break;
+ case 16:
+ if ((w >> 12) || (h >> 12) || (tc >> 6) || (tr >> 6) || (max_tile_width >> 12) || (max_tile_height >> 12) || (buf_size >> 26))
+ return JXR_EC_BADFORMAT;
+ break;
+ case 32:
+ if ((w >> 13) || (h >> 13) || (tc >> 7) || (tr >> 7) || (max_tile_width >> 12) || (max_tile_height >> 12) || (buf_size >> 28))
+ return JXR_EC_BADFORMAT;
+ break;
+ case 64:
+ if ((w >> 14) || (h >> 14) || (tc >> 8) || (tr >> 8) || (max_tile_width >> 12) || (max_tile_height >> 12) || (buf_size >> 30))
+ return JXR_EC_BADFORMAT;
+ break;
+ case 128:
+ if ((w >> 16) || (h >> 16) || (tc >> 10) || (tr >> 10) || (max_tile_width >> 12) || (max_tile_height >> 12) || (buf_size >> 32))
+ return JXR_EC_BADFORMAT;
+ break;
+ case 255: /* width and height restriction is 2^32 */
+ if ((w >> 32) || (h >> 32) || (tc >> 12) || (tr >> 12) || (max_tile_width >> 32) || (max_tile_height >> 32))
+ return JXR_EC_BADFORMAT;
+ break;
+ default:
+ return JXR_EC_BADFORMAT;
+ break;
+ }
+
+ return JXR_EC_OK;
+}
+
+void jxr_set_container_parameters(jxr_image_t image, jxrc_t_pixelFormat pixel_format, unsigned wid, unsigned hei, unsigned separate, unsigned char image_presence, unsigned char alpha_presence, unsigned char alpha) {
+ image->container_width = wid;
+ image->container_height = hei;
+ image->container_separate_alpha = separate ? 1 : 0;
+ image->container_image_band_presence = image_presence;
+ image->container_alpha_band_presence = alpha_presence;
+ image->container_current_separate_alpha = alpha ? 1 : 0;
+
+ switch (pixel_format) {
+ case JXRC_FMT_24bppRGB:
+ case JXRC_FMT_24bppBGR:
+ case JXRC_FMT_32bppBGR:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_RGB;
+ image->container_nc = 3;
+ break;
+ case JXRC_FMT_48bppRGB:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD16;
+ image->container_color = JXR_OCF_RGB;
+ image->container_nc = 3;
+ break;
+ case JXRC_FMT_48bppRGBFixedPoint:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD16S;
+ image->container_color = JXR_OCF_RGB;
+ image->container_nc = 3;
+ break;
+ case JXRC_FMT_48bppRGBHalf:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD16F;
+ image->container_color = JXR_OCF_RGB;
+ image->container_nc = 3;
+ break;
+ case JXRC_FMT_96bppRGBFixedPoint:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD32S;
+ image->container_color = JXR_OCF_RGB;
+ image->container_nc = 3;
+ break;
+ case JXRC_FMT_64bppRGBFixedPoint:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD16S;
+ image->container_color = JXR_OCF_RGB;
+ image->container_nc = 3;
+ break;
+ case JXRC_FMT_64bppRGBHalf:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD16F;
+ image->container_color = JXR_OCF_RGB;
+ image->container_nc = 3;
+ break;
+ case JXRC_FMT_128bppRGBFixedPoint:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD32S;
+ image->container_color = JXR_OCF_RGB;
+ image->container_nc = 3;
+ break;
+ case JXRC_FMT_128bppRGBFloat:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD32F;
+ image->container_color = JXR_OCF_RGB;
+ image->container_nc = 3;
+ break;
+ case JXRC_FMT_32bppBGRA:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_RGB;
+ image->container_nc = 4;
+ break;
+ case JXRC_FMT_64bppRGBA:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD16;
+ image->container_color = JXR_OCF_RGB;
+ image->container_nc = 4;
+ break;
+ case JXRC_FMT_64bppRGBAFixedPoint:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD16S;
+ image->container_color = JXR_OCF_RGB;
+ image->container_nc = 4;
+ break;
+ case JXRC_FMT_64bppRGBAHalf:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD16F;
+ image->container_color = JXR_OCF_RGB;
+ image->container_nc = 4;
+ break;
+ case JXRC_FMT_128bppRGBAFixedPoint:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD32S;
+ image->container_color = JXR_OCF_RGB;
+ image->container_nc = 4;
+ break;
+ case JXRC_FMT_128bppRGBAFloat:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD32F;
+ image->container_color = JXR_OCF_RGB;
+ image->container_nc = 4;
+ break;
+ case JXRC_FMT_32bppPBGRA:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_RGB;
+ image->container_nc = 4;
+ break;
+ case JXRC_FMT_64bppPRGBA:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD16;
+ image->container_color = JXR_OCF_RGB;
+ image->container_nc = 4;
+ break;
+ case JXRC_FMT_128bppPRGBAFloat:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD32F;
+ image->container_color = JXR_OCF_RGB;
+ image->container_nc = 4;
+ break;
+ case JXRC_FMT_32bppCMYK:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_CMYK;
+ image->container_nc = 4;
+ break;
+ case JXRC_FMT_40bppCMYKAlpha:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_CMYK;
+ image->container_nc = 5;
+ break;
+ case JXRC_FMT_64bppCMYK:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD16;
+ image->container_color = JXR_OCF_CMYK;
+ image->container_nc = 4;
+ break;
+ case JXRC_FMT_80bppCMYKAlpha:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD16;
+ image->container_color = JXR_OCF_CMYK;
+ image->container_nc = 5;
+ break;
+ case JXRC_FMT_24bpp3Channels:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_NCOMPONENT;
+ image->container_nc = 3;
+ break;
+ case JXRC_FMT_32bpp4Channels:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_NCOMPONENT;
+ image->container_nc = 4;
+ break;
+ case JXRC_FMT_40bpp5Channels:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_NCOMPONENT;
+ image->container_nc = 5;
+ break;
+ case JXRC_FMT_48bpp6Channels:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_NCOMPONENT;
+ image->container_nc = 6;
+ break;
+ case JXRC_FMT_56bpp7Channels:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_NCOMPONENT;
+ image->container_nc = 7;
+ break;
+ case JXRC_FMT_64bpp8Channels:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_NCOMPONENT;
+ image->container_nc = 8;
+ break;
+ case JXRC_FMT_32bpp3ChannelsAlpha:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_NCOMPONENT;
+ image->container_nc = 4;
+ break;
+ case JXRC_FMT_40bpp4ChannelsAlpha:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_NCOMPONENT;
+ image->container_nc = 5;
+ break;
+ case JXRC_FMT_48bpp5ChannelsAlpha:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_NCOMPONENT;
+ image->container_nc = 6;
+ break;
+ case JXRC_FMT_56bpp6ChannelsAlpha:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_NCOMPONENT;
+ image->container_nc = 7;
+ break;
+ case JXRC_FMT_64bpp7ChannelsAlpha:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_NCOMPONENT;
+ image->container_nc = 8;
+ break;
+ case JXRC_FMT_72bpp8ChannelsAlpha:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_NCOMPONENT;
+ image->container_nc = 9;
+ break;
+ case JXRC_FMT_48bpp3Channels:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD16;
+ image->container_color = JXR_OCF_NCOMPONENT;
+ image->container_nc = 3;
+ break;
+ case JXRC_FMT_64bpp4Channels:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD16;
+ image->container_color = JXR_OCF_NCOMPONENT;
+ image->container_nc = 4;
+ break;
+ case JXRC_FMT_80bpp5Channels:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD16;
+ image->container_color = JXR_OCF_NCOMPONENT;
+ image->container_nc = 5;
+ break;
+ case JXRC_FMT_96bpp6Channels:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD16;
+ image->container_color = JXR_OCF_NCOMPONENT;
+ image->container_nc = 6;
+ break;
+ case JXRC_FMT_112bpp7Channels:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD16;
+ image->container_color = JXR_OCF_NCOMPONENT;
+ image->container_nc = 7;
+ break;
+ case JXRC_FMT_128bpp8Channels:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD16;
+ image->container_color = JXR_OCF_NCOMPONENT;
+ image->container_nc = 8;
+ break;
+ case JXRC_FMT_64bpp3ChannelsAlpha:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD16;
+ image->container_color = JXR_OCF_NCOMPONENT;
+ image->container_nc = 4;
+ break;
+ case JXRC_FMT_80bpp4ChannelsAlpha:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD16;
+ image->container_color = JXR_OCF_NCOMPONENT;
+ image->container_nc = 5;
+ break;
+ case JXRC_FMT_96bpp5ChannelsAlpha:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD16;
+ image->container_color = JXR_OCF_NCOMPONENT;
+ image->container_nc = 6;
+ break;
+ case JXRC_FMT_112bpp6ChannelsAlpha:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD16;
+ image->container_color = JXR_OCF_NCOMPONENT;
+ image->container_nc = 7;
+ break;
+ case JXRC_FMT_128bpp7ChannelsAlpha:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD16;
+ image->container_color = JXR_OCF_NCOMPONENT;
+ image->container_nc = 8;
+ break;
+ case JXRC_FMT_144bpp8ChannelsAlpha:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD16;
+ image->container_color = JXR_OCF_NCOMPONENT;
+ image->container_nc = 9;
+ break;
+ case JXRC_FMT_8bppGray:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_YONLY;
+ image->container_nc = 1;
+ break;
+ case JXRC_FMT_16bppGray:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD16;
+ image->container_color = JXR_OCF_YONLY;
+ image->container_nc = 1;
+ break;
+ case JXRC_FMT_16bppGrayFixedPoint:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD16S;
+ image->container_color = JXR_OCF_YONLY;
+ image->container_nc = 1;
+ break;
+ case JXRC_FMT_16bppGrayHalf:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD16F;
+ image->container_color = JXR_OCF_YONLY;
+ image->container_nc = 1;
+ break;
+ case JXRC_FMT_32bppGrayFixedPoint:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD32S;
+ image->container_color = JXR_OCF_YONLY;
+ image->container_nc = 1;
+ break;
+ case JXRC_FMT_32bppGrayFloat:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD32F;
+ image->container_color = JXR_OCF_YONLY;
+ image->container_nc = 1;
+ break;
+ case JXRC_FMT_BlackWhite:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD1WHITE1; /* or JXR_BD1BLACK1 */
+ image->container_color = JXR_OCF_YONLY;
+ image->container_nc = 1;
+ break;
+ case JXRC_FMT_16bppBGR555:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD5;
+ image->container_color = JXR_OCF_RGB;
+ image->container_nc = 3;
+ break;
+ case JXRC_FMT_16bppBGR565:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD565;
+ image->container_color = JXR_OCF_RGB;
+ image->container_nc = 3;
+ break;
+ case JXRC_FMT_32bppBGR101010:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD10;
+ image->container_color = JXR_OCF_RGB;
+ image->container_nc = 3;
+ break;
+ case JXRC_FMT_32bppRGBE:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_RGBE;
+ image->container_nc = 3;
+ break;
+ case JXRC_FMT_32bppCMYKDIRECT:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_CMYKDIRECT;
+ image->container_nc = 4;
+ break;
+ case JXRC_FMT_64bppCMYKDIRECT:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD16;
+ image->container_color = JXR_OCF_CMYKDIRECT;
+ image->container_nc = 4;
+ break;
+ case JXRC_FMT_40bppCMYKDIRECTAlpha:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_CMYKDIRECT;
+ image->container_nc = 5;
+ break;
+ case JXRC_FMT_80bppCMYKDIRECTAlpha:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD16;
+ image->container_color = JXR_OCF_CMYKDIRECT;
+ image->container_nc = 5;
+ break;
+ case JXRC_FMT_12bppYCC420:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_YUV420;
+ image->container_nc = 3;
+ break;
+ case JXRC_FMT_16bppYCC422:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_YUV422;
+ image->container_nc = 3;
+ break;
+ case JXRC_FMT_20bppYCC422:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD10;
+ image->container_color = JXR_OCF_YUV422;
+ image->container_nc = 3;
+ break;
+ case JXRC_FMT_32bppYCC422:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD16;
+ image->container_color = JXR_OCF_YUV422;
+ image->container_nc = 3;
+ break;
+ case JXRC_FMT_24bppYCC444:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_YUV444;
+ image->container_nc = 3;
+ break;
+ case JXRC_FMT_30bppYCC444:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD10;
+ image->container_color = JXR_OCF_YUV444;
+ image->container_nc = 3;
+ break;
+ case JXRC_FMT_48bppYCC444:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD16;
+ image->container_color = JXR_OCF_YUV444;
+ image->container_nc = 3;
+ break;
+ case JXRC_FMT_48bppYCC444FixedPoint:
+ image->container_alpha = 0;
+ image->container_bpc = JXR_BD16S;
+ image->container_color = JXR_OCF_YUV444;
+ image->container_nc = 3;
+ break;
+ case JXRC_FMT_20bppYCC420Alpha:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_YUV420;
+ image->container_nc = 4;
+ break;
+ case JXRC_FMT_24bppYCC422Alpha:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_YUV422;
+ image->container_nc = 4;
+ break;
+ case JXRC_FMT_30bppYCC422Alpha:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD10;
+ image->container_color = JXR_OCF_YUV422;
+ image->container_nc = 4;
+ break;
+ case JXRC_FMT_48bppYCC422Alpha:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD16;
+ image->container_color = JXR_OCF_YUV422;
+ image->container_nc = 4;
+ break;
+ case JXRC_FMT_32bppYCC444Alpha:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD8;
+ image->container_color = JXR_OCF_YUV444;
+ image->container_nc = 4;
+ break;
+ case JXRC_FMT_40bppYCC444Alpha:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD10;
+ image->container_color = JXR_OCF_YUV444;
+ image->container_nc = 4;
+ break;
+ case JXRC_FMT_64bppYCC444Alpha:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD16;
+ image->container_color = JXR_OCF_YUV444;
+ image->container_nc = 4;
+ break;
+ case JXRC_FMT_64bppYCC444AlphaFixedPoint:
+ image->container_alpha = 1;
+ image->container_bpc = JXR_BD16S;
+ image->container_color = JXR_OCF_YUV444;
+ image->container_nc = 4;
+ break;
+ default:
+ /* all Guids listed above*/
+ assert(0);
+ break;
+ }
+}
+
+void jxr_set_NUM_VER_TILES_MINUS1(jxr_image_t image, unsigned num)
+{
+ assert( num > 0 && num < 4097 );
+ image->tile_columns = num;
+
+ if (num > 1)
+ jxr_set_TILING_FLAG(image, 1);
+}
+
+void jxr_set_TILE_WIDTH_IN_MB(jxr_image_t image, unsigned* list)
+{
+ unsigned idx, total_width = 0;
+
+ assert(list != 0);
+ image->tile_column_width = list;
+ image->tile_column_position = image->tile_column_width + image->tile_columns;
+
+ if (image->tile_column_width[0] == 0) {
+ total_width = 0;
+ for ( idx = 0 ; idx < image->tile_columns - 1 ; idx++ ) {
+ image->tile_column_width[idx] = (image->extended_width >> 4) / image->tile_columns;
+ image->tile_column_position[idx] = total_width;
+ total_width += image->tile_column_width[idx];
+ }
+ image->tile_column_width[image->tile_columns - 1] = (image->extended_width >> 4) - total_width;
+ image->tile_column_position[image->tile_columns - 1] = total_width;
+ }
+}
+
+void jxr_set_NUM_HOR_TILES_MINUS1(jxr_image_t image, unsigned num)
+{
+ assert( num > 0 && num < 4097 );
+ image->tile_rows = num;
+
+ if (num > 1)
+ jxr_set_TILING_FLAG(image, 1);
+}
+
+void jxr_set_TILE_HEIGHT_IN_MB(jxr_image_t image, unsigned* list)
+{
+ unsigned idx, total_height = 0;
+
+ assert(list != 0);
+ image->tile_row_height = list;
+ image->tile_row_position = image->tile_row_height + image->tile_rows;
+
+ if (image->tile_row_height[0] == 0) {
+ total_height = 0;
+ for ( idx = 0 ; idx < image->tile_rows - 1 ; idx++ ) {
+ image->tile_row_height[idx] = (image->extended_height >> 4) / image->tile_rows;
+ image->tile_row_position[idx] = total_height;
+ total_height += image->tile_row_height[idx];
+ }
+ image->tile_row_height[image->tile_rows - 1] = (image->extended_height >> 4) - total_height;
+ image->tile_row_position[image->tile_rows - 1] = total_height;
+ }
+}
+
+void jxr_set_TILING_FLAG(jxr_image_t image, int flag)
+{
+ assert(flag >= 0 && flag <= 1);
+ image->header_flags1 &= ~0x80;
+ image->header_flags1 |= (flag << 7);
+
+ /* Enable INDEX_TABLE_PRESENT_FLAG */
+ if (flag) {
+ jxr_set_INDEX_TABLE_PRESENT_FLAG(image, 1);
+ }
+}
+
+void jxr_set_TRIM_FLEXBITS(jxr_image_t image, int trim_flexbits)
+{
+ assert(trim_flexbits >= 0 && trim_flexbits < 16);
+ image->trim_flexbits = trim_flexbits;
+}
+
+void jxr_set_OVERLAP_FILTER(jxr_image_t image, int flag)
+{
+ assert(flag >= 0 && flag <= 3);
+ image->header_flags1 &= ~0x03;
+ image->header_flags1 |= flag&0x03;
+}
+
+void jxr_set_DISABLE_TILE_OVERLAP(jxr_image_t image, int disable_tile_overlap)
+{
+ image->disableTileOverlapFlag = disable_tile_overlap;
+}
+
+void jxr_set_QP_LOSSLESS(jxr_image_t image)
+{
+ unsigned char q[MAX_CHANNELS];
+ int idx;
+ for (idx = 0 ; idx < MAX_CHANNELS ; idx += 1)
+ q[idx] = 0;
+
+ jxr_set_QP_INDEPENDENT(image, q);
+
+ if (image->num_channels == 1) {
+ image->dc_component_mode = JXR_CM_UNIFORM;
+ image->lp_component_mode = JXR_CM_UNIFORM;
+ image->hp_component_mode = JXR_CM_UNIFORM;
+ } else if (image->num_channels == 3) {
+ image->dc_component_mode = JXR_CM_SEPARATE;
+ image->lp_component_mode = JXR_CM_SEPARATE;
+ image->hp_component_mode = JXR_CM_SEPARATE;
+ }
+}
+
+void jxr_set_QP_INDEPENDENT(jxr_image_t image, unsigned char*quant_per_channel)
+{
+ /*
+ * SCALED_FLAG MUST be set false if lossless compressing.
+ * SCALED_FLAG SHOULD be true otherwise.
+ *
+ * So assume that we are setting up for lossless compression
+ * until we find a QP flag that indicates otherwlse. If that
+ * happens, turn SCALED_FLAG on.
+ */
+ int idx;
+
+ image->scaled_flag = 0;
+
+ if (image->bands_present != JXR_BP_ALL)
+ image->scaled_flag = 1;
+
+ if (image->num_channels == 1) {
+ image->dc_component_mode = JXR_CM_UNIFORM;
+ image->lp_component_mode = JXR_CM_UNIFORM;
+ image->hp_component_mode = JXR_CM_UNIFORM;
+ } else {
+ image->dc_component_mode = JXR_CM_INDEPENDENT;
+ image->lp_component_mode = JXR_CM_INDEPENDENT;
+ image->hp_component_mode = JXR_CM_INDEPENDENT;
+ }
+
+ image->dc_frame_uniform = 1;
+ image->lp_frame_uniform = 1;
+ image->hp_frame_uniform = 1;
+ image->lp_use_dc_qp = 0;
+ image->hp_use_lp_qp = 0;
+
+ image->num_lp_qps = 1;
+ image->num_hp_qps = 1;
+
+ for (idx = 0 ; idx < image->num_channels ; idx += 1) {
+ if (quant_per_channel[idx] >= 1)
+ image->scaled_flag = 1;
+
+ image->dc_quant_ch[idx] = quant_per_channel[idx];
+ image->lp_quant_ch[idx][0] = quant_per_channel[idx];
+ image->hp_quant_ch[idx][0] = quant_per_channel[idx];
+ }
+}
+
+void jxr_set_QP_UNIFORM(jxr_image_t image, unsigned char quant)
+{
+ int idx;
+
+ image->scaled_flag = 0;
+
+ image->dc_component_mode = JXR_CM_UNIFORM;
+ image->lp_component_mode = JXR_CM_UNIFORM;
+ image->hp_component_mode = JXR_CM_UNIFORM;
+
+ image->dc_frame_uniform = 1;
+ image->lp_frame_uniform = 1;
+ image->hp_frame_uniform = 1;
+ image->lp_use_dc_qp = 0;
+ image->hp_use_lp_qp = 0;
+
+ image->num_lp_qps = 1;
+ image->num_hp_qps = 1;
+
+ if (quant >= 1)
+ image->scaled_flag = 1;
+ if (image->bands_present != JXR_BP_ALL)
+ image->scaled_flag = 1;
+
+ for (idx = 0 ; idx < image->num_channels ; idx += 1) {
+ image->dc_quant_ch[idx] = quant;
+ image->lp_quant_ch[idx][0] = quant;
+ image->hp_quant_ch[idx][0] = quant;
+ }
+}
+
+void jxr_set_QP_SEPARATE(jxr_image_t image, unsigned char*quant_per_channel)
+{
+ /*
+ * SCALED_FLAG MUST be set false if lossless compressing.
+ * SCALED_FLAG SHOULD be true otherwise.
+ *
+ * So assume that we are setting up for lossless compression
+ * until we find a QP flag that indicates otherwlse. If that
+ * happens, turn SCALED_FLAG on.
+ */
+ int ch;
+
+ image->scaled_flag = 0;
+
+ if (image->bands_present != JXR_BP_ALL)
+ image->scaled_flag = 1;
+
+ /* XXXX Only thought out how to handle 1 channel. */
+ assert(image->num_channels >= 3);
+
+ image->dc_component_mode = JXR_CM_SEPARATE;
+ image->lp_component_mode = JXR_CM_SEPARATE;
+ image->hp_component_mode = JXR_CM_SEPARATE;
+
+ image->dc_frame_uniform = 1;
+ image->lp_frame_uniform = 1;
+ image->hp_frame_uniform = 1;
+ image->lp_use_dc_qp = 0;
+ image->hp_use_lp_qp = 0;
+
+ if (quant_per_channel[0] >= 1)
+ image->scaled_flag = 1;
+
+ image->dc_quant_ch[0] = quant_per_channel[0];
+ image->lp_quant_ch[0][0] = quant_per_channel[0];
+ image->hp_quant_ch[0][0] = quant_per_channel[0];
+
+ if (quant_per_channel[1] >= 1)
+ image->scaled_flag = 1;
+
+ for (ch = 1 ; ch < image->num_channels ; ch += 1) {
+ image->dc_quant_ch[ch] = quant_per_channel[1];
+ image->lp_quant_ch[ch][0] = quant_per_channel[1];
+ image->hp_quant_ch[ch][0] = quant_per_channel[1];
+ }
+}
+
+void jxr_set_QP_DISTRIBUTED(jxr_image_t image, struct jxr_tile_qp*qp)
+{
+ image->dc_frame_uniform = 0;
+ image->lp_frame_uniform = 0;
+ image->hp_frame_uniform = 0;
+ image->lp_use_dc_qp = 0;
+ image->hp_use_lp_qp = 0;
+
+ image->tile_quant = qp;
+}
+
+void jxr_set_pixel_format(jxr_image_t image, jxrc_t_pixelFormat pixelFormat)
+{
+ image->ePixelFormat = pixelFormat;
+}
+
+void jxr_set_SHIFT_BITS(jxr_image_t image, unsigned char shift_bits)
+{
+ image->shift_bits = shift_bits;
+}
+
+void jxr_set_FLOAT(jxr_image_t image, unsigned char len_mantissa, char exp_bias)
+{
+ image->len_mantissa = len_mantissa;
+ image->exp_bias = exp_bias;
+}
+
+/*
+* $Log: api.c,v $
+* Revision 1.20 2009/05/29 12:00:00 microsoft
+* Reference Software v1.6 updates.
+*
+* Revision 1.19 2009/04/13 12:00:00 microsoft
+* Reference Software v1.5 updates.
+*
+* Revision 1.18 2008/03/21 18:05:53 steve
+* Proper CMYK formatting on input.
+*
+* Revision 1.17 2008/03/06 02:05:48 steve
+* Distributed quantization
+*
+* Revision 1.16 2008/03/05 04:04:30 steve
+* Clarify constraints on USE_DC_QP in image plane header.
+*
+* Revision 1.15 2008/03/05 01:27:15 steve
+* QP_UNIFORM may use USE_DC_LP optionally.
+*
+* Revision 1.14 2008/03/05 00:31:17 steve
+* Handle UNIFORM/IMAGEPLANE_UNIFORM compression.
+*
+* Revision 1.13 2008/03/04 23:01:28 steve
+* Cleanup QP API in preparation for distributed QP
+*
+* Revision 1.12 2008/03/02 19:56:27 steve
+* Infrastructure to read write BD16 files.
+*
+* Revision 1.11 2008/02/26 23:52:44 steve
+* Remove ident for MS compilers.
+*
+* Revision 1.10 2008/02/01 22:49:52 steve
+* Handle compress of YUV444 color DCONLY
+*
+* Revision 1.9 2008/01/08 01:06:20 steve
+* Add first pass overlap filtering.
+*
+* Revision 1.8 2008/01/07 16:19:10 steve
+* Properly configure TRIM_FLEXBITS_FLAG bit.
+*
+* Revision 1.7 2008/01/06 01:29:28 steve
+* Add support for TRIM_FLEXBITS in compression.
+*
+* Revision 1.6 2008/01/04 17:07:35 steve
+* API interface for setting QP values.
+*
+* Revision 1.5 2007/11/30 01:50:58 steve
+* Compression of DCONLY GRAY.
+*
+* Revision 1.4 2007/11/26 01:47:15 steve
+* Add copyright notices per MS request.
+*
+* Revision 1.3 2007/11/08 02:52:32 steve
+* Some progress in some encoding infrastructure.
+*
+* Revision 1.2 2007/09/08 01:01:43 steve
+* YUV444 color parses properly.
+*
+* Revision 1.1 2007/06/06 17:19:12 steve
+* Introduce to CVS.
+*
+*/
+
diff --git a/jpegxr/app_resource.h b/jpegxr/app_resource.h
new file mode 100644
index 000000000..eac8ab69b
--- /dev/null
+++ b/jpegxr/app_resource.h
@@ -0,0 +1,14 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by APP.rc
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/jpegxr/cr_parse.c b/jpegxr/cr_parse.c
new file mode 100644
index 000000000..563303a52
--- /dev/null
+++ b/jpegxr/cr_parse.c
@@ -0,0 +1,1423 @@
+
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+***********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: cr_parse.c,v 1.9 2008/03/21 21:23:14 steve Exp $")
+#else
+#ident "$Id: cr_parse.c,v 1.9 2008/03/21 21:23:14 steve Exp $"
+#endif
+
+# include "jxr_priv.h"
+# include <string.h>
+# include <stdlib.h>
+# include <assert.h>
+
+static int read_ifd(jxr_container_t container, FILE*fd, int image_number, uint32_t*ifd_next);
+
+jxr_container_t jxr_create_container(void)
+{
+ jxr_container_t res = (jxr_container_t)
+ calloc(1, sizeof (struct jxr_container));
+ return res;
+}
+
+void jxr_destroy_container(jxr_container_t container)
+{
+ if(container == NULL)
+ return;
+ free(container);
+}
+
+int jxr_read_image_container(jxr_container_t container, FILE*fd)
+{
+ unsigned char buf[4];
+ size_t rc;
+ uint32_t ifd_off;
+
+ rc = fread(buf, 1, 4, fd);
+ if (rc < 4)
+ return JXR_EC_BADMAGIC;
+
+ if (buf[0] != 0x49) return JXR_EC_BADMAGIC;
+ if (buf[1] != 0x49) return JXR_EC_BADMAGIC;
+ if (buf[2] != 0xbc) return JXR_EC_BADMAGIC;
+ if (buf[3] > 0x01) return JXR_EC_BADMAGIC; /* Version. */
+
+ rc = fread(buf, 1, 4, fd);
+ if (rc != 4) return JXR_EC_IO;
+
+ ifd_off = (buf[3] << 24) + (buf[2]<<16) + (buf[1]<<8) + (buf[0]<<0);
+ container->image_count = 0;
+
+ while (ifd_off != 0) {
+ uint32_t ifd_next;
+
+ container->image_count += 1;
+ container->table_cnt = (unsigned*)realloc(container->table_cnt,
+ container->image_count * sizeof(unsigned));
+ container->table = (struct ifd_table**) realloc(container->table,
+ container->image_count * sizeof(struct ifd_table*));
+
+ if (ifd_off & 0x1) return JXR_EC_IO;
+ rc = fseek(fd, ifd_off, SEEK_SET);
+ rc = read_ifd(container, fd, container->image_count-1, &ifd_next);
+ if (rc < 0) return (int) rc;
+
+ ifd_off = ifd_next;
+ }
+
+ return 0;
+}
+
+int jxrc_image_count(jxr_container_t container)
+{
+ return container->image_count;
+}
+
+int jxrc_document_name(jxr_container_t container, int image, char ** string)
+{
+
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0x010d)
+ break;
+ }
+
+ if (idx >= ifd_cnt) return -1;
+ if (ifd[idx].tag != 0x010d) return -1;
+ assert(ifd[idx].type == 2);
+
+ assert(string[0] == 0);
+ string[0] = (char *) malloc(ifd[idx].cnt * sizeof(char));
+ assert(string[0] != 0);
+
+ if (ifd[idx].cnt <= 4) {
+ unsigned i;
+ for (i = 0 ; i < ifd[idx].cnt ; i++)
+ string[0][i] = ifd[idx].value_.v_sbyte[i];
+ }
+ else {
+ unsigned i;
+ for (i = 0 ; i < ifd[idx].cnt ; i++)
+ string[0][i] = ifd[idx].value_.p_sbyte[i];
+ }
+
+ return 0;
+}
+
+int jxrc_image_description(jxr_container_t container, int image, char ** string)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0x010e)
+ break;
+ }
+
+ if (idx >= ifd_cnt) return -1;
+ if (ifd[idx].tag != 0x010e) return -1;
+ assert(ifd[idx].type == 2);
+
+ assert(string[0] == 0);
+ string[0] = (char *) malloc(ifd[idx].cnt * sizeof(char));
+ assert(string[0] != 0);
+
+ if (ifd[idx].cnt <= 4) {
+ unsigned i;
+ for (i = 0 ; i < ifd[idx].cnt ; i++)
+ string[0][i] = ifd[idx].value_.v_sbyte[i];
+ }
+ else {
+ unsigned i;
+ for (i = 0 ; i < ifd[idx].cnt ; i++)
+ string[0][i] = ifd[idx].value_.p_sbyte[i];
+ }
+
+ return 0;
+}
+
+int jxrc_equipment_make(jxr_container_t container, int image, char ** string)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0x010f)
+ break;
+ }
+
+ if (idx >= ifd_cnt) return -1;
+ if (ifd[idx].tag != 0x010f) return -1;
+ assert(ifd[idx].type == 2);
+
+ assert(string[0] == 0);
+ string[0] = (char *) malloc(ifd[idx].cnt * sizeof(char));
+ assert(string[0] != 0);
+
+ if (ifd[idx].cnt <= 4) {
+ unsigned i;
+ for (i = 0 ; i < ifd[idx].cnt ; i++)
+ string[0][i] = ifd[idx].value_.v_sbyte[i];
+ }
+ else {
+ unsigned i;
+ for (i = 0 ; i < ifd[idx].cnt ; i++)
+ string[0][i] = ifd[idx].value_.p_sbyte[i];
+ }
+
+ return 0;
+}
+
+int jxrc_equipment_model(jxr_container_t container, int image, char ** string)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0x0110)
+ break;
+ }
+
+ if (idx >= ifd_cnt) return -1;
+ if (ifd[idx].tag != 0x0110) return -1;
+ assert(ifd[idx].type == 2);
+
+ assert(string[0] == 0);
+ string[0] = (char *) malloc(ifd[idx].cnt * sizeof(char));
+ assert(string[0] != 0);
+
+ if (ifd[idx].cnt <= 4) {
+ unsigned i;
+ for (i = 0 ; i < ifd[idx].cnt ; i++)
+ string[0][i] = ifd[idx].value_.v_sbyte[i];
+ }
+ else {
+ unsigned i;
+ for (i = 0 ; i < ifd[idx].cnt ; i++)
+ string[0][i] = ifd[idx].value_.p_sbyte[i];
+ }
+
+ return 0;
+}
+
+int jxrc_page_name(jxr_container_t container, int image, char ** string)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0x011d)
+ break;
+ }
+
+ if (idx >= ifd_cnt) return -1;
+ if (ifd[idx].tag != 0x011d) return -1;
+ assert(ifd[idx].type == 2);
+
+ assert(string[0] == 0);
+ string[0] = (char *) malloc(ifd[idx].cnt * sizeof(char));
+ assert(string[0] != 0);
+
+ if (ifd[idx].cnt <= 4) {
+ unsigned i;
+ for (i = 0 ; i < ifd[idx].cnt ; i++)
+ string[0][i] = ifd[idx].value_.v_sbyte[i];
+ }
+ else {
+ unsigned i;
+ for (i = 0 ; i < ifd[idx].cnt ; i++)
+ string[0][i] = ifd[idx].value_.p_sbyte[i];
+ }
+
+ return 0;
+}
+
+int jxrc_page_number(jxr_container_t container, int image, unsigned short * value)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0x0129)
+ break;
+ }
+
+ if (idx >= ifd_cnt) return -1;
+ if (ifd[idx].tag != 0x0129) return -1;
+ assert(ifd[idx].cnt == 2);
+ assert(ifd[idx].type == 3);
+
+ value[0] = ifd[idx].value_.v_short[0];
+ value[1] = ifd[idx].value_.v_short[1];
+
+ return 0;
+}
+
+int jxrc_software_name_version(jxr_container_t container, int image, char ** string)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0x0131)
+ break;
+ }
+
+ if (idx >= ifd_cnt) return -1;
+ if (ifd[idx].tag != 0x0131) return -1;
+ assert(ifd[idx].type == 2);
+
+ assert(string[0] == 0);
+ string[0] = (char *) malloc(ifd[idx].cnt * sizeof(char));
+ assert(string[0] != 0);
+
+ if (ifd[idx].cnt <= 4) {
+ unsigned i;
+ for (i = 0 ; i < ifd[idx].cnt ; i++)
+ string[0][i] = ifd[idx].value_.v_sbyte[i];
+ }
+ else {
+ unsigned i;
+ for (i = 0 ; i < ifd[idx].cnt ; i++)
+ string[0][i] = ifd[idx].value_.p_sbyte[i];
+ }
+
+ return 0;
+}
+
+int jxrc_date_time(jxr_container_t container, int image, char ** string)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+ unsigned i;
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0x0132)
+ break;
+ }
+
+ if (idx >= ifd_cnt) return -1;
+ if (ifd[idx].tag != 0x0132) return -1;
+ assert(ifd[idx].type == 2);
+
+ assert(string[0] == 0);
+ string[0] = (char *) malloc(ifd[idx].cnt * sizeof(char));
+ assert(string[0] != 0);
+ assert(ifd[idx].cnt == 20);
+
+ for (i = 0 ; i < ifd[idx].cnt ; i++)
+ string[0][i] = ifd[idx].value_.p_sbyte[i];
+
+ assert(string[0][4] == 0x3a && string[0][7] == 0x3a && string[0][13] == 0x3a && string[0][16] == 0x3a);
+ assert(string[0][10] == 0x20);
+ assert((string[0][5] == '0' && (string[0][6] >= '1' && string[0][6] <= '9')) || (string[0][5] == '1' && (string[0][6] >= '0' && string[0][6] <= '2')));
+ assert((string[0][8] == '0' && (string[0][9] >= '1' && string[0][9] <= '9')) || ((string[0][8] == '1' || string[0][8] == '2') && (string[0][9] >= '0' && string[0][9] <= '9')) || (string[0][8] == '3' && (string[0][9] >= '0' && string[0][9] <= '1')));
+ assert(((string[0][11] == '0' || string[0][11] == '1') && (string[0][12] >= '0' && string[0][12] <= '9')) || (string[0][11] == '2' && (string[0][12] >= '0' && string[0][12] <= '3')));
+ assert(string[0][14] >= '0' && string[0][14] < '6');
+ assert(string[0][15] >= '0' && string[0][15] <= '9');
+ assert(string[0][17] >= '0' && string[0][17] < '6');
+ assert(string[0][18] >= '0' && string[0][18] <= '9');
+
+ return 0;
+}
+
+int jxrc_artist_name(jxr_container_t container, int image, char ** string)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0x013b)
+ break;
+ }
+
+ if (idx >= ifd_cnt) return -1;
+ if (ifd[idx].tag != 0x013b) return -1;
+ assert(ifd[idx].type == 2);
+
+ assert(string[0] == 0);
+ string[0] = (char *) malloc(ifd[idx].cnt * sizeof(char));
+ assert(string[0] != 0);
+
+ if (ifd[idx].cnt <= 4) {
+ unsigned i;
+ for (i = 0 ; i < ifd[idx].cnt ; i++)
+ string[0][i] = ifd[idx].value_.v_sbyte[i];
+ }
+ else {
+ unsigned i;
+ for (i = 0 ; i < ifd[idx].cnt ; i++)
+ string[0][i] = ifd[idx].value_.p_sbyte[i];
+ }
+
+ return 0;
+}
+
+int jxrc_host_computer(jxr_container_t container, int image, char ** string)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0x013c)
+ break;
+ }
+
+ if (idx >= ifd_cnt) return -1;
+ if (ifd[idx].tag != 0x013c) return -1;
+ assert(ifd[idx].type == 2);
+
+ assert(string[0] == 0);
+ string[0] = (char *) malloc(ifd[idx].cnt * sizeof(char));
+ assert(string[0] != 0);
+
+ if (ifd[idx].cnt <= 4) {
+ unsigned i;
+ for (i = 0 ; i < ifd[idx].cnt ; i++)
+ string[0][i] = ifd[idx].value_.v_sbyte[i];
+ }
+ else {
+ unsigned i;
+ for (i = 0 ; i < ifd[idx].cnt ; i++)
+ string[0][i] = ifd[idx].value_.p_sbyte[i];
+ }
+
+ return 0;
+}
+
+int jxrc_copyright_notice(jxr_container_t container, int image, char ** string)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0x8298)
+ break;
+ }
+
+ if (idx >= ifd_cnt) return -1;
+ if (ifd[idx].tag != 0x8298) return -1;
+ assert(ifd[idx].type == 2);
+
+ assert(string[0] == 0);
+ string[0] = (char *) malloc(ifd[idx].cnt * sizeof(char));
+ assert(string[0] != 0);
+
+ if (ifd[idx].cnt <= 4) {
+ unsigned i;
+ for (i = 0 ; i < ifd[idx].cnt ; i++)
+ string[0][i] = ifd[idx].value_.v_sbyte[i];
+ }
+ else {
+ unsigned i;
+ for (i = 0 ; i < ifd[idx].cnt ; i++)
+ string[0][i] = ifd[idx].value_.p_sbyte[i];
+ }
+
+ return 0;
+}
+
+unsigned short jxrc_color_space(jxr_container_t container, int image)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+ unsigned short value;
+
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0xa001)
+ break;
+ }
+
+ if (idx >= ifd_cnt) return 0;
+ if (ifd[idx].tag != 0xa001) return 0;
+ assert(ifd[idx].cnt == 1);
+ assert(ifd[idx].type == 3);
+
+ value = ifd[idx].value_.v_short[0];
+ if (value != 0x0001)
+ value = 0xffff;
+ if (value == 0x0001) {
+ switch(jxrc_image_pixelformat(container, image)) {
+ case JXRC_FMT_24bppRGB:
+ case JXRC_FMT_24bppBGR:
+ case JXRC_FMT_32bppBGR:
+ case JXRC_FMT_48bppRGB:
+ case JXRC_FMT_32bppBGRA:
+ case JXRC_FMT_64bppRGBA:
+ case JXRC_FMT_32bppPBGRA:
+ case JXRC_FMT_64bppPRGBA:
+ case JXRC_FMT_32bppCMYK:
+ case JXRC_FMT_40bppCMYKAlpha:
+ case JXRC_FMT_64bppCMYK:
+ case JXRC_FMT_80bppCMYKAlpha:
+ case JXRC_FMT_24bpp3Channels:
+ case JXRC_FMT_32bpp4Channels:
+ case JXRC_FMT_40bpp5Channels:
+ case JXRC_FMT_48bpp6Channels:
+ case JXRC_FMT_56bpp7Channels:
+ case JXRC_FMT_64bpp8Channels:
+ case JXRC_FMT_32bpp3ChannelsAlpha:
+ case JXRC_FMT_40bpp4ChannelsAlpha:
+ case JXRC_FMT_48bpp5ChannelsAlpha:
+ case JXRC_FMT_56bpp6ChannelsAlpha:
+ case JXRC_FMT_64bpp7ChannelsAlpha:
+ case JXRC_FMT_72bpp8ChannelsAlpha:
+ case JXRC_FMT_48bpp3Channels:
+ case JXRC_FMT_64bpp4Channels:
+ case JXRC_FMT_80bpp5Channels:
+ case JXRC_FMT_96bpp6Channels:
+ case JXRC_FMT_112bpp7Channels:
+ case JXRC_FMT_128bpp8Channels:
+ case JXRC_FMT_64bpp3ChannelsAlpha:
+ case JXRC_FMT_80bpp4ChannelsAlpha:
+ case JXRC_FMT_96bpp5ChannelsAlpha:
+ case JXRC_FMT_112bpp6ChannelsAlpha:
+ case JXRC_FMT_128bpp7ChannelsAlpha:
+ case JXRC_FMT_144bpp8ChannelsAlpha:
+ case JXRC_FMT_8bppGray:
+ case JXRC_FMT_16bppGray:
+ case JXRC_FMT_BlackWhite:
+ case JXRC_FMT_16bppBGR555:
+ case JXRC_FMT_16bppBGR565:
+ case JXRC_FMT_32bppBGR101010:
+ case JXRC_FMT_32bppCMYKDIRECT:
+ case JXRC_FMT_64bppCMYKDIRECT:
+ case JXRC_FMT_40bppCMYKDIRECTAlpha:
+ case JXRC_FMT_80bppCMYKDIRECTAlpha:
+ case JXRC_FMT_12bppYCC420:
+ case JXRC_FMT_16bppYCC422:
+ case JXRC_FMT_20bppYCC422:
+ case JXRC_FMT_32bppYCC422:
+ case JXRC_FMT_24bppYCC444:
+ case JXRC_FMT_30bppYCC444:
+ case JXRC_FMT_48bppYCC444:
+ case JXRC_FMT_20bppYCC420Alpha:
+ case JXRC_FMT_24bppYCC422Alpha:
+ case JXRC_FMT_30bppYCC422Alpha:
+ case JXRC_FMT_48bppYCC422Alpha:
+ case JXRC_FMT_32bppYCC444Alpha:
+ case JXRC_FMT_40bppYCC444Alpha:
+ case JXRC_FMT_64bppYCC444Alpha:
+ break;
+ default:
+ /* Color space tag can equal 1 only if format is UINT */
+ assert(0);
+ break;
+ }
+ }
+ return value;
+}
+
+jxrc_t_pixelFormat jxrc_image_pixelformat(jxr_container_t container, int imagenum)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+
+ unsigned char guid[16];
+ int i;
+ assert(imagenum < container->image_count);
+
+ ifd_cnt = container->table_cnt[imagenum];
+ ifd = container->table[imagenum];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0xbc01)
+ break;
+ }
+
+ assert(idx < ifd_cnt);
+ assert(ifd[idx].tag == 0xbc01);
+ assert(ifd[idx].cnt == 16);
+ memcpy(guid, ifd[idx].value_.p_byte, 16);
+ for(i=0; i< NUM_GUIDS; i++)
+ {
+ if(isEqualGUID(guid, jxr_guids[i]))
+ {
+ break;
+ }
+ }
+ if(i==NUM_GUIDS)
+ assert(0);
+ return (jxrc_t_pixelFormat)i;
+
+}
+
+unsigned long jxrc_spatial_xfrm_primary(jxr_container_t container, int image)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+ unsigned long spatial_xfrm;
+
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0xbc02)
+ break;
+ }
+
+ if (idx >= ifd_cnt) return 0;
+ if (ifd[idx].tag != 0xbc02) return 0;
+ assert(ifd[idx].cnt == 1);
+
+ switch (ifd[idx].type) {
+ case 4: /* ULONG */
+ spatial_xfrm = (unsigned long) ifd[idx].value_.v_long;
+ break;
+ case 3: /* USHORT */
+ spatial_xfrm = (unsigned long) ifd[idx].value_.v_short[0];
+ break;
+ case 1: /* BYTE */
+ spatial_xfrm = (unsigned long) ifd[idx].value_.v_byte[0];
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ if (spatial_xfrm > 7 || spatial_xfrm < 0)
+ spatial_xfrm = 0;
+ return spatial_xfrm;
+}
+
+unsigned long jxrc_image_type(jxr_container_t container, int image)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+ unsigned long image_type;
+
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0xbc04)
+ break;
+ }
+
+ if (idx >= ifd_cnt) return 0;
+ if (ifd[idx].tag != 0xbc04) return 0;
+ assert(ifd[idx].cnt == 1);
+ assert(ifd[idx].type == 4);
+
+ image_type = ifd[idx].value_.v_long;
+ image_type &= 0x00000003;
+ return image_type;
+}
+
+int jxrc_ptm_color_info(jxr_container_t container, int image, unsigned char * buf)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+ uint32_t i;
+
+ assert(image < container->image_count);
+ assert(buf);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0xbc05)
+ break;
+ }
+
+ if (idx >= ifd_cnt) return -1;
+ if (ifd[idx].tag != 0xbc05) return -1;
+ assert(ifd[idx].cnt == 4);
+ assert(ifd[idx].type == 1);
+
+ for (i = 0 ; i < 4 ; i += 1)
+ buf[i] = ifd[idx].value_.v_byte[i];
+
+ return 0;
+}
+
+int jxrc_profile_level_container(jxr_container_t container, int image, unsigned char * profile, unsigned char * level)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+ unsigned char * data;
+ uint32_t count_remaining;
+ uint8_t last, last_flag;
+
+ assert(image < container->image_count);
+ assert(profile);
+ assert(level);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ data = 0;
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0xbc06)
+ break;
+ }
+
+ if (idx >= ifd_cnt) return -1;
+ if (ifd[idx].tag != 0xbc06) return -1;
+ assert(ifd[idx].type == 1);
+ assert(ifd[idx].cnt > 3);
+
+ if (ifd[idx].cnt <= 4) {
+ data = (unsigned char *) (ifd[idx].value_.v_sbyte);
+ }
+ else {
+ data = (unsigned char *) (ifd[idx].value_.p_sbyte);
+ }
+
+ count_remaining = ifd[idx].cnt;
+ for (last = 0 ; last == 0 ; last = last_flag) {
+ profile[0] = data[0];
+ level[0] = data[1];
+ last_flag = (data[3] & 0x1);
+ data += 4;
+ count_remaining -= 4;
+ assert(count_remaining == 0 || count_remaining > 3);
+ }
+
+ return 0;
+}
+
+unsigned long jxrc_image_width(jxr_container_t container, int image)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+ unsigned long width;
+
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0xbc80)
+ break;
+ }
+
+ assert(idx < ifd_cnt);
+ assert(ifd[idx].tag == 0xbc80);
+ assert(ifd[idx].cnt == 1);
+
+ switch (ifd[idx].type) {
+ case 4: /* ULONG */
+ width = (unsigned long) ifd[idx].value_.v_long;
+ break;
+ case 3: /* USHORT */
+ width = (unsigned long) ifd[idx].value_.v_short[0];
+ break;
+ case 1: /* BYTE */
+ width = (unsigned long) ifd[idx].value_.v_byte[0];
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ return width;
+}
+
+unsigned long jxrc_image_height(jxr_container_t container, int image)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+ unsigned long height;
+
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0xbc81)
+ break;
+ }
+
+ assert(idx < ifd_cnt);
+ assert(ifd[idx].tag == 0xbc81);
+ assert(ifd[idx].cnt == 1);
+
+ switch (ifd[idx].type) {
+ case 4: /* ULONG */
+ height = (unsigned long) ifd[idx].value_.v_long;
+ break;
+ case 3: /* USHORT */
+ height = (unsigned long) ifd[idx].value_.v_short[0];
+ break;
+ case 1: /* BYTE */
+ height = (unsigned long) ifd[idx].value_.v_byte[0];
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ return height;
+}
+
+float jxrc_width_resolution(jxr_container_t container, int image)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+ float width_resolution;
+
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0xbc82)
+ break;
+ }
+
+ if (idx >= ifd_cnt) return 96.0;
+ if (ifd[idx].tag != 0xbc82) return 96.0;
+ assert(ifd[idx].cnt == 1);
+ assert(ifd[idx].type == 11);
+
+ width_resolution = ifd[idx].value_.v_float;
+ if (width_resolution == 0.0)
+ width_resolution = 96.0;
+ return width_resolution;
+}
+
+float jxrc_height_resolution(jxr_container_t container, int image)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+ float height_resolution;
+
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0xbc83)
+ break;
+ }
+
+ if (idx >= ifd_cnt) return 96.0;
+ if (ifd[idx].tag != 0xbc83) return 96.0;
+ assert(ifd[idx].cnt == 1);
+ assert(ifd[idx].type == 11);
+
+ height_resolution = ifd[idx].value_.v_float;
+ if (height_resolution == 0.0)
+ height_resolution = 96.0;
+ return height_resolution;
+}
+
+unsigned long jxrc_image_offset(jxr_container_t container, int image)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+ unsigned long pos;
+
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0xbcc0)
+ break;
+ }
+
+ assert(idx < ifd_cnt);
+ assert(ifd[idx].tag == 0xbcc0);
+ assert(ifd[idx].cnt == 1);
+
+ switch (ifd[idx].type) {
+ case 4: /* ULONG */
+ pos = (unsigned long) ifd[idx].value_.v_long;
+ break;
+ case 3: /* USHORT */
+ pos = (unsigned long) ifd[idx].value_.v_short[0];
+ break;
+ case 1: /* BYTE */
+ pos = (unsigned long) ifd[idx].value_.v_byte[0];
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ return pos;
+}
+
+unsigned long jxrc_image_bytecount(jxr_container_t container, int image)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+ unsigned long pos;
+
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0xbcc1)
+ break;
+ }
+
+ assert(idx < ifd_cnt);
+ assert(ifd[idx].tag == 0xbcc1);
+ assert(ifd[idx].cnt == 1);
+
+ switch (ifd[idx].type) {
+ case 4: /* ULONG */
+ pos = (unsigned long) ifd[idx].value_.v_long;
+ break;
+ case 3: /* USHORT */
+ pos = (unsigned long) ifd[idx].value_.v_short[0];
+ break;
+ case 1: /* BYTE */
+ pos = (unsigned long) ifd[idx].value_.v_byte[0];
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ return pos;
+}
+
+unsigned long jxrc_alpha_offset(jxr_container_t container, int image)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+ unsigned long pos;
+
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0xBCC2)
+ break;
+ }
+
+ if (idx >= ifd_cnt) return 0; /* No alpha coded image */
+ if (ifd[idx].tag != 0xbcc2) return 0;
+ assert(ifd[idx].cnt == 1);
+
+ switch (ifd[idx].type) {
+ case 4: /* ULONG */
+ pos = (unsigned long) ifd[idx].value_.v_long;
+ break;
+ case 3: /* USHORT */
+ pos = (unsigned long) ifd[idx].value_.v_short[0];
+ break;
+ case 1: /* BYTE */
+ pos = (unsigned long) ifd[idx].value_.v_byte[0];
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ return pos;
+}
+
+unsigned long jxrc_alpha_bytecount(jxr_container_t container, int image)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+ unsigned long pos;
+
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0xbcc3)
+ break;
+ }
+
+
+ if (idx >= ifd_cnt) return 0; /* No alpha coded image */
+ if (ifd[idx].tag != 0xbcc3) return 0;
+ assert(ifd[idx].cnt == 1);
+
+ switch (ifd[idx].type) {
+ case 4: /* ULONG */
+ pos = (unsigned long) ifd[idx].value_.v_long;
+ break;
+ case 3: /* USHORT */
+ pos = (unsigned long) ifd[idx].value_.v_short[0];
+ break;
+ case 1: /* BYTE */
+ pos = (unsigned long) ifd[idx].value_.v_byte[0];
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ return pos;
+}
+
+unsigned char jxrc_image_band_presence(jxr_container_t container, int image)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0xbcc4)
+ break;
+ }
+
+
+ if (idx >= ifd_cnt) return -1;
+ if (ifd[idx].tag != 0xbcc4) return -1;
+ assert(ifd[idx].cnt == 1);
+ assert(ifd[idx].type == 1);
+
+ return ifd[idx].value_.v_byte[0];
+}
+
+unsigned char jxrc_alpha_band_presence(jxr_container_t container, int image)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0xbcc5)
+ break;
+ }
+
+
+ if (idx >= ifd_cnt) return -1; /* tag is not present */
+ if (ifd[idx].tag != 0xbcc5) return -1;
+ assert(ifd[idx].cnt == 1);
+ assert(ifd[idx].type == 1);
+
+ return ifd[idx].value_.v_byte[0];
+}
+
+int jxrc_padding_data(jxr_container_t container, int image)
+{
+ unsigned ifd_cnt;
+ struct ifd_table*ifd;
+ unsigned idx;
+ unsigned char * data;
+ unsigned i;
+
+ assert(image < container->image_count);
+
+ ifd_cnt = container->table_cnt[image];
+ ifd = container->table[image];
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1) {
+ if (ifd[idx].tag == 0xea1c)
+ break;
+ }
+
+ if (idx >= ifd_cnt) return -1;
+ if (ifd[idx].tag != 0xea1c) return -1;
+ assert(ifd[idx].type == 7);
+ assert(ifd[idx].cnt > 1);
+
+ if (ifd[idx].cnt <= 4)
+ data = (unsigned char *) ifd[idx].value_.v_sbyte;
+ else
+ data = (unsigned char *) ifd[idx].value_.p_sbyte;
+
+ assert(data[0] == 0x1c);
+ assert(data[1] == 0xea);
+
+ return 0;
+}
+
+uint16_t bytes2_to_off(uint8_t*bp)
+{
+ return (bp[1]<<8) + (bp[0]);
+}
+
+uint32_t bytes4_to_off(uint8_t*bp)
+{
+ return (bp[3]<<24) + (bp[2]<<16) + (bp[1]<<8) + (bp[0]);
+}
+
+static int read_ifd(jxr_container_t container, FILE*fd, int image_number, uint32_t*ifd_next)
+{
+ unsigned char buf[16];
+ size_t rc;
+ int idx;
+ int ifd_tag_prev = 0;
+ int alpha_tag_check = 0;
+ uint32_t ifd_off;
+ struct ifd_table*cur;
+ uint16_t entry_count;
+
+ *ifd_next = 0;
+
+ rc = fread(buf, 1, 2, fd);
+ if (rc != 2) return -1;
+
+ entry_count = (buf[1]<<8) + (buf[0]<<0);
+ container->table_cnt[image_number] = entry_count;
+
+ cur = (struct ifd_table*)calloc(entry_count, sizeof(struct ifd_table));
+ assert(cur != 0);
+
+ container->table[image_number] = cur;
+
+ /* First read in the entire directory. Don't interpret the
+ types yet, just save the values as v_bytes. We will go
+ through the types later and interpret the values more
+ precisely. */
+ for (idx = 0 ; idx < entry_count ; idx += 1) {
+ uint16_t ifd_tag;
+ uint16_t ifd_type;
+ uint32_t ifd_cnt;
+
+ rc = fread(buf, 1, 12, fd);
+ assert(rc == 12);
+
+ ifd_tag = (buf[1]<<8) + (buf[0]<<0);
+ if (ifd_tag == 0xbcc2)
+ alpha_tag_check += 1;
+ if (ifd_tag == 0xbcc3)
+ alpha_tag_check += 2;
+ if (ifd_tag == 0xbcc5)
+ alpha_tag_check += 4;
+ ifd_type = (buf[3]<<8) + (buf[2]<<0);
+ if (ifd_type == 7)
+ assert (ifd_tag == 0x8773 || ifd_tag == 0xea1c);
+ ifd_cnt = (buf[7]<<24) + (buf[6]<<16) + (buf[5]<<8) + buf[4];
+
+ assert(ifd_tag > ifd_tag_prev);
+ ifd_tag_prev = ifd_tag;
+
+ cur[idx].tag = ifd_tag;
+ cur[idx].type = ifd_type;
+ cur[idx].cnt = ifd_cnt;
+
+ cur[idx].value_.v_byte[0] = buf[8];
+ cur[idx].value_.v_byte[1] = buf[9];
+ cur[idx].value_.v_byte[2] = buf[10];
+ cur[idx].value_.v_byte[3] = buf[11];
+ }
+ /* verify alpha ifd tags appear only in allowed combinations */
+ assert(alpha_tag_check == 0 || alpha_tag_check == 3 || alpha_tag_check == 7);
+
+ rc = fread(buf, 1, 4, fd);
+ assert(rc == 4);
+
+ /* Now interpret the tag types/values for easy access later. */
+ for (idx = 0 ; idx < entry_count ; idx += 1) {
+ switch (cur[idx].type) {
+
+ case 1: /* BYTE */
+ case 2: /* UTF8 */
+ case 6: /* SBYTE */
+ case 7: /* UNDEFINED */
+ DEBUG("Container %d: tag 0x%04x BYTE:", image_number, cur[idx].tag);
+ if (cur[idx].cnt > 4) {
+ ifd_off = bytes4_to_off(cur[idx].value_.v_byte);
+ assert((ifd_off & 1) == 0);
+ fseek(fd, ifd_off, SEEK_SET);
+ cur[idx].value_.p_byte = (uint8_t*)malloc(cur[idx].cnt);
+ fread(cur[idx].value_.p_byte, 1, cur[idx].cnt, fd);
+#if defined(DETAILED_DEBUG)
+ {
+ int bb;
+ for (bb = 0 ; bb < cur[idx].cnt ; bb += 1)
+ DEBUG("%02x", cur[idx].value_.p_byte[bb]);
+ }
+#endif
+ if (cur[idx].type == 2) {
+ int cc;
+ for (cc = 1 ; cc < cur[idx].cnt ; cc += 1)
+ assert((cur[idx].value_.p_byte[cc - 1] != 0) || (cur[idx].value_.p_byte[cc] != 0));
+ }
+ }
+ else {
+ if (cur[idx].type == 2) {
+ int cc;
+ for (cc = 1 ; cc < cur[idx].cnt ; cc += 1)
+ assert((cur[idx].value_.v_byte[cc - 1] != 0) || (cur[idx].value_.v_byte[cc] != 0));
+ }
+ }
+ /* No action required to access individual bytes */
+ DEBUG("\n");
+ break;
+
+ case 3: /* USHORT */
+ case 8: /* SSHORT */
+ if (cur[idx].cnt <= 2) {
+ cur[idx].value_.v_short[0] = bytes2_to_off(cur[idx].value_.v_byte + 0);
+ cur[idx].value_.v_short[1] = bytes2_to_off(cur[idx].value_.v_byte + 2);
+ DEBUG("Container %d: tag 0x%04x SHORT %u SHORT %u\n", image_number,
+ cur[idx].tag, cur[idx].value_.v_short[0], cur[idx].value_.v_short[1]);
+ } else {
+ uint16_t cdx;
+
+ ifd_off = bytes4_to_off(cur[idx].value_.v_byte);
+ assert((ifd_off & 1) == 0);
+ fseek(fd, ifd_off, SEEK_SET);
+ cur[idx].value_.p_short = (uint16_t*) calloc(cur[idx].cnt, sizeof(uint16_t));
+
+ DEBUG("Container %d: tag 0x%04x SHORT\n", image_number,
+ cur[idx].tag);
+ for (cdx = 0 ; cdx < cur[idx].cnt ; cdx += 1) {
+ uint8_t buf[2];
+ fread(buf, 1, 2, fd);
+ cur[idx].value_.p_short[cdx] = bytes2_to_off(buf);
+ DEBUG(" %u", cur[idx].value_.p_short[cdx]);
+ }
+ DEBUG("\n");
+ }
+ break;
+
+ case 4: /* ULONG */
+ case 9: /* SLONG */
+ case 11: /* FLOAT */
+ if (cur[idx].cnt == 1) {
+ cur[idx].value_.v_long = bytes4_to_off(cur[idx].value_.v_byte);
+ DEBUG("Container %d: tag 0x%04x LONG %u\n", image_number,
+ cur[idx].tag, cur[idx].value_.v_long);
+ } else {
+ uint32_t cdx;
+
+ ifd_off = bytes4_to_off(cur[idx].value_.v_byte);
+ assert((ifd_off & 1) == 0);
+ fseek(fd, ifd_off, SEEK_SET);
+ cur[idx].value_.p_long = (uint32_t*) calloc(cur[idx].cnt, sizeof(uint32_t));
+
+ DEBUG("Container %d: tag 0x%04x LONG\n", image_number,
+ cur[idx].tag);
+ for (cdx = 0 ; cdx < cur[idx].cnt ; cdx += 1) {
+ uint8_t buf[4];
+ fread(buf, 1, 4, fd);
+ cur[idx].value_.p_long[cdx] = bytes4_to_off(buf);
+ DEBUG(" %u", cur[idx].value_.p_long[cdx]);
+ }
+ DEBUG("\n");
+ }
+ break;
+
+ case 5: /* URATIONAL */
+ case 10: /* SRATIONAL */
+ case 12: /* DOUBLE */
+ {
+ uint64_t cdx;
+
+ /* Always offset */
+ ifd_off = bytes4_to_off(cur[idx].value_.v_byte);
+ assert((ifd_off & 1) == 0);
+ fseek(fd, ifd_off, SEEK_SET);
+ cur[idx].value_.p_rational = (uint64_t*) calloc(cur[idx].cnt, sizeof(uint64_t));
+
+ DEBUG("Container %d: tag 0x%04x LONG\n", image_number,
+ cur[idx].tag);
+ for (cdx = 0 ; cdx < cur[idx].cnt ; cdx += 1) {
+ uint8_t buf[4];
+ fread(buf, 1, 4, fd);
+ cur[idx].value_.p_long[2 * cdx + 0] = bytes4_to_off(buf);
+ fread(buf, 1, 4, fd);
+ cur[idx].value_.p_long[2 * cdx + 1] = bytes4_to_off(buf);
+ DEBUG(" %u", cur[idx].value_.p_rational[cdx]);
+ }
+ DEBUG("\n");
+ }
+ break;
+
+ default:
+ DEBUG("Container %d: tag 0x%04x type=%u\n", image_number, cur[idx].tag, cur[idx].type);
+ break;
+ }
+ }
+
+ /* Tell the caller about the next ifd. */
+ *ifd_next = (buf[3] << 24) + (buf[2]<<16) + (buf[1]<<8) + (buf[0]<<0);
+
+ return 0;
+}
+
+
+/*
+* $Log: cr_parse.c,v $
+* Revision 1.11 2009/05/29 12:00:00 microsoft
+* Reference Software v1.6 updates.
+*
+* Revision 1.10 2009/04/13 12:00:00 microsoft
+* Reference Software v1.5 updates.
+*
+* Revision 1.9 2008/03/21 21:23:14 steve
+* Some debug dump of the container.
+*
+* Revision 1.8 2008/03/05 19:32:02 gus
+* *** empty log message ***
+*
+* Revision 1.7 2008/03/01 02:46:08 steve
+* Add support for JXR container.
+*
+* Revision 1.6 2008/02/28 18:50:31 steve
+* Portability fixes.
+*
+* Revision 1.5 2008/02/26 23:52:44 steve
+* Remove ident for MS compilers.
+*
+* Revision 1.4 2007/11/26 01:47:15 steve
+* Add copyright notices per MS request.
+*
+* Revision 1.3 2007/11/07 18:11:35 steve
+* Accept magic number version 0
+*
+* Revision 1.2 2007/07/30 23:09:57 steve
+* Interleave FLEXBITS within HP block.
+*
+* Revision 1.1 2007/06/06 17:19:12 steve
+* Introduce to CVS.
+*
+*/
+
diff --git a/jpegxr/cw_emit.c b/jpegxr/cw_emit.c
new file mode 100644
index 000000000..cda26feed
--- /dev/null
+++ b/jpegxr/cw_emit.c
@@ -0,0 +1,677 @@
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+***********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: cw_emit.c,v 1.2 2008/03/02 18:35:27 steve Exp $")
+#else
+#ident "$Id: cw_emit.c,v 1.2 2008/03/02 18:35:27 steve Exp $"
+#endif
+
+# include "jxr_priv.h"
+# include <stdlib.h>
+# include <string.h>
+# include <assert.h>
+
+int jxrc_start_file(jxr_container_t cp, FILE*fd)
+{
+ const unsigned char head_bytes[8] = {0x49, 0x49, 0xbc, 0x01,
+ 0x08, 0x00, 0x00, 0x00 };
+
+ assert(cp->fd == 0);
+
+ /* initializations */
+ cp->separate_alpha_image_plane = 0;
+ cp->image_count_mark = 0;
+ cp->alpha_count_mark = 0;
+ cp->alpha_offset_mark = 0;
+ cp->alpha_band = 0;
+
+ cp->fd = fd;
+ cp->file_mark = ftell(cp->fd);
+
+ fwrite(head_bytes, 1, 8, cp->fd);
+ return 0;
+}
+
+int jxrc_begin_ifd_entry(jxr_container_t cp)
+{
+ assert(cp->image_count == 0);
+ cp->image_count = 1;
+ return 0;
+}
+
+
+int jxrc_set_pixel_format(jxr_container_t cp, jxrc_t_pixelFormat fmt)
+{
+ memcpy(cp->pixel_format, jxr_guids[fmt], 16);
+
+ return 0;
+}
+
+jxrc_t_pixelFormat jxrc_get_pixel_format(jxr_container_t cp)
+{
+ unsigned char guid[16];
+ int i;
+
+ for(i=0; i< NUM_GUIDS; i++)
+ {
+ if(isEqualGUID(cp->pixel_format, jxr_guids[i]))
+ {
+ break;
+ }
+ }
+ if(i==NUM_GUIDS)
+ assert(0);
+ return (jxrc_t_pixelFormat)i;
+
+}
+
+
+int jxrc_set_image_shape(jxr_container_t cp, unsigned wid, unsigned hei)
+{
+ cp->wid = wid;
+ cp->hei = hei;
+ return 0;
+}
+
+int jxrc_set_image_band_presence(jxr_container_t cp, unsigned bands)
+{
+ cp->image_band = (uint8_t) bands;
+ return 0;
+}
+
+/*
+This will induce the encoder to write as many of the
+IFD tags of table A.4 (the listing of IFD tags) as it can
+Off by default.
+#define WRITE_OPTIONAL_IFD_TAGS
+*/
+
+int jxrc_set_separate_alpha_image_plane(jxr_container_t cp, unsigned int alpha_present)
+{
+ cp->separate_alpha_image_plane = alpha_present;
+ return 0;
+}
+
+static void emit_ifd(jxr_container_t cp)
+{
+ unsigned long ifd_mark;
+ int idx;
+ struct ifd_table ifd[64];
+ unsigned char buf[1024];
+
+ int num_ifd = 0;
+ int num_buf = 0;
+ unsigned long ifd_len;
+ unsigned char scr[12];
+
+#ifdef WRITE_OPTIONAL_IFD_TAGS
+ int ifd_cnt;
+ char * input_string;
+
+ /* various sample strings used to test storage */
+ char document_name[] = {"JPEG XR image created by JPEG XR sample encoder."};
+ char image_description[] = {"The core codestream begins at WMPHOTO"};
+ char equipment_make[] = {"???"};
+ char equipment_model[] = {"JXR 0X1"};
+ char page_name[]={"Test page name"};
+ unsigned short page_number[] = {1,2};
+ char software_name_version[]={"JPEG XR reference software v1.6"};
+ char date_time[]={"2009:04:01 12:34:56"};
+ char artist_name[]={"JPEG Committee"};
+ char host_computer[]={"JXR"};
+ char copyright_notice[]={"©JPEG Committee"};
+ unsigned long spatial_xfrm = 0;
+ unsigned char profile_idc = 111;
+ unsigned char level_idc = 255;
+ float width_res = 96.0;
+ float height_res = 96.0;
+
+ assert(cp->image_count > 0);
+ if (cp->image_count > 1){
+ assert(0);
+ ifd_mark = 0;
+ } else {
+ ifd_mark = 8;
+ }
+
+ input_string = document_name;
+ ifd_cnt = strlen(input_string) + 1;
+ ifd[num_ifd].tag = 0x010d; /* DOCUMENT_NAME */
+ ifd[num_ifd].type = 2; /* UTF8 */
+ ifd[num_ifd].cnt = ifd_cnt;
+ if (ifd_cnt > 4)
+ ifd[num_ifd].value_.v_long = ifd_mark + num_buf;
+ else
+ memcpy(ifd[num_ifd].value_.v_sbyte, input_string, ifd_cnt);
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1)
+ buf[num_buf++] = input_string[idx];
+ if (num_buf & 0x1)
+ buf[num_buf++] = (unsigned char) 0;
+ num_ifd += 1;
+
+ input_string = image_description;
+ ifd_cnt = strlen(input_string) + 1;
+ ifd[num_ifd].tag = 0x010e; /* IMAGE_DESCRIPTION */
+ ifd[num_ifd].type = 2; /* UTF8 */
+ ifd[num_ifd].cnt = ifd_cnt;
+ if (ifd_cnt > 4)
+ ifd[num_ifd].value_.v_long = ifd_mark + num_buf;
+ else
+ memcpy(ifd[num_ifd].value_.v_sbyte, input_string, ifd_cnt);
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1)
+ buf[num_buf++] = input_string[idx];
+ if (num_buf & 0x1)
+ buf[num_buf++] = (unsigned char) 0;
+ num_ifd += 1;
+
+ input_string = equipment_make;
+ ifd_cnt = strlen(input_string) + 1;
+ ifd[num_ifd].tag = 0x010f; /* EQUIPMENT_MAKE */
+ ifd[num_ifd].type = 2; /* UTF8 */
+ ifd[num_ifd].cnt = ifd_cnt;
+ if (ifd_cnt > 4)
+ ifd[num_ifd].value_.v_long = ifd_mark + num_buf;
+ else
+ memcpy(ifd[num_ifd].value_.v_sbyte, input_string, ifd_cnt);
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1)
+ buf[num_buf++] = input_string[idx];
+ if (num_buf & 0x1)
+ buf[num_buf++] = (unsigned char) 0;
+ num_ifd += 1;
+
+ input_string = equipment_model;
+ ifd_cnt = strlen(input_string) + 1;
+ ifd[num_ifd].tag = 0x0110; /* EQUIPMENT_MODEL */
+ ifd[num_ifd].type = 2; /* UTF8 */
+ ifd[num_ifd].cnt = ifd_cnt;
+ if (ifd_cnt > 4)
+ ifd[num_ifd].value_.v_long = ifd_mark + num_buf;
+ else
+ memcpy(ifd[num_ifd].value_.v_sbyte, input_string, ifd_cnt);
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1)
+ buf[num_buf++] = input_string[idx];
+ if (num_buf & 0x1)
+ buf[num_buf++] = (unsigned char) 0;
+ num_ifd += 1;
+
+ input_string = page_name;
+ ifd_cnt = strlen(input_string) + 1;
+ ifd[num_ifd].tag = 0x011d; /* PAGE_NAME */
+ ifd[num_ifd].type = 2; /* UTF8 */
+ ifd[num_ifd].cnt = ifd_cnt;
+ if (ifd_cnt > 4)
+ ifd[num_ifd].value_.v_long = ifd_mark + num_buf;
+ else
+ memcpy(ifd[num_ifd].value_.v_sbyte, input_string, ifd_cnt);
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1)
+ buf[num_buf++] = input_string[idx];
+ if (num_buf & 0x1)
+ buf[num_buf++] = (unsigned char) 0;
+ num_ifd += 1;
+
+ ifd[num_ifd].tag = 0x0129; /* PAGE_NUMBER */
+ ifd[num_ifd].type = 3; /* USHORT */
+ ifd[num_ifd].cnt = 2;
+ ifd[num_ifd].value_.v_short[0] = page_number[0];
+ ifd[num_ifd].value_.v_short[1] = page_number[1];
+ num_ifd += 1;
+
+ input_string = software_name_version;
+ ifd_cnt = strlen(input_string) + 1;
+ ifd[num_ifd].tag = 0x0131; /* SOFTWARE_NAME_VERSION */
+ ifd[num_ifd].type = 2; /* UTF8 */
+ ifd[num_ifd].cnt = ifd_cnt;
+ if (ifd_cnt > 4)
+ ifd[num_ifd].value_.v_long = ifd_mark + num_buf;
+ else
+ memcpy(ifd[num_ifd].value_.v_sbyte, input_string, ifd_cnt);
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1)
+ buf[num_buf++] = input_string[idx];
+ if (num_buf & 0x1)
+ buf[num_buf++] = (unsigned char) 0;
+ num_ifd += 1;
+
+ input_string = date_time;
+ ifd_cnt = strlen(input_string) + 1;
+ ifd[num_ifd].tag = 0x0132; /* DATE_TIME */
+ ifd[num_ifd].type = 2; /* UTF8 */
+ ifd[num_ifd].cnt = ifd_cnt;
+ if (ifd_cnt > 4)
+ ifd[num_ifd].value_.v_long = ifd_mark + num_buf;
+ else
+ memcpy(ifd[num_ifd].value_.v_sbyte, input_string, ifd_cnt);
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1)
+ buf[num_buf++] = input_string[idx];
+ if (num_buf & 0x1)
+ buf[num_buf++] = (unsigned char) 0;
+ num_ifd += 1;
+
+ input_string = artist_name;
+ ifd_cnt = strlen(input_string) + 1;
+ ifd[num_ifd].tag = 0x013b; /* ARTIST_NAME */
+ ifd[num_ifd].type = 2; /* UTF8 */
+ ifd[num_ifd].cnt = ifd_cnt;
+ if (ifd_cnt > 4)
+ ifd[num_ifd].value_.v_long = ifd_mark + num_buf;
+ else
+ memcpy(ifd[num_ifd].value_.v_sbyte, input_string, ifd_cnt);
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1)
+ buf[num_buf++] = input_string[idx];
+ if (num_buf & 0x1)
+ buf[num_buf++] = (unsigned char) 0;
+ num_ifd += 1;
+
+ input_string = host_computer;
+ ifd_cnt = strlen(input_string) + 1;
+ ifd[num_ifd].tag = 0x013c; /* HOST_COMPUTER */
+ ifd[num_ifd].type = 2; /* UTF8 */
+ ifd[num_ifd].cnt = ifd_cnt;
+ if (ifd_cnt > 4)
+ ifd[num_ifd].value_.v_long = ifd_mark + num_buf;
+ else
+ memcpy(ifd[num_ifd].value_.v_sbyte, input_string, ifd_cnt);
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1)
+ buf[num_buf++] = input_string[idx];
+ if (num_buf & 0x1)
+ buf[num_buf++] = (unsigned char) 0;
+ num_ifd += 1;
+
+ input_string = copyright_notice;
+ ifd_cnt = strlen(input_string) + 1;
+ ifd[num_ifd].tag = 0x8298; /* COPYRIGHT_NOTICE */
+ ifd[num_ifd].type = 2; /* UTF8 */
+ ifd[num_ifd].cnt = ifd_cnt;
+ if (ifd_cnt > 4)
+ ifd[num_ifd].value_.v_long = ifd_mark + num_buf;
+ else
+ memcpy(ifd[num_ifd].value_.v_sbyte, input_string, ifd_cnt);
+
+ for (idx = 0 ; idx < ifd_cnt ; idx += 1)
+ buf[num_buf++] = input_string[idx];
+ if (num_buf & 0x1)
+ buf[num_buf++] = (unsigned char) 0;
+ num_ifd += 1;
+
+ ifd[num_ifd].tag = 0xa001; /* COLOR_SPACE */
+ ifd[num_ifd].type = 3; /* USHORT */
+ ifd[num_ifd].cnt = 1;
+ ifd[num_ifd].value_.v_short[0] = 0xffff; /* Just use this value for testing */
+ ifd[num_ifd].value_.v_short[1] = 0;
+ num_ifd += 1;
+#endif
+
+ ifd[num_ifd].tag = 0xbc01; /* PIXEL_FORMAT */
+ ifd[num_ifd].type = 1; /* BYTE */
+ ifd[num_ifd].cnt = 16;
+ ifd[num_ifd].value_.v_long = ifd_mark + num_buf;
+
+ for (idx = 0 ; idx < 16 ; idx += 1)
+ buf[num_buf++] = cp->pixel_format[idx];
+ num_ifd += 1;
+
+#ifdef WRITE_OPTIONAL_IFD_TAGS
+ ifd[num_ifd].tag = 0xbc02; /* SPATIAL_XFRM_PRIMARY */
+ ifd[num_ifd].type = 4; /* ULONG */
+ ifd[num_ifd].cnt = 1;
+ ifd[num_ifd].value_.v_long = spatial_xfrm;
+ num_ifd += 1;
+
+ /* IMAGE_TYPE should only be present when multiple images are in the image */
+ /* Fix this condition if encoder can handle multiple images */
+ if (0){
+ ifd[num_ifd].tag = 0xbc04; /* IMAGE_TYPE */
+ ifd[num_ifd].type = 4; /* ULONG */
+ ifd[num_ifd].cnt = 1;
+ ifd[num_ifd].value_.v_long = 0;
+ num_ifd += 1;
+ }
+
+ ifd[num_ifd].tag = 0xbc05; /* PTM_COLOR_INFO() */
+ ifd[num_ifd].type = 1; /* BYTE */
+ ifd[num_ifd].cnt = 4;
+ ifd[num_ifd].value_.v_byte[0] = 2; /* default to unspecified */
+ ifd[num_ifd].value_.v_byte[1] = 2; /* default to unspecified */
+ ifd[num_ifd].value_.v_byte[2] = 2; /* default to no rotation */
+ ifd[num_ifd].value_.v_byte[3] = 0; /* default to no rotation */
+ num_ifd += 1;
+
+ ifd[num_ifd].tag = 0xbc06; /* PROFILE_LEVEL_CONTAINER() */
+ ifd[num_ifd].type = 1; /* BYTE */
+ ifd[num_ifd].cnt = 4;
+ ifd[num_ifd].value_.v_byte[0] = profile_idc;
+ ifd[num_ifd].value_.v_byte[1] = level_idc;
+ ifd[num_ifd].value_.v_byte[2] = 0;
+ ifd[num_ifd].value_.v_byte[3] = 1;
+ num_ifd += 1;
+
+#endif
+
+ ifd[num_ifd].tag = 0xbc80; /* IMAGE_WIDTH */
+ ifd[num_ifd].type = 4; /* ULONG */
+ ifd[num_ifd].cnt = 1;
+ ifd[num_ifd].value_.v_long = cp->wid;
+
+ num_ifd += 1;
+
+ ifd[num_ifd].tag = 0xbc81; /* IMAGE_HEIGHT */
+ ifd[num_ifd].type = 4; /* ULONG */
+ ifd[num_ifd].cnt = 1;
+ ifd[num_ifd].value_.v_long = cp->hei;
+
+ num_ifd += 1;
+
+#ifdef WRITE_OPTIONAL_IFD_TAGS
+ ifd[num_ifd].tag = 0xbc82; /* WIDTH_RESOLUTION */
+ ifd[num_ifd].type = 11; /* FLOAT */
+ ifd[num_ifd].cnt = 1;
+ ifd[num_ifd].value_.v_float = width_res;
+ num_ifd += 1;
+
+ ifd[num_ifd].tag = 0xbc83; /* HEIGHT_RESOLUTION */
+ ifd[num_ifd].type = 11; /* FLOAT */
+ ifd[num_ifd].cnt = 1;
+ ifd[num_ifd].value_.v_float = height_res;
+ num_ifd += 1;
+#endif
+
+ ifd[num_ifd].tag = 0xbcc0; /* IMAGE_OFFSET */
+ ifd[num_ifd].type = 4; /* ULONG */
+ ifd[num_ifd].cnt = 1;
+ ifd[num_ifd].value_.v_long = 0;
+
+ num_ifd += 1;
+
+ ifd[num_ifd].tag = 0xbcc1; /* IMAGE_COUNT */
+ ifd[num_ifd].type = 4; /* ULONG */
+ ifd[num_ifd].cnt = 1;
+ ifd[num_ifd].value_.v_long = 0;
+
+ num_ifd += 1;
+
+ if (cp->separate_alpha_image_plane) {
+ ifd[num_ifd].tag = 0xbcc2; /* ALPHA_OFFSET */
+ ifd[num_ifd].type = 4; /* ULONG */
+ ifd[num_ifd].cnt = 1;
+ ifd[num_ifd].value_.v_long = 0;
+
+ num_ifd += 1;
+
+ ifd[num_ifd].tag = 0xbcc3; /* ALPHA_COUNT */
+ ifd[num_ifd].type = 4; /* ULONG */
+ ifd[num_ifd].cnt = 1;
+ ifd[num_ifd].value_.v_long = 0;
+
+ num_ifd += 1;
+ }
+
+#ifdef WRITE_OPTIONAL_IFD_TAGS
+ ifd[num_ifd].tag = 0xbcc4; /* IMAGE_BAND_PRESENCE */
+ ifd[num_ifd].type = 1; /* BYTE */
+ ifd[num_ifd].cnt = 1;
+ ifd[num_ifd].value_.v_byte[0] = cp->image_band;
+ num_ifd += 1;
+
+ if (cp->separate_alpha_image_plane) {
+ ifd[num_ifd].tag = 0xbcc5; /* ALPHA_BAND_PRESENCE */
+ ifd[num_ifd].type = 1; /* BYTE */
+ ifd[num_ifd].cnt = 1;
+ ifd[num_ifd].value_.v_byte[0] = cp->alpha_band;
+ num_ifd += 1;
+ }
+
+ ifd[num_ifd].tag = 0xea1c; /* PADDING_DATA */
+ ifd[num_ifd].type = 7; /* UNDEFINED */
+ ifd[num_ifd].cnt = 21; /* Value set arbitrarily to tests this IFD entry */
+ ifd[num_ifd].value_.v_long = ifd_mark + num_buf;
+
+ assert(ifd[num_ifd].cnt > 1);
+
+ buf[num_buf++] = 0x1c;
+ buf[num_buf++] = 0xea;
+ for (idx = 2 ; idx < ifd[num_ifd].cnt ; idx += 1)
+ buf[num_buf++] = 0;
+ num_ifd += 1;
+#endif
+
+ ifd_len = 2 + 12*num_ifd + 4; /* NUM_ENTRIES + 12 bytes per entry + ZERO_OR_NEXT_IFD_OFFSET */
+
+ cp->image_offset_mark = ifd_mark + ifd_len + num_buf;
+
+ for (idx = 0 ; idx < num_ifd ; idx += 1) {
+ switch (ifd[idx].type) {
+ case 1: /* BYTE */
+ case 2: /* UTF8 */
+ case 6: /* SBYTE */
+ case 7: /* UNDEFINED */
+ if (ifd[idx].cnt > 4)
+ ifd[idx].value_.v_long += ifd_len;
+ break;
+ case 3: /* USHORT */
+ case 8: /* SSHORT */
+ if (ifd[idx].cnt > 2)
+ ifd[idx].value_.v_long += ifd_len;
+ break;
+ case 4: /* ULONG */
+ case 9: /* SLONG */
+ case 11: /* FLOAT */
+ if (ifd[idx].cnt > 1)
+ ifd[idx].value_.v_long += ifd_len;
+ /* If we find the IMAGE_OFFSET, we know its value
+ now. Write it into v_long */
+ if (ifd[idx].tag == 0xbcc0) /* IMAGE_OFFSET */
+ ifd[idx].value_.v_long = cp->image_offset_mark;
+ /* For the following markers, record the locations to be filled in later */
+ if (ifd[idx].tag == 0xbcc1) /* IMAGE_COUNT */
+ cp->image_count_mark = ifd_mark + 2 + 12*idx + 8;
+ if (ifd[idx].tag == 0xbcc2) /* ALPHA_OFFSET */
+ cp->alpha_offset_mark = ifd_mark + 2 + 12*idx + 8;
+ if (ifd[idx].tag == 0xbcc3) /* ALPHA_COUNT */
+ cp->alpha_count_mark = ifd_mark + 2 + 12*idx + 8;
+
+ break;
+ case 5: /* URATIONAL */
+ case 10: /* SRATIONAL */
+ case 12: /* DOUBLE */
+ ifd[idx].value_.v_long += ifd_len;
+ break;
+ default: /* RESERVED */
+ assert(0);
+ }
+ }
+
+ scr[0] = (num_ifd>>0) & 0xff;
+ scr[1] = (num_ifd>>8) & 0xff;
+ fwrite(scr, 1, 2, cp->fd);
+ for (idx = 0 ; idx < num_ifd ; idx += 1) {
+ scr[0] = (ifd[idx].tag >> 0) & 0xff;
+ scr[1] = (ifd[idx].tag >> 8) & 0xff;
+ scr[2] = (ifd[idx].type>> 0) & 0xff;
+ scr[3] = (ifd[idx].type>> 8) & 0xff;
+ scr[4] = (ifd[idx].cnt >> 0) & 0xff;
+ scr[5] = (ifd[idx].cnt >> 8) & 0xff;
+ scr[6] = (ifd[idx].cnt >>16) & 0xff;
+ scr[7] = (ifd[idx].cnt >>24) & 0xff;
+
+ switch (ifd[idx].type) {
+ case 1: /* BYTE */
+ case 2: /* UTF8 */
+ case 6: /* SBYTE */
+ case 7: /* UNDEFINED */
+ if (ifd[idx].cnt <= 4) {
+ scr[ 8] = ifd[idx].value_.v_byte[0];
+ scr[ 9] = ifd[idx].value_.v_byte[1];
+ scr[10] = ifd[idx].value_.v_byte[2];
+ scr[11] = ifd[idx].value_.v_byte[3];
+ } else {
+ scr[ 8] = (ifd[idx].value_.v_long >> 0) & 0xff;
+ scr[ 9] = (ifd[idx].value_.v_long >> 8) & 0xff;
+ scr[10] = (ifd[idx].value_.v_long >>16) & 0xff;
+ scr[11] = (ifd[idx].value_.v_long >>24) & 0xff;
+ }
+ break;
+ case 3: /* USHORT */
+ case 8: /* SSHORT */
+ if (ifd[idx].cnt <= 2) {
+ scr[ 8] = (ifd[idx].value_.v_short[0] >> 0) & 0xff;
+ scr[ 9] = (ifd[idx].value_.v_short[0] >> 8) & 0xff;
+ scr[10] = (ifd[idx].value_.v_short[1] >> 0) & 0xff;
+ scr[11] = (ifd[idx].value_.v_short[1] >> 8) & 0xff;
+ } else {
+ scr[ 8] = (ifd[idx].value_.v_long >> 0) & 0xff;
+ scr[ 9] = (ifd[idx].value_.v_long >> 8) & 0xff;
+ scr[10] = (ifd[idx].value_.v_long >>16) & 0xff;
+ scr[11] = (ifd[idx].value_.v_long >>24) & 0xff;
+ }
+ break;
+ case 4: /* ULONG */
+ case 9: /* SLONG */
+ case 11: /* FLOAT */
+ case 5: /* URATIONAL */
+ case 10: /* SRATIONAL */
+ case 12: /* DOUBLE */
+ scr[ 8] = (ifd[idx].value_.v_long >> 0) & 0xff;
+ scr[ 9] = (ifd[idx].value_.v_long >> 8) & 0xff;
+ scr[10] = (ifd[idx].value_.v_long >>16) & 0xff;
+ scr[11] = (ifd[idx].value_.v_long >>24) & 0xff;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ fwrite(scr, 1, 12, cp->fd);
+ }
+ cp->next_ifd_mark = ftell(cp->fd);
+ scr[0] = 0;
+ scr[1] = 0;
+ scr[2] = 0;
+ scr[3] = 0;
+
+ fwrite(scr, 1, 4, cp->fd);
+
+ fwrite(buf, 1, num_buf, cp->fd);
+}
+
+int jxrc_begin_image_data(jxr_container_t cp)
+{
+ emit_ifd(cp);
+ return 0;
+}
+
+int jxrc_write_container_post(jxr_container_t cp)
+{
+ uint32_t mark = ftell(cp->fd);
+ uint32_t count;
+ unsigned char scr[4];
+
+ mark = (mark+1)&~1;
+
+ assert(mark > cp->image_offset_mark);
+ count = mark - cp->image_offset_mark;
+
+ DEBUG("CONTAINER: measured bitstream count=%u\n", count);
+
+ fseek(cp->fd, cp->image_count_mark, SEEK_SET);
+
+ scr[0] = (count >> 0) & 0xff;
+ scr[1] = (count >> 8) & 0xff;
+ scr[2] = (count >> 16) & 0xff;
+ scr[3] = (count >> 24) & 0xff;
+ fwrite(scr, 1, 4, cp->fd);
+
+ if(cp->separate_alpha_image_plane)
+ {
+ fseek(cp->fd, cp->alpha_offset_mark, SEEK_SET);
+ count = mark;
+ scr[0] = (count >> 0) & 0xff;
+ scr[1] = (count >> 8) & 0xff;
+ scr[2] = (count >> 16) & 0xff;
+ scr[3] = (count >> 24) & 0xff;
+ fwrite(scr, 1, 4, cp->fd);
+ }
+ fseek(cp->fd, mark, SEEK_SET);
+ cp->alpha_begin_mark = mark;
+ return 0;
+}
+
+int jxrc_write_container_post_alpha(jxr_container_t cp)
+{
+ uint32_t mark = ftell(cp->fd);
+ uint32_t count;
+
+ mark = (mark+1)&~1;
+
+ count = mark - cp->alpha_begin_mark;
+ DEBUG("CONTAINER: measured alpha count=%u\n", count);
+
+ if(cp->separate_alpha_image_plane)
+ {
+ unsigned char scr[4];
+ fseek(cp->fd, cp->alpha_count_mark, SEEK_SET);
+ count = mark;
+ scr[0] = (count >> 0) & 0xff;
+ scr[1] = (count >> 8) & 0xff;
+ scr[2] = (count >> 16) & 0xff;
+ scr[3] = (count >> 24) & 0xff;
+ fwrite(scr, 1, 4, cp->fd);
+ }
+ fseek(cp->fd, mark, SEEK_SET);
+ return 0;
+}
+/*
+* $Log: cw_emit.c,v $
+* Revision 1.2 2009/05/29 12:00:00 microsoft
+* Reference Software v1.6 updates.
+*
+* Revision 1.1 2009/04/13 12:00:00 microsoft
+* Reference Software v1.5 updates.
+*
+*/
+
diff --git a/jpegxr/dll_resource.h b/jpegxr/dll_resource.h
new file mode 100644
index 000000000..e1b08553e
--- /dev/null
+++ b/jpegxr/dll_resource.h
@@ -0,0 +1,14 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by DLL.rc
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/jpegxr/dllmain.c b/jpegxr/dllmain.c
new file mode 100644
index 000000000..e56685686
--- /dev/null
+++ b/jpegxr/dllmain.c
@@ -0,0 +1,75 @@
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+***********************************************************************/
+
+/* dllmain.c : Defines the entry point for the DLL application. */
+
+#ifdef _MSC_VER
+
+#include <windows.h>
+
+extern "C" BOOL APIENTRY DllMain( HMODULE hModule,
+ DWORD ul_reason_for_call,
+ LPVOID lpReserved
+ )
+{
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
+
+#endif
+
+/*
+* $Log: dllmain.c,v $
+* Revision 1.2 2009/05/29 12:00:00 microsoft
+* Reference Software v1.6 updates.
+*
+* Revision 1.1 2009/04/13 12:00:00 microsoft
+* Reference Software v1.5 updates.
+*
+*/
+
diff --git a/jpegxr/file.c b/jpegxr/file.c
new file mode 100644
index 000000000..1a8042fd5
--- /dev/null
+++ b/jpegxr/file.c
@@ -0,0 +1,3082 @@
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+**********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: file.c,v 1.15 2008/03/17 23:34:54 steve Exp $")
+#else
+#ident "$Id: file.c,v 1.15 2008/03/17 23:34:54 steve Exp $"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include "jpegxr.h"
+# include "jxr_priv.h"
+
+#ifndef _MSC_VER
+# include <stdint.h>
+#else
+/* MSVC (as of 2008) does not support C99 or the stdint.h header
+file. So include a private little header file here that does the
+minimal typedefs that we need. */
+# include "stdint_minimal.h"
+/* MSVC doesn't have strcasecmp. Use _stricmp instead */
+# define strcasecmp _stricmp
+#endif
+
+typedef struct context{
+ const char *name; /* name of TIFF or PNM file */
+ int wid; /* image width in pixels */
+ int hei; /* image height in pixels */
+ int ncomp; /* num of color components, 1, 3, or 4 */
+ int bpi; /* bits per component, 1..16 */
+ int ycc_bd10_flag; /* flag to distinguish RGB101010 from YCC BD10 formats*/
+ int ycc_format; /* ycc format, 0 (Not Applicable), 1 (YUV420), 2 (YUV422), 3 (YUV444)*/
+ short sf; /* sample format, 1 (UINT), 2 (FixedPoint), 3 (float) or 4 (RGBE)*/
+ int format; /* component format code 0..15 */
+ unsigned swap : 1; /* byte swapping required ? */
+ FILE *file; /* input or output file pointer */
+ void *buf; /* source or destination data buffer */
+ int my; /* last MB strip (of 16 lines) read, init to -1 */
+ int nstrips; /* num of TIFF strips, 0 for PNM */
+ int strip; /* index of the current TIFF strip, 0 for PNM */
+ int nlines; /* num of lines per TIFF strip, height for PNM */
+ int line; /* index of current line in current strip */
+ short photometric; /* PhotometricInterpretation:
+ WhiteIsZero 0
+ BlackIsZero 1
+ RGB 2
+ RGB Palette 3
+ Transparency mask 4
+ CMYK 5
+ YCbCr 6
+ CIELab 8
+ */
+ uint32_t offoff; /* offset in TIFF file of StripOffsets ifd entry*/
+ int padBytes;
+ int alpha; /* with alpha channel */
+ unsigned int isBgr;
+ int top_pad;
+ int top_pad_remaining;
+ int left_pad;
+}context;
+
+static void error(char *format,...)
+{
+ va_list args;
+ fprintf(stderr, "Error: ");
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ abort();
+}
+
+/* YCC/CMYKDIRECT format tests */
+
+unsigned int isOutputYUV444(jxr_image_t image)
+{
+ switch (jxr_get_pixel_format(image))
+ {
+ case JXRC_FMT_24bppYCC444:
+ case JXRC_FMT_30bppYCC444:
+ case JXRC_FMT_48bppYCC444:
+ case JXRC_FMT_48bppYCC444FixedPoint:
+ case JXRC_FMT_32bppYCC444Alpha:
+ case JXRC_FMT_40bppYCC444Alpha:
+ case JXRC_FMT_64bppYCC444Alpha:
+ case JXRC_FMT_64bppYCC444AlphaFixedPoint:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+unsigned int isOutputYUV422(jxr_image_t image)
+{
+ switch (jxr_get_pixel_format(image))
+ {
+ case JXRC_FMT_16bppYCC422:
+ case JXRC_FMT_20bppYCC422:
+ case JXRC_FMT_32bppYCC422:
+ case JXRC_FMT_24bppYCC422Alpha:
+ case JXRC_FMT_30bppYCC422Alpha:
+ case JXRC_FMT_48bppYCC422Alpha:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+unsigned int isOutputYUV420(jxr_image_t image)
+{
+ switch (jxr_get_pixel_format(image))
+ {
+ case JXRC_FMT_12bppYCC420:
+ case JXRC_FMT_20bppYCC420Alpha:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+unsigned int isOutputCMYKDirect(jxr_image_t image)
+{
+ switch (jxr_get_pixel_format(image))
+ {
+ case JXRC_FMT_32bppCMYKDIRECT:
+ case JXRC_FMT_64bppCMYKDIRECT:
+ case JXRC_FMT_40bppCMYKDIRECTAlpha:
+ case JXRC_FMT_80bppCMYKDIRECTAlpha:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/* File Reading Primitives: */
+
+static void read_data(context *con, void *buf, int size, int count)
+{
+ size_t rc = fread(buf, size, count, con->file);
+ if (rc!=count)
+ error("premature EOF in input file %s", con->name);
+}
+
+static inline void read_uint8(context *con, uint8_t *buf, int count)
+{
+ read_data(con, buf, 1, count);
+}
+
+static void read_uint16(context *con, uint16_t *buf, int count)
+{
+ read_data(con, buf, 2, count);
+ if (con->swap) {
+ uint8_t *p, *plim, t;
+ for (p=(uint8_t*)buf, plim=p+count*2; p<plim; p+=2)
+ t=p[0], p[0]=p[1], p[1]=t;
+ }
+}
+
+static void read_uint32(context *con, uint32_t *buf, int count)
+{
+ read_data(con, buf, 4, count);
+ if (con->swap) {
+ uint8_t *p, *plim, t;
+ for (p=(uint8_t*)buf, plim=p+count*4; p<plim; p+=4)
+ t=p[0], p[0]=p[3], p[3]=t, t=p[1], p[1]=p[2], p[2]=t;
+ }
+}
+
+static inline uint8_t get_uint8(context *con)
+{
+ uint8_t c;
+ read_uint8(con, &c, 1);
+ return c;
+}
+
+static inline uint16_t get_uint16(context *con)
+{
+ uint16_t c;
+ read_uint16(con, &c, 1);
+ return c;
+}
+
+static inline uint32_t get_uint32(context *con)
+{
+ uint32_t c;
+ read_uint32(con, &c, 1);
+ return c;
+}
+
+static void seek_file(context *con, long offset, int whence)
+{
+ int rc = fseek(con->file, offset, whence);
+ if (rc!=0)
+ error("cannot seek to desired offset in input file %s", con->name);
+}
+
+/* File Writing Primitives: */
+
+static void write_data(context *con, const void *buf, int size, int count)
+{
+ size_t rc = fwrite(buf, size, count, con->file);
+ if (rc!=count)
+ error("unable to write to output file %s", con->name);
+}
+
+static inline void write_uint8(context *con, const uint8_t *buf, int count)
+{
+ write_data(con, buf, 1, count);
+}
+
+static void write_uint16(context *con, uint16_t *buf, int count)
+{
+ if (con->swap) { /* destructive ! */
+ char *p, *plim, t;
+ for (p=(char*)buf, plim=p+count*2; p<plim; p+=2)
+ t=p[0], p[0]=p[1], p[1]=t;
+ }
+ write_data(con, buf, 2, count);
+}
+
+static void write_uint32(context *con, uint32_t *buf, int count)
+{
+ if (con->swap) { /* destructive ! */
+ char *p, *plim, t;
+ for (p=(char*)buf, plim=p+count*4; p<plim; p+=4)
+ t=p[0], p[0]=p[3], p[3]=t, t=p[1], p[1]=p[2], p[2]=t;
+ }
+ write_data(con, buf, 4, count);
+}
+
+static inline void put_uint8(context *con, const uint8_t value)
+{
+ write_uint8(con, &value, 1);
+}
+
+static inline void put_uint16(context *con, const uint16_t value)
+{
+ uint16_t buf = value;
+ write_uint16(con, &buf, 1);
+}
+
+static inline void put_uint32(context *con, const uint32_t value)
+{
+ uint32_t buf = value;
+ write_uint32(con, &buf, 1);
+}
+
+/* PNM File Header Operations: */
+
+static unsigned read_pnm_number(context *con)
+{
+ int c;
+ unsigned n=0;
+
+ while (1) {
+ c = get_uint8(con);
+ if (c=='#')
+ while (get_uint8(con)!='\n');
+ else if (isdigit(c)) break;
+ else if (!isspace(c))
+ error("unexpected character 0x%02x (%c) found in PNM file %s", c, c, con->name);
+ }
+ do {
+ n = 10*n+c-'0';
+ c = get_uint8(con);
+ }
+ while (isdigit(c));
+ if (!isspace(c))
+ error("unexpected character 0x%02x (%c) following max value in PNM file %s", c, c, con->name);
+ return n;
+}
+
+static void open_pnm_input_file(context *con)
+{
+ int c, max, one=1;
+
+ rewind(con->file);
+ c=get_uint8(con);
+ if (c!='P')
+ error("unexpected character 0x%02x (%c) at start of PNM file %s", c, c, con->name);
+ switch (c=get_uint8(con)) {
+ case '1' :
+ case '2' :
+ case '3' :
+ case '4' : error("unsupported PNM file type P%c in PNM file %s", c, con->name);
+ case '5' : con->ncomp = 1; break;
+ case '6' : con->ncomp = 3; break;
+ default : error("unexpected character 0x%02x (%c) following 'P' in PNM file %s", c, c, con->name);
+ }
+
+ con->wid = read_pnm_number(con);
+ if (con->wid<=0)
+ error("invalid image width %d in PNM file %s",con->wid, con->name);
+ con->hei = read_pnm_number(con);
+ if (con->hei<=0)
+ error("invalid image height %d in PNM file %s", con->hei, con->name);
+ max=read_pnm_number(con);
+ if (max>=0x10000)
+ error("invalid maximum value 0x%02x (%d) in PNM file %s", max, max, con->name);
+ if (max<0x100) con->swap = 0;
+ else con->swap = *(char*)&one==1;
+ for (con->bpi=1; max>(1<<con->bpi); con->bpi++);
+
+ con->nlines = con->hei;
+}
+
+static void start_pnm_output_file(context *con)
+{
+ int max, one=1;
+ con->file = fopen(con->name, "wb");
+ if (con->file==0)
+ error("cannot create PNM output file %s",con->name);
+ max = (1<<con->bpi)-1;
+ if (max<256) con->swap = 0;
+ else con->swap = *(char*)&one==1;
+ fprintf(con->file, "P%c\n%d %d\n%d\n", con->ncomp==1?'5':'6', con->wid, con->hei, max);
+}
+
+/* TIFF File Header Operations: */
+
+#define ImageWidth 256
+#define ImageLength 257
+#define BitsPerSample 258
+#define Compression 259
+#define Photometric 262
+#define StripOffsets 273
+#define SamplesPerPixel 277
+#define RowsPerStrip 278
+#define StripByteCounts 279
+#define SampleFormat 339
+#define InkSet 332
+
+static void read_tif_ifd_entry(context *con, uint32_t ifdoff, uint16_t *tag, uint16_t *type, uint32_t *count)
+{
+ seek_file(con, ifdoff, SEEK_SET);
+ read_uint16(con, tag, 1);
+ read_uint16(con, type, 1);
+ read_uint32(con, count, 1);
+}
+
+static void read_tif_data(context *con, uint16_t type, uint32_t count, int index, int nval, void *buf)
+{
+ int size=0;
+
+ switch (type) {
+ case 3 : size = 2; break;
+ case 4 : size = 4; break;
+ default : return;
+ }
+
+ if (index+nval>(int)count)
+ error("data array is to small for read request in TIFF file %s", con->name);
+
+ index *= size;
+ size *= count;
+ uint32_t offset = ftell(con->file);
+ if (size>4)
+ read_uint32(con, &offset, 1);
+ seek_file(con, offset+index, SEEK_SET);
+ switch (type) {
+ case 3 : read_uint16(con, (uint16_t*)buf, nval); break;
+ case 4 : read_uint32(con, (uint32_t*)buf, nval);
+ }
+}
+
+static uint32_t read_tif_datum(context *con, uint16_t type, uint32_t count, int index)
+{
+ uint8_t buf[4];
+
+ read_tif_data(con, type, count, index, 1, buf);
+ switch (type) {
+ case 3 : return (uint32_t)*(uint16_t*)buf;
+ case 4 : return (uint32_t)*(uint32_t*)buf;
+ default : return 0;
+ }
+}
+
+static uint32_t get_tif_datum(context *con, uint32_t ifdoff, int index)
+{
+ uint16_t tag, type;
+ uint32_t count;
+
+ read_tif_ifd_entry(con, ifdoff, &tag, &type, &count);
+ return read_tif_datum(con, type, count, index);
+}
+
+static void open_tif_input_file(context *con)
+{
+ int i, one=1;
+ uint16_t magic, nentry, tag, type;
+ uint32_t count, diroff;
+
+ rewind(con->file);
+ read_uint16(con, &magic, 1);
+ switch (magic) {
+ case 0x4949 : con->swap = *(char*)&one!=1; break;
+ case 0x4d4d : con->swap = *(char*)&one==1; break;
+ default : error("bad magic number 0x%04x found at start of TIFF file %s", magic, con->name);
+ }
+ read_uint16(con, &magic, 1);
+ if (magic!=42)
+ error("magic number 42 not found in TIFF file %s", con->name);
+ read_uint32(con, &diroff, 1);
+
+ seek_file(con, diroff, SEEK_SET);
+ read_uint16(con, &nentry, 1);
+ for (i=0; i<nentry; i++) {
+ int ifdoff = diroff+2+12*i;
+ read_tif_ifd_entry(con, ifdoff, &tag, &type, &count);
+ uint32_t data = read_tif_datum(con, type, count, 0);
+ switch (tag) {
+ case ImageWidth:
+ con->wid = data;
+ break;
+ case ImageLength:
+ con->hei = data;
+ break;
+ case BitsPerSample:
+ con->bpi = data;
+ break;
+ case SamplesPerPixel:
+ con->ncomp = data;
+ break;
+ case Compression:
+ if (data!=1)
+ error("TIFF input file %s is compressed", con->name);
+ break;
+ case StripOffsets:
+ con->nstrips = count;
+ con->offoff = ifdoff;
+ break;
+ case RowsPerStrip:
+ con->nlines = data;
+ break;
+ case SampleFormat:
+ con->sf = data;
+ break;
+ case Photometric:
+ con->photometric = data;
+ break;
+
+ }
+ }
+
+ if (con->wid<=0)
+ error("valid ImageWidth entry not found in directory of TIFF file %s", con->name);
+ if (con->hei<=0)
+ error("valid ImageLength entry not found in directory of TIFF file %s", con->name);
+ if (con->ncomp!=1 && con->ncomp!=3 && con->ncomp!=4 && con->ncomp!=5)
+ error("valid SamplesPerPixel entry (1, 3, 4, or 5) not found in directory of TIFF file %s", con->name);
+ if (con->bpi>32)
+ error("valid BitsPerSample entry not found in directory of TIFF file %s", con->name);
+ if (con->nstrips<=0 || con->offoff==0)
+ error("valid StripOffsets entry not found in directory of TIFF file %s", con->name);
+ if (con->nlines<=0)
+ error("valid RowsPerStrip entry not found in directory of TIFF file %s", con->name);
+ con->line = con->nlines;
+}
+
+
+static void put_ifd_entry(context *con, int tag, int type, int count, uint32_t offset)
+{
+ put_uint16(con, tag);
+ put_uint16(con, type);
+ put_uint32(con, count);
+ if (type==3 && count==1) {
+ put_uint16(con, offset);
+ put_uint16(con, 0);
+ }
+ else put_uint32(con, offset);
+}
+
+unsigned int validate_tif_output(jxrc_t_pixelFormat ePixelFormat)
+{
+ switch(ePixelFormat)
+ {
+ case JXRC_FMT_24bppRGB:return 1;
+ case JXRC_FMT_24bppBGR: return 0;
+ case JXRC_FMT_32bppBGR:return 0;
+ case JXRC_FMT_48bppRGB:return 1;
+ case JXRC_FMT_48bppRGBFixedPoint: return 1;
+ case JXRC_FMT_48bppRGBHalf: return 1;
+ case JXRC_FMT_96bppRGBFixedPoint:return 1;
+ case JXRC_FMT_64bppRGBFixedPoint:return 1;
+ case JXRC_FMT_64bppRGBHalf:return 1;
+ case JXRC_FMT_128bppRGBFixedPoint:return 1;
+ case JXRC_FMT_128bppRGBFloat:return 1;
+ case JXRC_FMT_32bppBGRA:return 0;
+ case JXRC_FMT_64bppRGBA:return 1;
+ case JXRC_FMT_64bppRGBAFixedPoint:return 1;
+ case JXRC_FMT_64bppRGBAHalf:return 1;
+ case JXRC_FMT_128bppRGBAFixedPoint:return 1;
+ case JXRC_FMT_128bppRGBAFloat:return 1;
+ case JXRC_FMT_32bppPBGRA:return 0;
+ case JXRC_FMT_64bppPRGBA:return 0;
+ case JXRC_FMT_128bppPRGBAFloat:return 0;
+ case JXRC_FMT_32bppCMYK:return 1;
+ case JXRC_FMT_40bppCMYKAlpha:return 1;
+ case JXRC_FMT_64bppCMYK:return 1;
+ case JXRC_FMT_80bppCMYKAlpha:return 1;
+ case JXRC_FMT_24bpp3Channels:return 0;
+ case JXRC_FMT_32bpp4Channels:return 0;
+ case JXRC_FMT_40bpp5Channels:return 0;
+ case JXRC_FMT_48bpp6Channels:return 0;
+ case JXRC_FMT_56bpp7Channels:return 0;
+ case JXRC_FMT_64bpp8Channels:return 0;
+ case JXRC_FMT_32bpp3ChannelsAlpha:return 0;
+ case JXRC_FMT_40bpp4ChannelsAlpha:return 0;
+ case JXRC_FMT_48bpp5ChannelsAlpha:return 0;
+ case JXRC_FMT_56bpp6ChannelsAlpha:return 0;
+ case JXRC_FMT_64bpp7ChannelsAlpha:return 0;
+ case JXRC_FMT_72bpp8ChannelsAlpha:return 0;
+ case JXRC_FMT_48bpp3Channels:return 0;
+ case JXRC_FMT_64bpp4Channels:return 0;
+ case JXRC_FMT_80bpp5Channels:return 0;
+ case JXRC_FMT_96bpp6Channels:return 0;
+ case JXRC_FMT_112bpp7Channels:return 0;
+ case JXRC_FMT_128bpp8Channels:return 0;
+ case JXRC_FMT_64bpp3ChannelsAlpha:return 0;
+ case JXRC_FMT_80bpp4ChannelsAlpha:return 0;
+ case JXRC_FMT_96bpp5ChannelsAlpha:return 0;
+ case JXRC_FMT_112bpp6ChannelsAlpha:return 0;
+ case JXRC_FMT_128bpp7ChannelsAlpha:return 0;
+ case JXRC_FMT_144bpp8ChannelsAlpha:return 0;
+ case JXRC_FMT_8bppGray:return 1;
+ case JXRC_FMT_16bppGray:return 1;
+ case JXRC_FMT_16bppGrayFixedPoint:return 1;
+ case JXRC_FMT_16bppGrayHalf:return 1;
+ case JXRC_FMT_32bppGrayFixedPoint:return 1;
+ case JXRC_FMT_32bppGrayFloat:return 1;
+ case JXRC_FMT_BlackWhite:return 1;
+ case JXRC_FMT_16bppBGR555:return 0;
+ case JXRC_FMT_16bppBGR565:return 0;
+ case JXRC_FMT_32bppBGR101010:return 0;
+ case JXRC_FMT_32bppRGBE:return 0;
+ case JXRC_FMT_32bppCMYKDIRECT:return 0;
+ case JXRC_FMT_64bppCMYKDIRECT:return 0;
+ case JXRC_FMT_40bppCMYKDIRECTAlpha:return 0;
+ case JXRC_FMT_80bppCMYKDIRECTAlpha:return 0;
+ case JXRC_FMT_12bppYCC420:return 0;
+ case JXRC_FMT_16bppYCC422:return 0;
+ case JXRC_FMT_20bppYCC422:return 0;
+ case JXRC_FMT_32bppYCC422:return 0;
+ case JXRC_FMT_24bppYCC444:return 0;
+ case JXRC_FMT_30bppYCC444:return 0;
+ case JXRC_FMT_48bppYCC444:return 0;
+ case JXRC_FMT_48bppYCC444FixedPoint:return 0;
+ case JXRC_FMT_20bppYCC420Alpha:return 0;
+ case JXRC_FMT_24bppYCC422Alpha:return 0;
+ case JXRC_FMT_30bppYCC422Alpha:return 0;
+ case JXRC_FMT_48bppYCC422Alpha:return 0;
+ case JXRC_FMT_32bppYCC444Alpha:return 0;
+ case JXRC_FMT_40bppYCC444Alpha:return 0;
+ case JXRC_FMT_64bppYCC444Alpha:return 0;
+ case JXRC_FMT_64bppYCC444AlphaFixedPoint:return 0;
+ default: return 0;
+ }
+}
+unsigned int validate_pnm_output(jxrc_t_pixelFormat ePixelFormat)
+{
+ switch(ePixelFormat)
+ {
+ case JXRC_FMT_24bppRGB:return 1;
+ case JXRC_FMT_8bppGray:return 1;
+ default: return 0;
+ }
+}
+
+static void start_tif_output_file(context *con)
+{
+ con->file = fopen(con->name, "wb");
+ if (con->file==0)
+ error("cannot create TIFF output file %s", con->name);
+ con->swap = 0;
+
+ int one = 1;
+ char magic = *(char*)&one==1 ? 'I' : 'M';
+ int nentry = 10;
+ if (con->ncomp == 4 && !con->alpha) /* CMYK */
+ nentry += 1;
+ int bitsize = con->ncomp>=3 ? 2*con->ncomp : 0;
+ int bitoff = 8 + 2 + 12*nentry + 4;
+ int datoff = bitoff + bitsize;
+
+ put_uint8(con, magic);
+ put_uint8(con, magic);
+ put_uint16(con, 42);
+ put_uint32(con, 8);
+ put_uint16(con, nentry);
+ put_ifd_entry(con, ImageWidth, 4, 1, con->wid);
+ put_ifd_entry(con, ImageLength, 4, 1, con->hei);
+ put_ifd_entry(con, BitsPerSample, 3, con->ncomp, con->ncomp>=3 ? bitoff : con->bpi);
+ switch (con->format)
+ {
+ case 0: /* BD1WHITE1*/
+ case 1: /* BD8 */
+ case 2: /* BD16 */
+ /* case 5: Reserved */
+ case 8: /* BD5 */
+ case 9: /* BD10 */
+ case 15: /* BD1BLACK1 */
+ con->sf = 1;
+ break;
+ case 3: /* BD16S */
+ case 6: /* BD32S */
+ con->sf = 2;
+ break;
+ case 4: /* BD16F */
+ case 7: /* BD32F */
+ con->sf = 3;
+ break;
+ default:
+ assert(0);
+ }
+ put_ifd_entry(con, SampleFormat, 3, 1, con->sf);
+ put_ifd_entry(con, Compression, 3, 1, 1);
+ put_ifd_entry(con, Photometric, 3, 1, con->photometric);
+ put_ifd_entry(con, StripOffsets, 4, 1, datoff);
+ if(!con->padBytes)
+ put_ifd_entry(con, SamplesPerPixel, 3, 1, con->ncomp);
+ else
+ put_ifd_entry(con, SamplesPerPixel, 3, 1, con->ncomp + 1);
+
+ put_ifd_entry(con, RowsPerStrip, 4, 1, con->hei);
+ if(con->bpi == 1)
+ put_ifd_entry(con, StripByteCounts, 4, 1, ((con->wid+7)>>3) * con->hei * con->ncomp);
+ else if(!con->padBytes)
+ put_ifd_entry(con, StripByteCounts, 4, 1, con->wid * con->hei * con->ncomp * ((con->bpi+7)/8));
+ else
+ put_ifd_entry(con, StripByteCounts, 4, 1, con->wid * con->hei * (con->ncomp + 1)* ((con->bpi+7)/8));
+
+ if (con->ncomp == 4 && !con->alpha)
+ put_ifd_entry(con, InkSet, 3, 1, 1);
+
+ put_uint32(con, 0);
+ assert(ftell(con->file)==bitoff);
+ if (con->ncomp>=3) {
+ int i;
+ for (i=0; i<con->ncomp; i++)
+ put_uint16(con, con->bpi);
+ }
+ assert(ftell(con->file)==datoff);
+}
+
+static void start_raw_output_file(context *con)
+{
+ con->file = fopen(con->name, "w+b");
+ if (con->file==0)
+ error("cannot create RAW output file %s", con->name);
+ con->swap = 0;
+}
+
+/* Generic File Header Operations: */
+
+void *open_input_file(const char *name, const raw_info *raw_info_t, int *alpha_mode, int *padded_format)
+{
+ context *con;
+
+ con = (context*)malloc(sizeof(context));
+ if (con==0)
+ error("unable to allocate memory");
+
+ con->name = name;
+ con->wid = 0;
+ con->hei = 0;
+ con->ncomp = 0;
+ con->bpi = 0;
+ con->format = 0;
+ con->sf = 1;
+ con->swap = 0;
+ con->buf = 0;
+ con->my = -1;
+ con->nstrips = 0;
+ con->strip = 0;
+ con->nlines = 0;
+ con->line = 0;
+ con->photometric = 0;
+ con->offoff = 0;
+ con->ycc_bd10_flag = 0;
+ con->ycc_format = 0;
+
+ con->file = fopen(name, "rb");
+ if (con->file==0)
+ error("cannot find input file %s", name);
+
+ if (!raw_info_t->is_raw) {
+ switch (get_uint8(con)) {
+ case 'P' : open_pnm_input_file(con); break;
+ case 'I' :
+ case 'M' : open_tif_input_file(con); break;
+ default : error("format of input file %s is unrecognized", name);
+ }
+
+ con->padBytes = 0;
+ if(con->photometric == 2 && con->ncomp == 4) /* RGBA */
+ if( *padded_format == 1) { /* for RGB_NULL, there is a padding channel */
+ con->padBytes = 1;
+ con->ncomp --;
+ if(*alpha_mode != 0)
+ {
+ *alpha_mode = 0; /* Turn off alpha mode */
+ fprintf(stderr, "Setting alpha_mode to 0 to encode a padded format \n");
+ }
+ }
+ else
+ {
+ if(*alpha_mode == 0)
+ {
+ *alpha_mode = 2; /* Turn on separate alpha */
+ }
+ }
+ }
+ else { /* raw input */
+ con->wid = raw_info_t->raw_width;
+ con->hei = raw_info_t->raw_height;
+ con->nlines = con->hei;
+ con->bpi = raw_info_t->raw_bpc;
+ con->sf = 1; /* UINT */
+ con->padBytes = 0;
+ if (con->bpi == 10 && raw_info_t->raw_format > 18) {
+ con->ycc_bd10_flag = 1;
+ con->bpi = 16;
+ }
+
+ if ((raw_info_t->raw_format >= 3) && (raw_info_t->raw_format <= 8)) { /* N-channel */
+ con->ncomp = raw_info_t->raw_format;
+ }
+ else if ((raw_info_t->raw_format >= 9) && (raw_info_t->raw_format <= 14)) { /* N-channel with Alpha */
+ con->ncomp = raw_info_t->raw_format - 5;
+ }
+ else if (15 == raw_info_t->raw_format) {/* RGBE */
+ con->ncomp = 4;
+ con->sf = 4;
+ }
+ else if (16 == raw_info_t->raw_format) {/* 555 */
+ con->ncomp = 3;
+ con->bpi = 5;
+ }
+ else if (17 == raw_info_t->raw_format) {/* 565 */
+ con->ncomp = 3;
+ con->bpi = 6;
+ }
+ else if (18 == raw_info_t->raw_format) {/* 101010 */
+ con->ncomp = 3;
+ con->bpi = 10;
+ }
+ else if (19 == raw_info_t->raw_format) {
+ con->ncomp = 3;
+ con->ycc_format = 1;
+ }
+ else if (20 == raw_info_t->raw_format) {
+ con->ncomp = 3;
+ con->ycc_format = 2;
+ }
+ else if (21 == raw_info_t->raw_format) {
+ con->ncomp = 3;
+ con->ycc_format = 3;
+ }
+ else if (22 == raw_info_t->raw_format) {
+ con->ncomp = 3;
+ con->sf = 2; /* SINT */
+ con->ycc_format = 3;
+ }
+ else if (23 == raw_info_t->raw_format) {
+ con->ncomp = 4;
+ con->ycc_format = 1;
+ }
+ else if (24 == raw_info_t->raw_format) {
+ con->ncomp = 4;
+ con->ycc_format = 2;
+ }
+ else if (25 == raw_info_t->raw_format) {
+ con->ncomp = 4;
+ con->ycc_format = 3;
+ }
+ else if (26 == raw_info_t->raw_format) {
+ con->ncomp = 4;
+ con->sf = 2; /* SINT */
+ con->ycc_format = 3;
+ }
+ else if (27 == raw_info_t->raw_format) {
+ con->ncomp = 4;
+ }
+ else if (28 == raw_info_t->raw_format) {
+ con->ncomp = 5;
+ }
+ else if(29 == raw_info_t->raw_format) {/* 24bppBGR */
+ con->ncomp = 3;
+ con->bpi = 8;
+ }
+ else if(30 == raw_info_t->raw_format) {/* 32bppBGR */
+ con->ncomp = 3;
+ con->bpi = 8;
+ con->padBytes = 1;
+ *padded_format = 1;
+ }
+ else if(31 == raw_info_t->raw_format) {/* 32bppBGRA */
+ con->ncomp = 4;
+ con->bpi = 8;
+ }
+ else if(32 == raw_info_t->raw_format) {/* 32bppPBGRA */
+ con->ncomp = 4;
+ con->bpi = 8;
+ }
+ else if(33 == raw_info_t->raw_format) {/* 64bppPRGBA */
+ con->ncomp = 4;
+ con->bpi = 16;
+ }
+ else if(34 == raw_info_t->raw_format) {/* 128bppPRGBAFloat */
+ con->ncomp = 4;
+ con->bpi = 32;
+ con->sf = 3;
+ con->photometric = 2;
+ }
+ }
+
+ if(con->padBytes == 0 && *padded_format)
+ {
+ *padded_format = 0;
+ fprintf(stderr, "Ignoring -p option from command line \n");
+ }
+
+ size_t strip_bytes;
+ if (con->ycc_format == 1)
+ strip_bytes = 8 * ((4*con->ncomp-6) + con->padBytes) * ((con->bpi+7)/8) * ((con->wid+15)&~15)/2;
+ else if (con->ycc_format == 2)
+ strip_bytes = 16 * ((2*con->ncomp-2) + con->padBytes) * ((con->bpi+7)/8) * ((con->wid+15)&~15)/2;
+ else
+ strip_bytes = 16 * (con->ncomp + con->padBytes) * ((con->bpi+7)/8) * ((con->wid+15)&~15);
+
+ if (con->bpi == 1)
+ strip_bytes >>= 3;
+ else if ((con->bpi == 5) || (con->bpi == 6) || (con->bpi == 10 && !con->ycc_bd10_flag))
+ strip_bytes = (strip_bytes << 1) / 3; /* external buffer */
+
+ con->buf = calloc(strip_bytes, 1);
+ if (con->buf==0)
+ error("cannot allocate memory");
+
+ return con;
+}
+void set_ncomp(void *input_handle, int ncomp)
+{
+ context *con = (context *)input_handle;
+ con->ncomp = ncomp;
+}
+
+void *open_output_file(const char *name)
+{
+ context *con = (context*)malloc(sizeof(context));
+ if (con==0)
+ error("unable to allocate memory");
+ con->file = 0;
+ con->name = name;
+ con->wid = 0;
+ con->hei = 0;
+ con->ncomp = 0;
+ con->bpi = 0;
+ con->format = 0;
+ con->swap = 0;
+ con->buf = 0;
+ return con;
+}
+
+void close_file(void *handle)
+{
+ if(handle == NULL)
+ return;
+ context *con = (context*)handle;
+ if (con->file) fclose(con->file);
+ if (con->buf) free(con->buf);
+ free(con);
+}
+
+void get_file_parameters(void *handle, int *wid, int *hei, int *ncomp, int *bpi, short *sf, short *photometric, int *padBytes)
+{
+ context *con = (context*)handle;
+ if (wid) *wid = con->wid;
+ if (hei) *hei = con->hei;
+ if (ncomp) *ncomp = con->ncomp;
+ if (bpi) *bpi = con->bpi;
+ if (sf) *sf = con->sf;
+ if (photometric) *photometric = con->photometric;
+ if (padBytes) *padBytes = con->padBytes;
+}
+
+void set_photometric_interp(context *con, jxrc_t_pixelFormat pixelFormat)
+{
+ switch(pixelFormat)
+ {
+ case JXRC_FMT_32bppCMYK:
+ case JXRC_FMT_40bppCMYKAlpha:
+ case JXRC_FMT_64bppCMYK:
+ case JXRC_FMT_80bppCMYKAlpha:
+ con->photometric = 5;
+ return;
+ case JXRC_FMT_8bppGray:
+ case JXRC_FMT_16bppGray:
+ case JXRC_FMT_16bppGrayFixedPoint:
+ case JXRC_FMT_16bppGrayHalf:
+ case JXRC_FMT_32bppGrayFixedPoint:
+ case JXRC_FMT_32bppGrayFloat:
+ case JXRC_FMT_BlackWhite:
+ con->photometric = 1;
+ return;
+ default:
+ con->photometric = 2;
+ return;
+ }
+}
+
+static void start_output_file(context *con, int ext_width, int ext_height, int width, int height, int ncomp, int format, jxrc_t_pixelFormat pixelFormat)
+{
+ int bpi=0;
+ switch (format) {
+ case 0 : bpi=1; break;
+ case 1 : bpi=8; break;
+ case 2 :
+ case 3 :
+ case 4 : bpi=16; break;
+ case 5 :
+ case 6 :
+ case 7 : bpi=32; break;
+ case 8 : bpi=5; break;
+ case 9 : bpi=10; break;
+ case 10 : bpi=6; break;
+ case 15 : bpi=1; break;
+ default : error("invalid component format code (%d) for output file %s", format, con->name);
+ }
+
+ if (bpi<1 || bpi>32)
+ error("invalid bits per sample (%d) for output file %s", bpi, con->name);
+ if (width<=0 || height<=0)
+ error("invalid dimensions (%d X %d) for output file %s", width, height, con->name);
+
+ con->wid = width;
+ con->hei = height;
+ con->ncomp = ncomp;
+ con->bpi = bpi;
+ con->format = format;
+ /* Add one extra component for possible padding channel */
+ con->buf = malloc(((ext_width)/16) * 256 * (ncomp + 1) * ((con->bpi+7)/8));
+ if (con->buf==0) error("unable to allocate memory");
+
+ const char *p = strrchr(con->name, '.');
+ if (p==0)
+ error("output file name %s needs a suffix to determine its format", con->name);
+ if (!strcasecmp(p, ".pnm") || !strcasecmp(p, ".pgm") || !strcasecmp(p, ".ppm"))
+ {
+ if(!validate_pnm_output(pixelFormat))
+ {
+ printf("User error: PixelFormat is incompatible with pnm output, use .raw or .tif extension for output file\n");
+ assert(0);
+ }
+ start_pnm_output_file(con);
+ }
+ else if (!strcasecmp(p, ".tif"))
+ {
+ if(!validate_tif_output(pixelFormat) && ncomp != 1)
+ {
+ printf("User error: PixelFormat is incompatible with tif output, use .raw extension for output file\n");
+ assert(0);
+ }
+ set_photometric_interp(con, pixelFormat);
+ start_tif_output_file(con);
+ }
+ else if (!strcasecmp(p, ".raw"))
+ start_raw_output_file(con);
+ else error("unrecognized suffix on output file name %s", con->name);
+}
+
+/* File Read and Write Operations: */
+
+static int PreScalingBD16F(int hHalf)
+{
+ int s;
+ s = (hHalf >> 31);
+ hHalf = ((hHalf & 0x7fff) ^ s) - s;
+ return hHalf;
+}
+
+static int PreScalingBD32F(int f, const char _c, const unsigned char _lm)
+{
+ int _h, e, e1, m, s;
+
+ if (f == 0)
+ {
+ _h = 0;
+ }
+ else
+ {
+ e = (f >> 23) & 0x000000ff;/* here set e as e, not s! e includes s: [s e] 9 bits [31..23] */
+ m = (f & 0x007fffff) | 0x800000; /* actual mantissa, with normalizer */
+ if (e == 0) { /* denormal-land */
+ m ^= 0x800000; /* actual mantissa, removing normalizer */
+ e++; /* actual exponent -126 */
+ }
+
+ e1 = e - 127 + _c; /* this is basically a division or quantization to a different exponent */
+
+ if (e1 <= 1) { /* denormal */
+ if (e1 < 1)
+ m >>= (1 - e1); /* shift mantissa right to make exponent 1 */
+ e1 = 1;
+ if ((m & 0x800000) == 0) /* if denormal, set e1 to zero else to 1 */
+ e1 = 0;
+ }
+ m &= 0x007fffff;
+
+ _h = (e1 << _lm) + ((m + (1 << (23 - _lm - 1))) >> (23 - _lm));/* take 23-bit m, shift (23-lm), get lm-bit m */
+ s = (f >> 31);
+ /* padding to int-32: */
+ _h = (_h ^ s) - s;
+ }
+
+ return _h;
+}
+
+int forwardRGBE (int RGB, int E)
+{
+ int iResult = 0, iAppend = 1;
+
+ if (E == 0)
+ return 0;
+
+ E--;
+ while (((RGB & 0x80) == 0) && (E > 0)) {
+ RGB = (RGB << 1) + iAppend;
+ iAppend = 0;
+ E--;
+ }
+
+ if (E == 0) {
+ iResult = RGB;
+ }
+ else {
+ E++;
+ iResult = (RGB & 0x7f) + (E << 7);
+ }
+
+ return iResult;
+}
+
+void set_pad_bytes(context *con, jxr_image_t image)
+{
+ /* Incomplete: Add padding data for other formats as we go */
+ switch (jxr_get_pixel_format(image))
+ {
+ case JXRC_FMT_128bppRGBFloat:
+ case JXRC_FMT_128bppRGBFixedPoint:
+ con->padBytes = 32;
+ break;
+ case JXRC_FMT_64bppRGBFixedPoint:
+ case JXRC_FMT_64bppRGBHalf:
+ con->padBytes = 16;
+ break;
+ case JXRC_FMT_32bppBGR:
+ con->padBytes = 8;
+ break;
+ default:
+ con->padBytes = 0;
+ break;
+ }
+
+}
+
+void set_bgr_flag(context *con, jxr_image_t image)
+{
+ con->isBgr = 0;
+ switch (jxr_get_pixel_format(image))
+ {
+ case JXRC_FMT_24bppBGR:
+ case JXRC_FMT_32bppBGR:
+ case JXRC_FMT_32bppBGRA:
+ case JXRC_FMT_32bppPBGRA:
+ con->isBgr = 1;
+ break;
+ default:
+ break;
+ }
+ return;
+}
+
+void switch_r_b(void *data, int bpi)
+{
+ uint32_t tmp;
+ data = (uint8_t*)data;
+ if(bpi == 8)
+ {
+ uint8_t *p = (uint8_t*)data;
+ tmp = p[0];
+ p[0] = p[2];
+ p[2] = tmp;
+
+ }
+
+ else if(bpi == 16)
+ {
+ uint16_t *p = (uint16_t*)data;
+ tmp = p[0];
+ p[0] = p[2];
+ p[2] = tmp;
+ }
+ else if(bpi == 32)
+ {
+ uint32_t *p = (uint32_t *)data;
+ tmp = p[0];
+ p[0] = p[2];
+ p[2] = tmp;
+ }
+ else
+ {
+ assert(!"Invalid bpi\n");
+ }
+}
+
+static void read_setup(context *con)
+{
+ if (con->line == con->nlines) {
+ if (con->strip == con->nstrips)
+ error("unexpected end of data encountered in input file %s", con->name);
+ seek_file(con, get_tif_datum(con, con->offoff, con->strip), SEEK_SET);
+ con->strip++;
+ }
+ con->line++;
+}
+
+void read_file_YCC(jxr_image_t image, int mx, int my, int *data) {
+ /* There are 3 or 4 buffers, depending on whether there is an alpha channel or not */
+ context *con = (context*) jxr_get_user_data(image);
+ int num_channels = con->ncomp;
+
+ unsigned int widthY = con->wid, heightY = con->hei;
+ unsigned int widthUV = con->wid >> ((con->ycc_format == 1 || con->ycc_format == 2) ? 1 : 0);
+ unsigned int heightUV = con->hei >> (con->ycc_format == 1 ? 1 : 0);
+ unsigned int MBheightY = 16;
+ unsigned int MBheightUV = con->ycc_format == 1 ? 8 : 16;
+ unsigned int sizeY = widthY * heightY;
+ unsigned int sizeUV = widthUV * heightUV;
+
+ if (my != con->my) {
+ if (con->bpi == 8) {
+ unsigned int offsetY = my * MBheightY * widthY;
+ unsigned int offsetU = sizeY + my * MBheightUV * widthUV;
+ unsigned int offsetV = sizeY + sizeUV + my * MBheightUV * widthUV;
+ unsigned int offsetA = sizeY + 2 * sizeUV + my * MBheightY * widthY;
+
+ uint8_t *sp = (uint8_t*)con->buf;
+
+ seek_file(con, offsetY, SEEK_SET);
+ memset(sp, 0, widthY * MBheightY);
+ read_data(con, sp, 1, widthY * MBheightY);
+ sp += widthY * MBheightY;
+
+ seek_file(con, offsetU, SEEK_SET);
+ memset(sp, 0, widthUV * MBheightUV);
+ read_data(con, sp, 1, widthUV * MBheightUV);
+ sp += widthUV * MBheightUV;
+
+ seek_file(con, offsetV, SEEK_SET);
+ memset(sp, 0, widthUV * MBheightUV);
+ read_data(con, sp, 1, widthUV * MBheightUV);
+ sp += widthUV * MBheightUV;
+
+ if (con->ncomp == 4) {
+ seek_file(con, offsetA, SEEK_SET);
+ memset(sp, 0, widthY * MBheightY);
+ read_data(con, sp, 1, widthY * MBheightY);
+ sp += widthY * MBheightY;
+ }
+ }
+ else if (con->bpi == 16) {
+ unsigned int offsetY = 2 * (my * MBheightY * widthY);
+ unsigned int offsetU = 2 * (sizeY + my * MBheightUV * widthUV);
+ unsigned int offsetV = 2 * (sizeY + sizeUV + my * MBheightUV * widthUV);
+ unsigned int offsetA = 2 * (sizeY + 2 * sizeUV + my * MBheightY * widthY);
+
+ uint16_t *sp = (uint16_t*)con->buf;
+
+ seek_file(con, offsetY, SEEK_SET);
+ memset(sp, 0, 2 * widthY * MBheightY);
+ read_data(con, sp, 2, widthY * MBheightY);
+ sp += widthY * MBheightY;
+
+ seek_file(con, offsetU, SEEK_SET);
+ memset(sp, 0, 2 * widthUV * MBheightUV);
+ read_data(con, sp, 2, widthUV * MBheightUV);
+ sp += widthUV * MBheightUV;
+
+ seek_file(con, offsetV, SEEK_SET);
+ memset(sp, 0, 2 * widthUV * MBheightUV);
+ read_data(con, sp, 2, widthUV * MBheightUV);
+ sp += widthUV * MBheightUV;
+
+ if (con->ncomp == 4) {
+ seek_file(con, offsetA, SEEK_SET);
+ memset(sp, 0, 2 * widthY * MBheightY);
+ read_data(con, sp, 2, widthY * MBheightY);
+ sp += widthY * MBheightY;
+ }
+ }
+ con->my = my;
+ }
+
+ int idx1, idx2;
+ int xDiv = 16;
+ int yDiv = 16;
+
+ if (con->bpi == 8) {
+ /* Y */
+ uint8_t *sp = (uint8_t*)con->buf + xDiv*mx;
+ for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
+ for (idx2 = 0; idx2 < xDiv; idx2 += 1)
+ data[(idx1 * xDiv + idx2) * num_channels + 0] = sp[idx2];
+ sp += widthY;
+ }
+
+ if (con->ycc_format == 2)
+ xDiv = 8;
+
+ if (con->ycc_format == 1)
+ xDiv = yDiv = 8;
+
+ /* U */
+ sp = (uint8_t*)con->buf + widthY * MBheightY + xDiv*mx;
+ for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
+ for (idx2 = 0; idx2 < xDiv; idx2 += 1)
+ data[(idx1 * xDiv + idx2) * num_channels + 1] = sp[idx2];
+ sp += widthUV;
+ }
+
+ /* V */
+ sp = (uint8_t*)con->buf + widthY * MBheightY + widthUV * MBheightUV + xDiv*mx;
+ for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
+ for (idx2 = 0; idx2 < xDiv; idx2 += 1)
+ data[(idx1 * xDiv + idx2) * num_channels + 2] = sp[idx2];
+ sp += widthUV;
+ }
+
+ if(con->ncomp == 4)
+ {
+ xDiv = yDiv = 16;
+ sp = (uint8_t*)con->buf + widthY * MBheightY + 2 * widthUV * MBheightUV + xDiv*mx;
+ for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
+ for (idx2 = 0; idx2 < xDiv; idx2 += 1)
+ data[(idx1 * xDiv + idx2) * num_channels + 3] = sp[idx2];
+ sp += widthY;
+ }
+ }
+ }
+ else if (con->bpi == 16 || con->bpi == 10) {
+ if (con->sf == 1) {
+ /* Y */
+ uint16_t *sp = (uint16_t*)con->buf + xDiv*mx;
+ for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
+ for (idx2 = 0; idx2 < xDiv; idx2 += 1)
+ data[(idx1 * xDiv + idx2) * num_channels + 0] = sp[idx2];
+ sp += widthY;
+ }
+
+ if (con->ycc_format == 2)
+ xDiv = 8;
+
+ if (con->ycc_format == 1)
+ xDiv = yDiv = 8;
+
+ /* U */
+ sp = (uint16_t*)con->buf + widthY * MBheightY + xDiv*mx;
+ for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
+ for (idx2 = 0; idx2 < xDiv; idx2 += 1)
+ data[(idx1 * xDiv + idx2) * num_channels + 1] = sp[idx2];
+ sp += widthUV;
+ }
+
+ /* V */
+ sp = (uint16_t*)con->buf + widthY * MBheightY + widthUV * MBheightUV + xDiv*mx;
+ for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
+ for (idx2 = 0; idx2 < xDiv; idx2 += 1)
+ data[(idx1 * xDiv + idx2) * num_channels + 2] = sp[idx2];
+ sp += widthUV;
+ }
+
+ if(con->ncomp == 4)
+ {
+ xDiv = yDiv = 16;
+ sp = (uint16_t*)con->buf + widthY * MBheightY + 2 * widthUV * MBheightUV + xDiv*mx;
+ for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
+ for (idx2 = 0; idx2 < xDiv; idx2 += 1)
+ data[(idx1 * xDiv + idx2) * num_channels + 3] = sp[idx2];
+ sp += widthY;
+ }
+ }
+ }
+ else if (con->sf == 2) {
+ /* Y */
+ short *sp = (short*)con->buf + xDiv*mx;
+ for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
+ for (idx2 = 0; idx2 < xDiv; idx2 += 1)
+ data[(idx1 * xDiv + idx2) * num_channels + 0] = sp[idx2];
+ sp += widthY;
+ }
+
+ if (con->ycc_format == 2)
+ xDiv = 8;
+
+ if (con->ycc_format == 1)
+ xDiv = yDiv = 8;
+
+ /* U */
+ sp = (short*)con->buf + widthY * MBheightY + xDiv*mx;
+ for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
+ for (idx2 = 0; idx2 < xDiv; idx2 += 1)
+ data[(idx1 * xDiv + idx2) * num_channels + 1] = sp[idx2];
+ sp += widthUV;
+ }
+
+ /* V */
+ sp = (short*)con->buf + widthY * MBheightY + widthUV * MBheightUV + xDiv*mx;
+ for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
+ for (idx2 = 0; idx2 < xDiv; idx2 += 1)
+ data[(idx1 * xDiv + idx2) * num_channels + 2] = sp[idx2];
+ sp += widthUV;
+ }
+
+ if(con->ncomp == 4)
+ {
+ xDiv = yDiv = 16;
+ sp = (short*)con->buf + widthY * MBheightY + 2 * widthUV * MBheightUV + xDiv*mx;
+ for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
+ for (idx2 = 0; idx2 < xDiv; idx2 += 1)
+ data[(idx1 * xDiv + idx2) * num_channels + 3] = sp[idx2];
+ sp += widthY;
+ }
+ }
+ }
+ }
+}
+
+void read_file_CMYK(jxr_image_t image, int mx, int my, int *data) {
+ /* There are 4 or 5 buffers, depending on whether there is an alpha channel or not */
+ context *con = (context*) jxr_get_user_data(image);
+ int num_channels = con->ncomp;
+
+ unsigned int width = con->wid, height = con->hei;
+ unsigned int MBheight = 16;
+ unsigned int size = width * height;
+
+ if (my != con->my) {
+ if (con->bpi == 8) {
+ unsigned int offsetC = my * MBheight * width + 0 * size;
+ unsigned int offsetM = my * MBheight * width + 1 * size;
+ unsigned int offsetY = my * MBheight * width + 2 * size;
+ unsigned int offsetK = my * MBheight * width + 3 * size;
+ unsigned int offsetA = my * MBheight * width + 4 * size;
+
+ uint8_t *sp = (uint8_t*)con->buf;
+
+ seek_file(con, offsetC, SEEK_SET);
+ memset(sp, 0, width * MBheight);
+ read_data(con, sp, 1, width * MBheight);
+ sp += width * MBheight;
+
+ seek_file(con, offsetM, SEEK_SET);
+ memset(sp, 0, width * MBheight);
+ read_data(con, sp, 1, width * MBheight);
+ sp += width * MBheight;
+
+ seek_file(con, offsetY, SEEK_SET);
+ memset(sp, 0, width * MBheight);
+ read_data(con, sp, 1, width * MBheight);
+ sp += width * MBheight;
+
+ seek_file(con, offsetK, SEEK_SET);
+ memset(sp, 0, width * MBheight);
+ read_data(con, sp, 1, width * MBheight);
+ sp += width * MBheight;
+
+ if (con->ncomp == 5) {
+ seek_file(con, offsetA, SEEK_SET);
+ memset(sp, 0, width * MBheight);
+ read_data(con, sp, 1, width * MBheight);
+ sp += width * MBheight;
+ }
+ }
+ else if (con->bpi == 16) {
+ unsigned int offsetC = 2 * (my * MBheight * width + 0 * size);
+ unsigned int offsetM = 2 * (my * MBheight * width + 1 * size);
+ unsigned int offsetY = 2 * (my * MBheight * width + 2 * size);
+ unsigned int offsetK = 2 * (my * MBheight * width + 3 * size);
+ unsigned int offsetA = 2 * (my * MBheight * width + 4 * size);
+
+ uint16_t *sp = (uint16_t*)con->buf;
+
+ seek_file(con, offsetC, SEEK_SET);
+ memset(sp, 0, 2 * width * MBheight);
+ read_data(con, sp, 2, width * MBheight);
+ sp += width * MBheight;
+
+ seek_file(con, offsetM, SEEK_SET);
+ memset(sp, 0, 2 * width * MBheight);
+ read_data(con, sp, 2, width * MBheight);
+ sp += width * MBheight;
+
+ seek_file(con, offsetY, SEEK_SET);
+ memset(sp, 0, 2 * width * MBheight);
+ read_data(con, sp, 2, width * MBheight);
+ sp += width * MBheight;
+
+ seek_file(con, offsetK, SEEK_SET);
+ memset(sp, 0, 2 * width * MBheight);
+ read_data(con, sp, 2, width * MBheight);
+ sp += width * MBheight;
+
+ if (con->ncomp == 5) {
+ seek_file(con, offsetA, SEEK_SET);
+ memset(sp, 0, 2 * width * MBheight);
+ read_data(con, sp, 2, width * MBheight);
+ sp += width * MBheight;
+ }
+ }
+ con->my = my;
+ }
+
+ int idx1, idx2;
+ int xDiv = 16;
+ int yDiv = 16;
+
+ if (con->bpi == 8) {
+ /* C */
+ uint8_t *sp = (uint8_t*)con->buf + xDiv*mx + 0 * width * MBheight;
+ for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
+ for (idx2 = 0; idx2 < xDiv; idx2 += 1)
+ data[(idx1 * xDiv + idx2) * num_channels + 0] = sp[idx2];
+ sp += width;
+ }
+
+ /* M */
+ sp = (uint8_t*)con->buf + xDiv*mx + 1 * width * MBheight;
+ for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
+ for (idx2 = 0; idx2 < xDiv; idx2 += 1)
+ data[(idx1 * xDiv + idx2) * num_channels + 1] = sp[idx2];
+ sp += width;
+ }
+
+ /* Y */
+ sp = (uint8_t*)con->buf + xDiv*mx + 2 * width * MBheight;
+ for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
+ for (idx2 = 0; idx2 < xDiv; idx2 += 1)
+ data[(idx1 * xDiv + idx2) * num_channels + 2] = sp[idx2];
+ sp += width;
+ }
+
+ /* K */
+ sp = (uint8_t*)con->buf + xDiv*mx + 3 * width * MBheight;
+ for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
+ for (idx2 = 0; idx2 < xDiv; idx2 += 1)
+ data[(idx1 * xDiv + idx2) * num_channels + 3] = sp[idx2];
+ sp += width;
+ }
+
+ if(con->ncomp == 5)
+ {
+ sp = (uint8_t*)con->buf + xDiv*mx + 4 * width * MBheight;
+ for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
+ for (idx2 = 0; idx2 < xDiv; idx2 += 1)
+ data[(idx1 * xDiv + idx2) * num_channels + 4] = sp[idx2];
+ sp += width;
+ }
+ }
+ }
+ else if (con->bpi == 16) {
+ /* C */
+ uint16_t *sp = (uint16_t*)con->buf + xDiv*mx + 0 * width * MBheight;
+ for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
+ for (idx2 = 0; idx2 < xDiv; idx2 += 1)
+ data[(idx1 * xDiv + idx2) * num_channels + 0] = sp[idx2];
+ sp += width;
+ }
+
+ /* M */
+ sp = (uint16_t*)con->buf + xDiv*mx + 1 * width * MBheight;
+ for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
+ for (idx2 = 0; idx2 < xDiv; idx2 += 1)
+ data[(idx1 * xDiv + idx2) * num_channels + 1] = sp[idx2];
+ sp += width;
+ }
+
+ /* Y */
+ sp = (uint16_t*)con->buf + xDiv*mx + 2 * width * MBheight;
+ for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
+ for (idx2 = 0; idx2 < xDiv; idx2 += 1)
+ data[(idx1 * xDiv + idx2) * num_channels + 2] = sp[idx2];
+ sp += width;
+ }
+
+ /* K */
+ sp = (uint16_t*)con->buf + xDiv*mx + 3 * width * MBheight;
+ for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
+ for (idx2 = 0; idx2 < xDiv; idx2 += 1)
+ data[(idx1 * xDiv + idx2) * num_channels + 3] = sp[idx2];
+ sp += width;
+ }
+
+ if(con->ncomp == 5)
+ {
+ sp = (uint16_t*)con->buf + xDiv*mx + 4 * width * MBheight;
+ for (idx1 = 0; idx1 < yDiv; idx1 += 1) {
+ for (idx2 = 0; idx2 < xDiv; idx2 += 1)
+ data[(idx1 * xDiv + idx2) * num_channels + 4] = sp[idx2];
+ sp += width;
+ }
+ }
+ }
+}
+
+
+void read_file(jxr_image_t image, int mx, int my, int *data)
+{
+ context *con = (context*) jxr_get_user_data(image);
+ unsigned char uExternalNcomp = con->ncomp + con->padBytes;
+ int block_wid = uExternalNcomp * ((con->wid+15)&~15);
+
+ if((isOutputYUV444(image) || isOutputYUV422(image) || isOutputYUV420(image)) && jxr_get_IMAGE_CHANNELS(image) == 3)
+ {
+ /* Use special YCC format only for primary image */
+ read_file_YCC(image, mx, my, data);
+ return;
+ }
+ else if(isOutputCMYKDirect(image) && jxr_get_IMAGE_CHANNELS(image) == 4)
+ {
+ /* Use special YCC format only for primary image */
+ read_file_CMYK(image, mx, my, data);
+ return;
+ }
+
+ if(con->ncomp == 3 || con->ncomp == 4)
+ {
+ set_bgr_flag(con, image);
+ }
+ else
+ {
+ con->isBgr = 0;
+ }
+
+ if (my != con->my) {
+ int trans = (my*16 + 16 > con->hei) ? con->hei%16 : 16;
+ int line_wid = uExternalNcomp * con->wid;
+ int idx;
+ if (con->bpi == 1) {
+ uint8_t *sp = (uint8_t*)con->buf;
+ line_wid = ((line_wid + 7) >> 3);
+ block_wid >>= 3;
+ for (idx = 0; idx < trans; idx += 1) {
+ read_setup(con);
+ read_uint8(con, sp, line_wid);
+ sp += block_wid;
+ }
+ }
+ else if ((con->bpi == 5) || (con->bpi == 6)) {
+ uint16_t *sp = (uint16_t*)con->buf;
+ block_wid = ((con->wid+15)&~15);
+ for (idx = 0; idx < trans; idx += 1) {
+ read_setup(con);
+ read_uint16(con, sp, con->wid);
+ sp += block_wid;
+ }
+ }
+ else if (con->bpi == 8) {
+ uint8_t *sp = (uint8_t*)con->buf;
+ for (idx = 0; idx < trans; idx += 1) {
+ read_setup(con);
+ read_uint8(con, sp, line_wid);
+ if(con->isBgr)
+ {
+ int i;
+ for(i = 0; i < con->wid; i ++)
+ {
+ int tmp = sp[i*(uExternalNcomp)] ;
+ sp[i*(uExternalNcomp)] = sp[i*(uExternalNcomp)+ 2];
+ sp[i*(uExternalNcomp)+ 2] = tmp;
+ }
+ }
+ sp += block_wid;
+ }
+ }
+ else if (con->bpi == 10) {
+ uint32_t *sp = (uint32_t*)con->buf;
+ block_wid = ((con->wid+15)&~15);
+ for (idx = 0; idx < trans; idx += 1) {
+ read_setup(con);
+ read_uint32(con, sp, con->wid);
+ sp += block_wid;
+ }
+ }
+ else if (con->bpi == 16) {
+ if (con->sf == 1) { /* UINT */
+ uint16_t *sp = (uint16_t*)con->buf;
+ for (idx = 0; idx < trans; idx += 1) {
+ read_setup(con);
+ read_uint16(con, sp, line_wid);
+ sp += block_wid;
+ }
+ }
+ else if (con->sf == 2) { /* fixed point */
+ short *sp = (short*)con->buf;
+ for (idx = 0; idx < trans; idx += 1) {
+ read_setup(con);
+ read_uint16(con, (uint16_t *)sp, line_wid);
+ sp += block_wid;
+ }
+ }
+ else if (con->sf == 3) { /* Half float */
+ short *sp = (short*)con->buf;
+ for (idx = 0; idx < trans; idx += 1) {
+ read_setup(con);
+ read_uint16(con, (uint16_t *)sp, line_wid);
+ sp += block_wid;
+ }
+ }
+ }
+ else if (con->bpi == 32) {
+ if (con->sf == 2) { /* fixed point */
+ uint32_t *sp = (uint32_t*)con->buf;
+ for (idx = 0; idx < trans; idx += 1) {
+ read_setup(con);
+ read_uint32(con, sp, line_wid);
+ sp += block_wid;
+ }
+ }
+ else if (con->sf == 3) { /* float */
+ uint32_t *sp = (uint32_t*)con->buf;
+ for (idx = 0; idx < trans; idx += 1) {
+ read_setup(con);
+ read_uint32(con, sp, line_wid);
+ sp += block_wid;
+ }
+ }
+ }
+ con->my = my;
+ }
+
+ int xdx, ydx, sxdx;
+ if (con->bpi == 1) {
+ block_wid = (((con->wid+15)&~15) >> 3);
+ for (ydx = 0 ; ydx < 16 ; ydx += 1) {
+ if (con->sf == 1) {
+ uint8_t *sp = (uint8_t*)con->buf + ydx*block_wid + ((con->ncomp*16*mx) >> 3);
+ int *dp = data + con->ncomp*16*ydx;
+ if (!con->photometric) {
+ for (xdx = 0 ; xdx < con->ncomp*16 ; xdx++)
+ dp[xdx] = ((sp[xdx >> 3] >> (7 - (xdx & 7))) & 1);
+ }
+ else {
+ for (xdx = 0 ; xdx < con->ncomp*16 ; xdx++)
+ dp[xdx] = (((~sp[xdx >> 3]) >> (7 - (xdx & 7))) & 1);
+ }
+ }
+ }
+ }
+ else if (con->bpi == 5) {
+ block_wid = ((con->wid+15)&~15);
+ for (ydx = 0 ; ydx < 16 ; ydx += 1) {
+ uint16_t *sp = (uint16_t*)con->buf + ydx*block_wid + 16*mx;
+ int *dp = data + uExternalNcomp*16*ydx;
+ for (xdx = 0, sxdx = 0; xdx < uExternalNcomp*16 ; xdx += uExternalNcomp, sxdx++) {
+ dp[xdx] = (sp[sxdx] & 0x1f);
+ dp[xdx + 1] = ((sp[sxdx] >> 5) & 0x1f);
+ dp[xdx + 2] = ((sp[sxdx] >> 10) & 0x1f);
+ }
+ }
+ }
+ else if (con->bpi == 6) {
+ block_wid = ((con->wid+15)&~15);
+ for (ydx = 0 ; ydx < 16 ; ydx += 1) {
+ uint16_t *sp = (uint16_t*)con->buf + ydx*block_wid + 16*mx;
+ int *dp = data + uExternalNcomp*16*ydx;
+ for (xdx = 0, sxdx = 0; xdx < uExternalNcomp*16 ; xdx += uExternalNcomp, sxdx++) {
+ dp[xdx] = ((sp[sxdx] & 0x1f) << 1);
+ dp[xdx + 1] = ((sp[sxdx] >> 5) & 0x3f);
+ dp[xdx + 2] = (((sp[sxdx] >> 11) & 0x1f) << 1);
+ }
+ }
+ }
+ else if (con->bpi == 8) {
+ for (ydx = 0 ; ydx < 16 ; ydx += 1) {
+ if (con->sf == 1) { /* UINT */
+ uint8_t *sp = (uint8_t*)con->buf + ydx*block_wid + uExternalNcomp*16*mx;
+ int *dp = data + con->ncomp*16*ydx;
+ int iCh;
+ for (xdx = 0 ; xdx < 16 ; xdx++) {
+ for (iCh = 0; iCh < con->ncomp; iCh ++){
+ dp[iCh] = (sp[iCh] >> image->shift_bits);
+ }
+ dp += con->ncomp;
+ sp += uExternalNcomp;
+ }
+ }
+ else if (con->sf == 4){ /* RGBE */
+ uint8_t *sp = (uint8_t*)con->buf + ydx*block_wid + con->ncomp*16*mx; /* external ncomp is 4, internal is 3 */
+ int *dp = data + 3*16*ydx;
+ for (xdx = 0, sxdx = 0 ; xdx < 3*16 ; xdx += 3, sxdx +=4) {
+ dp[xdx] = forwardRGBE((int)sp[sxdx], (int)sp[sxdx + 3]);
+ dp[xdx + 1] = forwardRGBE((int)sp[sxdx + 1], (int)sp[sxdx + 3]);
+ dp[xdx + 2] = forwardRGBE((int)sp[sxdx + 2], (int)sp[sxdx + 3]);
+ }
+ }
+ }
+ }
+ else if (con->bpi == 10) {
+ block_wid = ((con->wid+15)&~15);
+ for (ydx = 0 ; ydx < 16 ; ydx += 1) {
+ uint32_t *sp = (uint32_t*)con->buf + ydx*block_wid + 16*mx;
+ int *dp = data + uExternalNcomp*16*ydx;
+ for (xdx = 0, sxdx = 0; xdx < uExternalNcomp*16 ; xdx += uExternalNcomp, sxdx++) {
+ dp[xdx] = (sp[sxdx] & 0x3ff);
+ dp[xdx + 1] = ((sp[sxdx] >> 10) & 0x3ff);
+ dp[xdx + 2] = ((sp[sxdx] >> 20) & 0x3ff);
+ }
+ }
+ }
+ else if (con->bpi == 16) {
+ if (con->sf == 1) { /* UINT */
+ for (ydx = 0 ; ydx < 16 ; ydx += 1) {
+ uint16_t *sp = (uint16_t*)con->buf + ydx*block_wid + con->ncomp*16*mx;
+ int *dp = data + con->ncomp*16*ydx;
+ for (xdx = 0 ; xdx < con->ncomp*16 ; xdx++)
+ dp[xdx] = (sp[xdx] >> image->shift_bits);
+ }
+ }
+ else if (con->sf == 2) { /* fixed point */
+ for (ydx = 0 ; ydx < 16 ; ydx += 1) {
+ short *sp = (short*)con->buf + ydx*block_wid + uExternalNcomp*16*mx;
+ int *dp = data + con->ncomp*16*ydx;
+ int iCh;
+ for (xdx = 0 ; xdx < 16 ; xdx++) {
+ for (iCh = 0; iCh < con->ncomp; iCh ++){
+ dp[iCh] = (sp[iCh] >> image->shift_bits);
+ }
+ dp += con->ncomp;
+ sp += uExternalNcomp;
+ }
+ }
+ }
+ else if (con->sf == 3) { /* Half float */
+ for (ydx = 0 ; ydx < 16 ; ydx += 1) {
+ short *sp = (short*)con->buf + ydx*block_wid + uExternalNcomp*16*mx;
+ int *dp = data + con->ncomp*16*ydx;
+ int iCh;
+ for (xdx = 0 ; xdx < 16 ; xdx++) {
+ for (iCh = 0; iCh < con->ncomp; iCh ++) {
+ dp[iCh] = PreScalingBD16F((int)sp[iCh]);
+ }
+ dp += con->ncomp;
+ sp += uExternalNcomp;
+ }
+ }
+ }
+ }
+ else if (con->bpi == 32) {
+ /* no 32-UINT */
+ if (con->sf == 2) { /* fixed point */
+ for (ydx = 0 ; ydx < 16 ; ydx += 1) {
+ int32_t *sp = (int32_t*)con->buf + ydx*block_wid + uExternalNcomp*16*mx;
+ int *dp = data + con->ncomp*16*ydx;
+ int iCh;
+ for (xdx = 0 ; xdx < 16 ; xdx++) {
+ for (iCh = 0; iCh < con->ncomp; iCh ++) {
+ dp[iCh] = (sp[iCh] >> image->shift_bits);
+ }
+ dp += con->ncomp;
+ sp += uExternalNcomp;
+ }
+ }
+ }
+ else if (con->sf == 3) { /* float */
+ for (ydx = 0 ; ydx < 16 ; ydx += 1) {
+ int *sp = (int*)con->buf + ydx*block_wid + uExternalNcomp*16*mx;
+ int *dp = data + con->ncomp*16*ydx;
+ int iCh;
+ for (xdx = 0 ; xdx < 16 ; xdx++) {
+ for (iCh = 0; iCh < con->ncomp; iCh ++) {
+ dp[iCh] = PreScalingBD32F(sp[iCh], image->exp_bias, image->len_mantissa);
+ }
+ dp += con->ncomp;
+ sp += uExternalNcomp;
+ }
+ }
+ }
+ }
+}
+
+void write_file_YCC(jxr_image_t image, int mx, int my, int* data)
+{
+ /* There are 3 or 4 buffers, depending on whether there is an alpha channel or not */
+ /* Write each individual component to its own file and then concatenate(not interleave these files together */
+
+ int *dataY = data;
+ int *dataU = dataY + 256;
+ int *dataV = dataU + 256;
+ int *dataA = dataV + 256;
+ static context *conY = NULL;
+ static context *conU = NULL;
+ static context *conV = NULL;
+ static context *conA = NULL;
+ context *con = (context*) jxr_get_user_data(image);
+
+
+ if (con->file==0)
+ {
+ con->alpha = jxr_get_ALPHACHANNEL_FLAG(image);
+
+ conY = (context *)malloc(sizeof(context));
+ conU = (context *)malloc(sizeof(context));
+ conV = (context *)malloc(sizeof(context));
+ if(con->alpha)
+ conA = (context *)malloc(sizeof(context));
+ memcpy(conY, con, sizeof(context));
+ memcpy(conU, con, sizeof(context));
+ memcpy(conV, con, sizeof(context));
+ if(con->alpha)
+ memcpy(conA, con, sizeof(context));
+ conY->name = "Y.raw";
+ conU->name = "U.raw";
+ conV->name = "V.raw";
+ if(con->alpha)
+ conA->name = "A.raw";
+
+ con->left_pad = image->window_extra_left;
+ con->top_pad_remaining = image->window_extra_top;
+ con->top_pad = image->window_extra_top;
+
+ con->ncomp = conY->ncomp = conU->ncomp = conV->ncomp =1;
+ if(con->alpha)
+ conA->ncomp = 1;
+ start_output_file(con, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
+ jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
+ 1 , jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
+ start_output_file(conY, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
+ jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
+ 1 , jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
+ start_output_file(conU, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
+ jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
+ 1 , jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
+ start_output_file(conV, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
+ jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
+ 1 , jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
+ if(con->alpha)
+ start_output_file(conA, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
+ jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
+ 1 , jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
+
+ }
+
+ int idx;
+ int strip_blocks = (image->extended_width)/16;
+ int dy = 16*strip_blocks;
+
+ if (con->bpi == 8) {
+
+ int xDiv = 16;
+ int yDiv = 16;
+ /* Y */
+ uint8_t *dp = (uint8_t*)conY->buf + xDiv*mx;
+ for (idx = 0; idx < xDiv*yDiv; idx += 1) {
+ int dix = (idx/xDiv)*dy + (idx%xDiv);
+ dp[dix] = dataY[idx];
+ }
+
+ if(isOutputYUV422(image))
+ {
+ dy = 8*strip_blocks;
+ xDiv = 8;
+ }
+
+ if(isOutputYUV420(image))
+ {
+ dy = 8*strip_blocks;
+ xDiv = yDiv = 8;
+ }
+
+ /* U */
+ dp = (uint8_t*)conU->buf + xDiv*mx;
+ for (idx = 0; idx < xDiv*yDiv; idx += 1) {
+ int dix = (idx/xDiv)*dy + (idx%xDiv);
+ dp[dix] = dataU[idx];
+ }
+ /* V */
+ dp = (uint8_t*)conV->buf + xDiv*mx;
+ for (idx = 0; idx < xDiv*yDiv; idx += 1) {
+ int dix = (idx/xDiv)*dy + (idx%xDiv);
+ dp[dix] = dataV[idx];
+ }
+
+ if(con->alpha)
+ {
+ xDiv = yDiv = 16;
+ dy = 16*strip_blocks;
+ dp = (uint8_t*)conA->buf + xDiv*mx;
+ for (idx = 0; idx < xDiv*yDiv; idx += 1) {
+ int dix = (idx/xDiv)*dy + (idx%xDiv);
+ dp[dix] = dataA[idx];
+ }
+ }
+
+ }
+ else if(con->bpi == 16 || con->bpi == 10) {
+
+ int xDiv = 16;
+ int yDiv = 16;
+ /* Y */
+ uint16_t *dp = (uint16_t*)conY->buf + xDiv*mx;
+ for (idx = 0; idx < xDiv*yDiv; idx += 1) {
+ int dix = (idx/xDiv)*dy + (idx%xDiv);
+ dp[dix] = dataY[idx];
+ }
+
+ if(isOutputYUV422(image))
+ {
+ dy = 8*strip_blocks;
+ xDiv = 8;
+ }
+
+ if(isOutputYUV420(image))
+ {
+ assert(!"There is no 420 pixel format with bitdepth 16\n");
+ dy = 8*strip_blocks;
+ xDiv = yDiv = 8;
+ }
+
+ /* U */
+ dp = (uint16_t*)conU->buf + xDiv*mx;
+ for (idx = 0; idx < xDiv*yDiv; idx += 1) {
+ int dix = (idx/xDiv)*dy + (idx%xDiv);
+ dp[dix] = dataU[idx];
+ }
+ /* V */
+ dp = (uint16_t*)conV->buf + xDiv*mx;
+ for (idx = 0; idx < xDiv*yDiv; idx += 1) {
+ int dix = (idx/xDiv)*dy + (idx%xDiv);
+ dp[dix] = dataV[idx];
+ }
+
+ if(con->alpha)
+ {
+ xDiv = yDiv = 16;
+ dy = 16*strip_blocks;
+ dp = (uint16_t*)conA->buf + xDiv*mx;
+ for (idx = 0; idx < xDiv*yDiv; idx += 1) {
+ int dix = (idx/xDiv)*dy + (idx%xDiv);
+ dp[dix] = dataA[idx];
+ }
+ }
+
+ }
+ else
+ {
+ assert(!"Unsupported bitdepth\n");
+ }
+
+ if (mx+1 == strip_blocks) {
+
+ int xDiv = 16;
+ int yDiv = 16;
+ int subX = 1;
+ int subY = 1;
+
+ if(con->bpi == 8)
+ {
+ /* Y */
+ int left_pad_shift = con->left_pad;
+ int first = (con->top_pad_remaining > yDiv) ? yDiv : con->top_pad_remaining;
+ int trans = (my*yDiv + yDiv > (con->hei + con->top_pad)) ? (con->hei + con->top_pad)%yDiv : yDiv;
+ dy = 16*strip_blocks;
+ for (idx = first; idx < trans; idx += 1) {
+ uint8_t *dp = (uint8_t*)conY->buf + idx*dy + con->left_pad;
+ write_uint8(conY, dp, conY->wid );
+ }
+ /* U */
+ if(isOutputYUV422(image))
+ {
+ dy = 8*strip_blocks;
+ xDiv = 8;
+ subX = 2;
+ left_pad_shift >>= 1;
+ }
+
+ if(isOutputYUV420(image))
+ {
+ dy = 8*strip_blocks;
+ xDiv = yDiv = 8;
+ subX = subY = 2;
+ left_pad_shift >>= 1;
+ }
+ first = (con->top_pad_remaining > yDiv) ? yDiv : con->top_pad_remaining/subY;
+ trans = (my*yDiv + yDiv > (con->hei + con->top_pad)) ? ((con->hei + con->top_pad)/subY)%yDiv : yDiv;
+ for (idx = first; idx < trans; idx += 1) {
+ uint8_t *dp = (uint8_t*)conU->buf + idx*dy + left_pad_shift;
+ write_uint8(conU, dp, (conU->wid)/subX );
+ }
+ /* V */
+ trans = (my*yDiv + yDiv > (con->hei + con->top_pad)) ? ((con->hei + con->top_pad)/subY)%yDiv : yDiv;
+ for (idx = first; idx < trans; idx += 1) {
+ uint8_t *dp = (uint8_t*)conV->buf + idx*dy + left_pad_shift;
+ write_uint8(conV, dp, (conV->wid)/subX );
+ }
+ /* A */
+ if(con->alpha)
+ {
+ dy = 16*strip_blocks;
+ xDiv = yDiv = 16;
+ first = (con->top_pad_remaining > yDiv) ? yDiv : con->top_pad_remaining;
+ trans = (my*yDiv + yDiv > (con->hei + con->top_pad)) ? (con->hei + con->top_pad)%yDiv : yDiv;
+ for (idx = first; idx < trans; idx += 1) {
+ uint8_t *dp = (uint8_t*)conA->buf + idx*dy + con->left_pad;
+ write_uint8(conA, dp, conA->wid);
+ }
+ }
+ first = (con->top_pad_remaining > 16) ? 16 : con->top_pad_remaining;
+ con->top_pad_remaining -= first;
+ }
+ else if(con->bpi == 16 || con->bpi == 10)
+ {
+ /* Y */
+ int left_pad_shift = con->left_pad;
+ int first = (con->top_pad_remaining > yDiv) ? yDiv : con->top_pad_remaining;
+ int trans = (my*yDiv + yDiv > (con->hei + con->top_pad)) ? (con->hei + con->top_pad)%yDiv : yDiv;
+ dy = 16*strip_blocks;
+ for (idx = first; idx < trans; idx += 1) {
+ uint16_t *dp = (uint16_t*)conY->buf + idx*dy + con->left_pad;
+ write_uint16(conY, dp, conY->wid );
+ }
+ /* U */
+ if(isOutputYUV422(image))
+ {
+ dy = 8*strip_blocks;
+ xDiv = 8;
+ subX = 2;
+ left_pad_shift >>= 1;
+ }
+
+ if(isOutputYUV420(image))
+ {
+ dy = 8*strip_blocks;
+ xDiv = yDiv = 8;
+ subX = subY = 2;
+ left_pad_shift >>= 1;
+ }
+ first = (con->top_pad_remaining > yDiv) ? yDiv : con->top_pad_remaining/subY;
+ trans = (my*yDiv + yDiv > (con->hei + con->top_pad)) ? ((con->hei + con->top_pad)/subY)%yDiv : yDiv;
+ for (idx = first; idx < trans; idx += 1) {
+ uint16_t *dp = (uint16_t*)conU->buf + idx*dy + left_pad_shift;
+ write_uint16(conU, dp, (conU->wid)/subX );
+ }
+ /* V */
+ first = (con->top_pad_remaining > yDiv) ? yDiv : con->top_pad_remaining/subY;
+ trans = (my*yDiv + yDiv > (con->hei + con->top_pad)) ? ((con->hei + con->top_pad)/subY)%yDiv : yDiv;
+ for (idx = first; idx < trans; idx += 1) {
+ uint16_t *dp = (uint16_t*)conV->buf + idx*dy + left_pad_shift;
+ write_uint16(conV, dp, (conV->wid)/subX );
+ }
+ /* A */
+ if(con->alpha)
+ {
+ dy = 16*strip_blocks;
+ xDiv = yDiv = 16;
+ first = (con->top_pad_remaining > yDiv) ? yDiv : con->top_pad_remaining;
+ trans = (my*yDiv + yDiv >(con->hei + con->top_pad)) ? (con->hei + con->top_pad)%yDiv : yDiv;
+ for (idx = first; idx < trans; idx += 1) {
+ uint16_t *dp = (uint16_t*)conA->buf + idx*dy + con->left_pad;
+ write_uint16(conA, dp, conA->wid);
+ }
+ }
+ first = (con->top_pad_remaining > 16) ? 16 : con->top_pad_remaining;
+ con->top_pad_remaining -= first;
+ }
+ else
+ assert(!"Unsupported bitdepth\n");
+ }
+ if(my*16 + 16 >= (con->hei + con->top_pad) && mx+1 == strip_blocks)
+ {
+ /* End of decode */
+ long size = ftell(conY->file);
+ fseek(conY->file, 0, 0);
+ long ii;
+ for(ii = 0; ii < size; ii++)
+ {
+ uint8_t val;
+ fread(&val, 1, 1, conY->file);
+ fwrite(&val, 1, 1, con->file);
+ }
+ size = ftell(conU->file);
+ fseek(conU->file, 0, 0);
+ for( ii = 0; ii < size; ii++)
+ {
+ uint8_t val;
+ fread(&val, 1, 1, conU->file);
+ fwrite(&val, 1, 1, con->file);
+ }
+ size = ftell(conV->file);
+ fseek(conV->file, 0, 0);
+ for( ii = 0; ii < size; ii++)
+ {
+ uint8_t val;
+ fread(&val, 1, 1, conV->file);
+ fwrite(&val, 1, 1, con->file);
+ }
+ if(con->alpha)
+ {
+ size = ftell(conA->file);
+ fseek(conA->file, 0, 0);
+ for( ii = 0; ii < size && con->alpha; ii++)
+ {
+ uint8_t val;
+ fread(&val, 1, 1, conA->file);
+ fwrite(&val, 1, 1, con->file);
+ }
+ }
+ fclose(conY->file);
+ fclose(conU->file);
+ fclose(conV->file);
+ if(con->alpha)
+ fclose(conA->file);
+
+ free(conY->buf);
+ free(conU->buf);
+ free(conV->buf);
+ if(con->alpha)
+ free(conA->buf);
+
+ free(conY);
+ free(conU);
+ free(conV);
+ if(con->alpha)
+ free(conA);
+
+ remove("Y.raw");
+ remove("U.raw");
+ remove("V.raw");
+ if(con->alpha)
+ remove("A.raw");
+
+ }
+}
+
+void write_file_CMYK(jxr_image_t image, int mx, int my, int* data)
+{
+ /* There are 4 or 5 buffers, depending on whether there is an alpha channel or not */
+ /* Write each individual component to its own file and then concatenate(not interleave these files together */
+
+ int *dataC = data;
+ int *dataM = dataC + 256;
+ int *dataY = dataM + 256;
+ int *dataK = dataY + 256;
+ int *dataA = dataK + 256;
+ static context *conC = NULL;
+ static context *conM = NULL;
+ static context *conY = NULL;
+ static context *conK = NULL;
+ static context *conA = NULL;
+ context *con = (context*) jxr_get_user_data(image);
+ if (con->file==0)
+ {
+ con->alpha = jxr_get_ALPHACHANNEL_FLAG(image);
+
+ conC = (context *)malloc(sizeof(context));
+ conM = (context *)malloc(sizeof(context));
+ conY = (context *)malloc(sizeof(context));
+ conK = (context *)malloc(sizeof(context));
+ if(con->alpha)
+ conA = (context *)malloc(sizeof(context));
+ memcpy(conC, con, sizeof(context));
+ memcpy(conM, con, sizeof(context));
+ memcpy(conY, con, sizeof(context));
+ memcpy(conK, con, sizeof(context));
+ if(con->alpha)
+ memcpy(conA, con, sizeof(context));
+ conC->name = "C.raw";
+ conM->name = "M.raw";
+ conY->name = "Y.raw";
+ conK->name = "K.raw";
+ if(con->alpha)
+ conA->name = "A.raw";
+
+ con->left_pad = image->window_extra_left;
+ con->top_pad_remaining = image->window_extra_top;
+ con->top_pad = image->window_extra_top;
+
+ con->ncomp = conC->ncomp = conM->ncomp = conY->ncomp = conK->ncomp = 1;
+ if(con->alpha)
+ conA->ncomp = 1;
+ start_output_file(con, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
+ jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
+ 1 , jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
+ start_output_file(conC, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
+ jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
+ 1 , jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
+ start_output_file(conM, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
+ jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
+ 1 , jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
+ start_output_file(conY, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
+ jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
+ 1 , jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
+ start_output_file(conK, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
+ jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
+ 1 , jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
+
+ if(con->alpha)
+ start_output_file(conA, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
+ jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
+ 1 , jxr_get_OUTPUT_BITDEPTH(image),jxr_get_pixel_format(image));
+
+ }
+
+ int idx;
+ int strip_blocks = (image->extended_width)/16;
+ int dy = 16*strip_blocks;
+
+ if (con->bpi == 8) {
+
+ /* C */
+ uint8_t *dp = (uint8_t*)conC->buf + 16*mx;
+ for (idx = 0; idx < 256; idx += 1) {
+ int dix = (idx/16)*dy + (idx%16);
+ dp[dix] = dataC[idx];
+ }
+
+ /* M */
+ dp = (uint8_t*)conM->buf + 16*mx;
+ for (idx = 0; idx < 256; idx += 1) {
+ int dix = (idx/16)*dy + (idx%16);
+ dp[dix] = dataM[idx];
+ }
+ /* Y */
+ dp = (uint8_t*)conY->buf + 16*mx;
+ for (idx = 0; idx < 256; idx += 1) {
+ int dix = (idx/16)*dy + (idx%16);
+ dp[dix] = dataY[idx];
+ }
+ /* K */
+ dp = (uint8_t*)conK->buf + 16*mx;
+ for (idx = 0; idx < 256; idx += 1) {
+ int dix = (idx/16)*dy + (idx%16);
+ dp[dix] = dataK[idx];
+ }
+
+
+ if(con->alpha)
+ {
+ dp = (uint8_t*)conA->buf + 16*mx;
+ for (idx = 0; idx < 256; idx += 1) {
+ int dix = (idx/16)*dy + (idx%16);
+ dp[dix] = dataA[idx];
+ }
+ }
+
+ }
+ else if(con->bpi == 16 || con->bpi == 10) {
+
+ /* C */
+ uint16_t *dp = (uint16_t*)conC->buf + 16*mx;
+ for (idx = 0; idx < 256; idx += 1) {
+ int dix = (idx/16)*dy + (idx%16);
+ dp[dix] = dataC[idx];
+ }
+
+ /* M */
+ dp = (uint16_t*)conM->buf + 16*mx;
+ for (idx = 0; idx < 256; idx += 1) {
+ int dix = (idx/16)*dy + (idx%16);
+ dp[dix] = dataM[idx];
+ }
+ /* Y */
+ dp = (uint16_t*)conY->buf + 16*mx;
+ for (idx = 0; idx < 256; idx += 1) {
+ int dix = (idx/16)*dy + (idx%16);
+ dp[dix] = dataY[idx];
+ }
+ /* K */
+ dp = (uint16_t*)conK->buf + 16*mx;
+ for (idx = 0; idx < 256; idx += 1) {
+ int dix = (idx/16)*dy + (idx%16);
+ dp[dix] = dataK[idx];
+ }
+
+ /* A */
+ if(con->alpha)
+ {
+ dp = (uint16_t*)conA->buf + 16*mx;
+ for (idx = 0; idx < 256; idx += 1) {
+ int dix = (idx/16)*dy + (idx%16);
+ dp[dix] = dataA[idx];
+ }
+ }
+ }
+ else
+ {
+ assert(!"Unsupported bitdepth\n");
+ }
+
+ if (mx+1 == strip_blocks) {
+
+ if(con->bpi == 8)
+ {
+ int first = (con->top_pad_remaining > 16) ? 16 : con->top_pad_remaining;
+ int trans = (my*16 + 16 > (con->hei + con->top_pad)) ? (con->hei + con->top_pad)%16 : 16;
+
+ dy = 16*strip_blocks;
+ for (idx = first; idx < trans; idx += 1) {
+ uint8_t *dp = (uint8_t*)conC->buf + idx*dy + con->left_pad;
+ write_uint8(conC, dp, conC->wid );
+ }
+ for (idx = first; idx < trans; idx += 1) {
+ uint8_t *dp = (uint8_t*)conM->buf + idx*dy + con->left_pad;
+ write_uint8(conM, dp, (conM->wid));
+ }
+ for (idx = first; idx < trans; idx += 1) {
+ uint8_t *dp = (uint8_t*)conY->buf + idx*dy + con->left_pad;
+ write_uint8(conY, dp, (conY->wid));
+ }
+ for (idx = first; idx < trans; idx += 1) {
+ uint8_t *dp = (uint8_t*)conK->buf + idx*dy + con->left_pad;
+ write_uint8(conK, dp, (conK->wid));
+ }
+
+ if(con->alpha)
+ {
+ for (idx = first; idx < trans; idx += 1) {
+ uint8_t *dp = (uint8_t*)conA->buf + idx*dy + con->left_pad;
+ write_uint8(conA, dp, conA->wid);
+ }
+ }
+ con->top_pad_remaining -= first;
+ }
+ else if(con->bpi == 16 || con->bpi == 10)
+ {
+ int first = (con->top_pad_remaining > 16) ? 16 : con->top_pad_remaining;
+ int trans = (my*16 + 16 > (con->hei + con->top_pad)) ? (con->hei + con->top_pad)%16 : 16;
+ dy = 16*strip_blocks;
+ for (idx = first; idx < trans; idx += 1) {
+ uint16_t *dp = (uint16_t*)conC->buf + idx*dy + con->left_pad;
+ write_uint16(conC, dp, conC->wid );
+ }
+
+ for (idx = first; idx < trans; idx += 1) {
+ uint16_t *dp = (uint16_t*)conM->buf + idx*dy + con->left_pad;
+ write_uint16(conM, dp, (conM->wid) );
+ }
+
+ for (idx = first; idx < trans; idx += 1) {
+ uint16_t *dp = (uint16_t*)conY->buf + idx*dy + con->left_pad;
+ write_uint16(conY, dp, (conY->wid) );
+ }
+
+ for (idx = first; idx < trans; idx += 1) {
+ uint16_t *dp = (uint16_t*)conK->buf + idx*dy + con->left_pad;
+ write_uint16(conK, dp, (conK->wid) );
+ }
+
+ if(con->alpha)
+ {
+ for (idx = first; idx < trans; idx += 1) {
+ uint16_t *dp = (uint16_t*)conA->buf + idx*dy + con->left_pad;
+ write_uint16(conA, dp, conA->wid);
+ }
+ }
+ con->top_pad_remaining -= first;
+ }
+ else
+ assert(!"Unsupported bitdepth\n");
+ }
+ if(my*16 + 16 >= (con->hei + con->top_pad) && mx+1 == strip_blocks)
+ {
+ /* End of decode */
+ long size = ftell(conC->file);
+ long ii;
+ fseek(conC->file, 0, 0);
+ for( ii = 0; ii < size; ii++)
+ {
+ uint8_t val;
+ fread(&val, 1, 1, conC->file);
+ fwrite(&val, 1, 1, con->file);
+ }
+ size = ftell(conM->file);
+ fseek(conM->file, 0, 0);
+ for( ii = 0; ii < size; ii++)
+ {
+ uint8_t val;
+ fread(&val, 1, 1, conM->file);
+ fwrite(&val, 1, 1, con->file);
+ }
+ size = ftell(conY->file);
+ fseek(conY->file, 0, 0);
+ for( ii = 0; ii < size; ii++)
+ {
+ uint8_t val;
+ fread(&val, 1, 1, conY->file);
+ fwrite(&val, 1, 1, con->file);
+ }
+ size = ftell(conK->file);
+ fseek(conK->file, 0, 0);
+ for( ii = 0; ii < size; ii++)
+ {
+ uint8_t val;
+ fread(&val, 1, 1, conK->file);
+ fwrite(&val, 1, 1, con->file);
+ }
+ if(con->alpha)
+ {
+ size = ftell(conA->file);
+ fseek(conA->file, 0, 0);
+ for( ii = 0; ii < size && con->alpha; ii++)
+ {
+ uint8_t val;
+ fread(&val, 1, 1, conA->file);
+ fwrite(&val, 1, 1, con->file);
+ }
+ }
+ fclose(conC->file);
+ fclose(conM->file);
+ fclose(conY->file);
+ fclose(conK->file);
+ if(con->alpha)
+ fclose(conA->file);
+
+ free(conC->buf);
+ free(conM->buf);
+ free(conY->buf);
+ free(conK->buf);
+ if(con->alpha)
+ free(conA->buf);
+
+ free(conC);
+ free(conM);
+ free(conY);
+ free(conK);
+ if(con->alpha)
+ free(conA);
+
+ remove("C.raw");
+ remove("M.raw");
+ remove("Y.raw");
+ remove("K.raw");
+ if(con->alpha)
+ remove("A.raw");
+ }
+}
+
+void write_file(jxr_image_t image, int mx, int my, int*data)
+{
+ context *con = (context*) jxr_get_user_data(image);
+
+ if((isOutputYUV444(image) || isOutputYUV422(image) || isOutputYUV420(image)) && jxr_get_IMAGE_CHANNELS(image) == 3)
+ {
+ /* Use special YCC format only for primary image */
+ write_file_YCC(image, mx, my, data);
+ return;
+ }
+ else if(isOutputCMYKDirect(image) && jxr_get_IMAGE_CHANNELS(image) == 4)
+ {
+ /* Use special YCC format only for primary image */
+ write_file_CMYK(image, mx, my, data);
+ return;
+ }
+
+ if (con->file==0)
+ {
+ int channels = jxr_get_IMAGE_CHANNELS(image);
+ if( channels == 3)
+ set_bgr_flag(con, image);
+ else
+ con->isBgr = 0;
+
+ if(jxr_get_pixel_format(image) == JXRC_FMT_32bppRGBE)
+ {
+ channels++;
+ }
+
+ set_pad_bytes(con, image);
+
+ con->left_pad = image->window_extra_left;
+ con->top_pad_remaining = image->window_extra_top;
+ con->top_pad = image->window_extra_top;
+
+ con->alpha = jxr_get_ALPHACHANNEL_FLAG(image);
+ if (con->alpha) /* with alpha channel */
+ channels ++;
+
+ start_output_file(con, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
+ jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
+ channels, jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
+ }
+
+ int idx, jdx;
+ int strip_blocks = (image->extended_width)/16;
+ int dy = 16*con->ncomp*strip_blocks;
+ if(con->padBytes !=0)
+ dy = dy+16*strip_blocks;
+ if (con->bpi == 1 || con->bpi == 5 || con->bpi == 6 || con->bpi == 8) {
+ uint8_t *dp = (uint8_t*)con->buf + 16*con->ncomp*mx;
+ if(con->padBytes != 0)
+ {
+ dp = dp + 16*mx; /* Add padding channel offset */
+ }
+ for (idx = 0; idx < 256; idx += 1) {
+ int dix = (idx/16)*dy + (idx%16)*con->ncomp;
+ if(con->padBytes)
+ dix +=(idx%16);
+ int six = idx*con->ncomp;
+ int pl;
+ for (pl = 0 ; pl < con->ncomp ; pl += 1)
+ dp[dix + pl] = data[six + pl];
+ if(con->padBytes != 0)
+ dp[dix + pl] = 0; /* Padding data after all n channels */
+ if(con->isBgr)
+ switch_r_b(dp+dix, con->bpi);
+ }
+ }
+ else if(con->bpi == 10 || con->bpi == 16){
+ uint16_t *dp = (uint16_t*)con->buf + 16*con->ncomp*mx;
+ if(con->padBytes != 0)
+ {
+ dp = dp + 16*mx; /* Add padding channel offset */
+ }
+
+ for (idx = 0; idx < 256; idx += 1) {
+ int dix = (idx/16)*dy + (idx%16)*con->ncomp;
+ if(con->padBytes)
+ dix +=(idx%16);
+ int six = idx*con->ncomp;
+ int pl;
+ for (pl = 0 ; pl < con->ncomp ; pl += 1)
+ dp[dix + pl] = data[six + pl];
+ if(con->padBytes != 0)
+ dp[dix + pl] = 0; /* Padding data after all n channels */
+ if(con->isBgr)
+ switch_r_b(dp + dix, con->bpi);
+ }
+ }
+ else if(con->bpi ==32) {
+ uint32_t *dp = (uint32_t*)con->buf + 16*con->ncomp*mx;
+ if(con->padBytes != 0)
+ {
+ dp = dp + 16*mx; /* Add padding channel offset */
+ }
+ for (idx = 0; idx < 256; idx += 1) {
+ int dix = (idx/16)*dy + (idx%16)*con->ncomp;
+ if(con->padBytes)
+ dix +=(idx%16);
+ int six = idx*con->ncomp;
+ int pl;
+ for (pl = 0 ; pl < con->ncomp ; pl += 1)
+ dp[dix + pl] = data[six + pl];
+ if(con->padBytes != 0)
+ dp[dix + pl] = 0; /* Padding data after all n channels */
+ if(con->isBgr)
+ switch_r_b(dp + dix, con->bpi);
+ }
+ }
+ else
+ {
+ assert(!"Unsupported bitdepth\n");
+ }
+
+ if (mx+1 == strip_blocks) {
+ int first = (con->top_pad_remaining > 16) ? 16 : con->top_pad_remaining;
+ con->top_pad_remaining -= first; /* skip the padding rows */
+ int trans = (my*16 + 16 > (con->hei + con->top_pad)) ? (con->hei + con->top_pad)%16 : 16;
+ if(con->bpi == 1)
+ {
+ /* ClipAndPackBD1BorW */
+ /* Clipping is already handled in scale_and_emit_top, so just pack */
+ for (idx = first; idx < trans; idx += 1) {
+ uint8_t *dp = (uint8_t*)con->buf + idx*dy;
+ for(jdx = con->left_pad; jdx < (con->wid + con->left_pad); jdx = jdx + 8)
+ {
+ uint8_t buff[8];
+ uint8_t iResult = 0;
+ int end = jdx + 8 > con->wid? con->wid:jdx + 8;
+ memset(buff, 0, 8 * sizeof(uint8_t));
+ memcpy(buff, dp+jdx, (end-jdx) * sizeof(uint8_t));
+ if (jxr_get_OUTPUT_BITDEPTH(image) == JXR_BD1BLACK1)
+ {
+ iResult = (1-buff[7]) + ((1 - buff[6]) << 1) + ((1 - buff[5]) << 2) +
+ ((1 - buff[4]) << 3) + ((1 - buff[3]) << 4) + ((1 - buff[2]) << 5) +
+ ((1 - buff[1]) << 6) + ((1 - buff[0]) << 7);
+ }
+ else/* jxr_output_bitdepth(image) = = BD1WHITE1 */
+ {
+ iResult = buff[7] + (buff[6] << 1) + (buff[5] << 2) +
+ (buff[4] << 3) + (buff[3] << 4) + (buff[2] << 5) +
+ (buff[1] << 6) + (buff[0] << 7);
+ }
+
+ write_uint8(con, &iResult,1 );
+ }
+ }
+ }
+ else if(con->bpi == 5)
+ {
+ /* ClipAndPack555 */
+ /* Clipping is already handled in scale_and_emit_top, so just pack */
+ for (idx = first; idx < trans; idx += 1) {
+ uint8_t *dp = (uint8_t*)con->buf + idx*dy;
+ assert(con->ncomp == 3);
+ for(jdx = con->left_pad*con->ncomp; jdx < (con->wid + con->left_pad)*con->ncomp; jdx = jdx + con->ncomp)
+ {
+ uint16_t iResult = 0;
+ iResult = (uint16_t)dp[jdx] + (((uint16_t)dp[jdx + 1])<<5) + (((uint16_t)dp[jdx + 2])<<10);
+ write_uint16(con, &iResult,1 );
+ }
+ }
+ }
+ else if(con->bpi == 6)
+ {
+ /* ClipAndPack565 */
+ /* Clipping is already handled in scale_and_emit_top, so just pack */
+ for (idx = first; idx < trans; idx += 1) {
+ uint8_t *dp = (uint8_t*)con->buf + idx*dy;
+ assert(con->ncomp == 3);
+ for(jdx = con->left_pad*con->ncomp; jdx < (con->wid + con->left_pad)*con->ncomp; jdx = jdx + con->ncomp)
+ {
+ uint16_t iResult = 0;
+ iResult = (uint16_t)dp[jdx] + (((uint16_t)dp[jdx + 1])<<5) + (((uint16_t)dp[jdx + 2])<<11);
+ write_uint16(con, &iResult,1 );
+ }
+ }
+ }
+ else if (con->bpi==8)
+ for (idx = first; idx < trans; idx += 1) {
+ uint8_t *dp = (uint8_t*)con->buf + idx*dy + con->left_pad*con->ncomp;
+ int padComp = con->ncomp;
+ if(con->padBytes != 0 )
+ padComp ++;
+ write_uint8(con, dp, con->wid*padComp); }
+ else if(con->bpi == 10 && con->ncomp == 3)
+ {
+ /* ClipAndPack10 */
+ /* Clipping is already handled in scale_and_emit_top, so just pack */
+ for (idx = first; idx < trans; idx += 1) {
+ uint16_t *dp = (uint16_t*)con->buf + idx*dy;
+ for(jdx = con->left_pad*con->ncomp; jdx < (con->wid + con->left_pad)*con->ncomp; jdx = jdx + con->ncomp)
+ {
+ uint32_t iResult = 0;
+ iResult = (uint32_t)dp[jdx] + (((uint32_t)dp[jdx + 1])<<10) + (((uint32_t)dp[jdx + 2])<<20);
+ write_uint32(con, &iResult,1 );
+ }
+ }
+ }
+ else if(con->bpi == 10 && con->ncomp == 1)/*Alpha image decoding for JXR_30bppYCC422Alpha JXR_40bppYCC4444Alpha */
+ {
+ /* ClipAndPack10 */
+ /* Clipping is already handled in scale_and_emit_top, so just pack */
+ for (idx = 0; idx < trans; idx += 1) {
+ uint16_t *dp = (uint16_t*)con->buf + idx*dy;
+ for(jdx = con->left_pad*con->ncomp; jdx < (con->wid + con->left_pad)*con->ncomp; jdx = jdx + con->ncomp)
+ {
+ uint16_t iResult = 0;
+ iResult = (uint16_t)dp[jdx];
+ write_uint16(con, &iResult,1 );
+ }
+ }
+ }
+ else if(con->bpi==16)
+ for (idx = first; idx < trans; idx += 1) {
+ uint16_t *dp = (uint16_t*)con->buf + idx*dy + con->left_pad*con->ncomp; /* dy already contains offset for padding data */
+ int padComp = con->ncomp;
+ if(con->padBytes != 0 )
+ padComp ++;
+ write_uint16(con, dp, con->wid*padComp );
+ }
+ else if(con->bpi == 32)
+ for (idx = first; idx < trans; idx += 1) {
+ uint32_t *dp = (uint32_t*)con->buf + idx*dy + con->left_pad*con->ncomp;
+ int padComp = con->ncomp;
+ if(con->padBytes != 0 )
+ padComp ++;
+ write_uint32(con, dp, con->wid*padComp );
+ }
+ else
+ assert(!"Unsupported bitdepth\n");
+ }
+}
+
+
+void concatenate_primary_alpha(jxr_image_t image, FILE *fpPrimary, FILE *fpAlpha)
+{
+ context *con = (context*) jxr_get_user_data(image);
+ if (con->file==0)
+ {
+ set_pad_bytes(con, image);
+ /* Add 1 to number of channels for alpha */
+ con->alpha = 1;
+ start_output_file(con, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
+ jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
+ jxr_get_IMAGE_CHANNELS(image) + 1, jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
+ }
+ fseek(fpPrimary, 0, SEEK_END);
+ long size = ftell(fpPrimary);
+ fseek(fpPrimary, 0, SEEK_SET);
+ long i;
+ for(i = 0; i < size; i++)
+ {
+ uint8_t val;
+ fread(&val, 1, 1, fpPrimary);
+ fwrite(&val, 1, 1, con->file);
+ }
+ fseek(fpAlpha, 0, SEEK_END);
+ size = ftell(fpAlpha);
+ fseek(fpAlpha, 0, SEEK_SET);
+ for(i = 0; i < size; i++)
+ {
+ uint8_t val;
+ fread(&val, 1, 1, fpAlpha);
+ fwrite(&val, 1, 1, con->file);
+ }
+}
+
+
+
+void write_file_combine_primary_alpha(jxr_image_t image, FILE *fpPrimary, FILE *fpAlpha)
+{
+ context *con = (context*) jxr_get_user_data(image);
+ int i;
+
+ if(isOutputYUV444(image) || isOutputYUV422(image) || isOutputYUV420(image) || isOutputCMYKDirect(image))
+ {
+ concatenate_primary_alpha(image, fpPrimary, fpAlpha);
+ return;
+ }
+ if (con->file==0)
+ {
+ set_pad_bytes(con, image);
+ /* Add 1 to number of channels for alpha */
+ con->alpha = 1;
+ start_output_file(con, jxr_get_EXTENDED_IMAGE_WIDTH(image), jxr_get_EXTENDED_IMAGE_HEIGHT(image),
+ jxr_get_IMAGE_WIDTH(image), jxr_get_IMAGE_HEIGHT(image),
+ jxr_get_IMAGE_CHANNELS(image) + 1, jxr_get_OUTPUT_BITDEPTH(image), jxr_get_pixel_format(image));
+ }
+ int numPixels = jxr_get_IMAGE_WIDTH(image) * jxr_get_IMAGE_HEIGHT(image);
+ int nPrimaryComp = jxr_get_IMAGE_CHANNELS(image);
+ if(con->padBytes)
+ nPrimaryComp ++;
+ if (con->bpi == 8) {
+ for (i=0; i<numPixels; i++) {
+ unsigned char combine[MAX_CHANNELS + 1 + 1];/* +1 for alpha + 1 for padded channel */
+ fread(&combine[0],sizeof(char),nPrimaryComp, fpPrimary);
+ fread(&(combine[nPrimaryComp]),sizeof(char), 1,fpAlpha);
+ write_uint8(con, combine, nPrimaryComp+1);
+ }
+ }
+ else if(con->bpi == 16)
+ {
+ for (i=0; i<numPixels; i++) {
+ uint16_t combine[MAX_CHANNELS + 1 + 1];/* +1 for alpha + 1 for padded channel */
+ fread(&combine[0],sizeof(uint16_t),nPrimaryComp, fpPrimary);
+ fread(&(combine[nPrimaryComp]),sizeof(uint16_t), 1,fpAlpha);
+ write_uint16(con, combine, nPrimaryComp+1);
+ }
+ }
+ else if(con->bpi == 32)
+ {
+ for (i=0; i<numPixels; i++) {
+ uint32_t combine[MAX_CHANNELS + 1 + 1];/* +1 for alpha + 1 for padded channel */
+ fread(&combine[0],sizeof(uint32_t),nPrimaryComp, fpPrimary);
+ fread(&(combine[nPrimaryComp]),sizeof(uint32_t), 1,fpAlpha);
+ write_uint32(con, combine,nPrimaryComp+1);
+ }
+ }
+ else
+ assert(!"Unsupported bitdepth\n");
+}
+
+
+void split_primary_alpha(jxr_image_t image,void *input_handle, context *con_primary, context *con_alpha, jxr_container_t container)
+{
+ /* Used for YCCA and CMYKA */
+ int wid, hei, ncomp, bpi;
+ short sf, photometric;
+ int padBytes;
+
+ get_file_parameters(input_handle, &wid, &hei, &ncomp, &bpi, &sf, &photometric, &padBytes);
+ int numPixels = wid * hei;
+ int nPrimaryComp = ncomp-1;
+ context *con = (context *)input_handle;
+ read_setup(con);
+
+ int i;
+
+ start_output_file(con_primary, wid, hei, wid, hei, con_primary->ncomp, jxr_get_OUTPUT_BITDEPTH(image), jxrc_get_pixel_format(container));
+ start_output_file(con_alpha, wid, hei, wid, hei, con_alpha->ncomp, jxr_get_OUTPUT_BITDEPTH(image), jxrc_get_pixel_format(container));
+
+ if(isOutputYUV444(image) || isOutputYUV422(image) || isOutputYUV420(image) || isOutputCMYKDirect(image))
+ {
+ //16 * (con->ncomp + con->padBytes) * ((con->bpi+7)/8) * ((con->wid+15)&~15);
+ unsigned bytes = (con->bpi+7)/8;
+ unsigned size_luma = numPixels * bytes;
+ unsigned size_chroma = size_luma;
+ if (isOutputYUV422(image))
+ size_chroma >>= 1;
+ if (isOutputYUV420(image))
+ size_chroma >>= 2;
+
+ uint8_t * combine = 0;
+ combine = (uint8_t*)malloc(size_luma);
+ assert(combine != 0);
+
+ read_uint8(con, combine, size_luma);
+ write_uint8(con_primary, combine, size_luma);
+
+ for (i = 1; i < nPrimaryComp; i++) {
+ read_uint8(con, combine, size_chroma);
+ write_uint8(con_primary, combine, size_chroma);
+ }
+
+ read_uint8(con, combine, size_luma);
+ write_uint8(con_alpha, combine, size_luma);
+
+ free(combine);
+ }
+ else
+ {
+ for (i=0; i<numPixels; i++)
+ {
+ if (con->bpi == 8) {
+
+ unsigned char combine[MAX_CHANNELS + 1];/*+ 1 for padded channel */
+ read_uint8(con, &combine[0],nPrimaryComp);
+ write_uint8(con_primary, combine, nPrimaryComp);
+
+ }
+ else if(con->bpi == 16)
+ {
+
+ uint16_t combine[MAX_CHANNELS + 1];/*+ 1 for padded channel */
+ read_uint16(con, &combine[0],nPrimaryComp);
+ write_uint16(con_primary, combine, nPrimaryComp);
+
+ }
+ else if(con->bpi == 32)
+ {
+
+ uint32_t combine[MAX_CHANNELS + 1];/*+ 1 for padded channel */
+ read_uint32(con, &combine[0],nPrimaryComp);
+ write_uint32(con_primary, combine, nPrimaryComp);
+
+ }
+ else
+ assert(!"Unsupported bitdepth\n");
+ }
+ for (i=0; i<numPixels; i++)
+ {
+ if (con->bpi == 8) {
+
+ unsigned char combine[1];
+ read_uint8(con, &combine[0],1);
+ write_uint8(con_alpha, combine, 1);
+
+ }
+ else if(con->bpi == 16)
+ {
+
+ uint16_t combine[1];
+ read_uint16(con, &combine[0],1);
+ write_uint16(con_alpha, combine, 1);
+
+ }
+ else if(con->bpi == 32)
+ {
+
+ uint32_t combine[1];
+ read_uint32(con, &combine[0],1);
+ write_uint32(con_alpha, combine, 1);
+
+ }
+ else
+ assert(!"Unsupported bitdepth\n");
+ }
+ }
+ close_file(con_primary);
+ close_file(con_alpha);
+}
+
+
+void separate_primary_alpha(jxr_image_t image, void *input_handle, char *path_out, char * path_primary, char *path_alpha, jxr_container_t container)
+{
+
+ context *con;
+
+ int i;
+ int wid, hei, ncomp, bpi;
+ short sf, photometric;
+ int padBytes;
+
+ con = (context *)input_handle;
+ read_setup(con);
+
+
+ context *con_primary = (context *)malloc(sizeof(context));
+ assert(con_primary != NULL);
+ context *con_alpha = (context *)malloc(sizeof(context));
+ assert(con_alpha != NULL);
+
+ memcpy(con_primary, con, sizeof(*con));
+ memcpy(con_alpha, con, sizeof(*con));
+ con_primary->alpha = con_alpha->alpha = 0;
+ con_primary->buf = con_alpha->buf = 0;
+ con_primary->ncomp = con->ncomp - 1;
+ con_alpha->ncomp = 1;
+
+ get_file_parameters(con, &wid, &hei, &ncomp, &bpi, &sf, &photometric, &padBytes);
+
+ const char *p = strrchr(con->name, '.');
+ if (p==0)
+ error("output file name %s needs a suffix to determine its format", con->name);
+ if (!strcasecmp(p, ".pnm") || !strcasecmp(p, ".pgm") || !strcasecmp(p, ".ppm"))
+ {
+ error("Alpha channel not supported by PNM, PGM and PPM");
+ }
+ else if (!strcasecmp(p, ".tif"))
+ {
+ strcpy(path_primary, path_out);
+ strcat(path_primary, "_input_primary.tif");
+ strcpy(path_alpha, path_out);
+ strcat(path_alpha, "_input_alpha.tif");
+
+ }
+ else if (!strcasecmp(p, ".raw"))
+ {
+ strcpy(path_primary, path_out);
+ strcat(path_primary, "_input_primary.raw");
+ strcpy(path_alpha, path_out);
+ strcat(path_alpha, "_input_alpha.raw");
+ }
+ else error("unrecognized suffix on output file name %s", con->name);
+
+ con_primary->name = path_primary;
+ con_alpha->name = path_alpha;
+
+
+ if(isOutputYUV444(image) || isOutputYUV422(image) || isOutputYUV420(image) || isOutputCMYKDirect(image))
+ {
+ split_primary_alpha(image, input_handle,con_primary, con_alpha, container);
+ return;
+ }
+
+ start_output_file(con_primary, wid, hei, wid, hei, con_primary->ncomp, jxr_get_OUTPUT_BITDEPTH(image), jxrc_get_pixel_format(container));
+ start_output_file(con_alpha, wid, hei, wid, hei, con_alpha->ncomp, jxr_get_OUTPUT_BITDEPTH(image), jxrc_get_pixel_format(container));
+
+ int numPixels = wid * hei;
+ int nPrimaryComp = ncomp-1;
+
+ if (con->bpi == 8) {
+ for (i=0; i<numPixels; i++) {
+ unsigned char combine[MAX_CHANNELS + 1 + 1];/* +1 for alpha + 1 for padded channel */
+ read_uint8(con, &combine[0],ncomp);
+ write_uint8(con_primary, combine, nPrimaryComp);
+ write_uint8(con_alpha, &(combine[nPrimaryComp]), 1);
+
+ }
+ }
+ else if(con->bpi == 16)
+ {
+ for (i=0; i<numPixels; i++) {
+ uint16_t combine[MAX_CHANNELS + 1 + 1];/* +1 for alpha + 1 for padded channel */
+ read_uint16(con, &combine[0],ncomp);
+ write_uint16(con_primary, combine, nPrimaryComp);
+ write_uint16(con_alpha, &(combine[nPrimaryComp]), 1);
+ }
+ }
+ else if(con->bpi == 32)
+ {
+ for (i=0; i<numPixels; i++) {
+ uint32_t combine[MAX_CHANNELS + 1 + 1];/* +1 for alpha + 1 for padded channel */
+ read_uint32(con, &combine[0],ncomp);
+ write_uint32(con_primary, combine, nPrimaryComp);
+ write_uint32(con_alpha, &(combine[nPrimaryComp]), 1);
+ }
+ }
+ else
+ assert(!"Unsupported bitdepth\n");
+ close_file(con_primary);
+ close_file(con_alpha);
+}
+
+/*
+* $Log: file.c,v $
+* Revision 1.17 2009/05/29 12:00:00 microsoft
+* Reference Software v1.6 updates.
+*
+* Revision 1.16 2009/04/13 12:00:00 microsoft
+* Reference Software v1.5 updates.
+*
+* Revision 1.15 2008/03/17 23:34:54 steve
+* Support output of CMYK TIFF images.
+*
+* Revision 1.14 2008/03/06 09:33:47 rick
+* Add support for reading multi-strip TIFF files; fix TIFF reader bug.
+*
+* Revision 1.13 2008/03/05 19:32:02 gus
+* *** empty log message ***
+*
+* Revision 1.12 2008/03/05 06:58:10 gus
+* *** empty log message ***
+*
+* Revision 1.11 2008/03/03 03:16:18 rick
+* Re-implement BDx to bpi mapping.
+*
+* Revision 1.10 2008/03/03 01:57:34 steve
+* Fix BDx to bpi mapping.
+*
+* Revision 1.9 2008/03/03 01:51:40 rick
+* Allow output file depths other than 8.
+*
+* Revision 1.8 2008/02/29 01:03:31 steve
+* MSC doesnt have strcasecmp. Use stricmp instead.
+*
+* Revision 1.7 2008/02/29 00:45:21 steve
+* Portability, esp w/ C++ compilers.
+*
+* Revision 1.6 2008/02/27 06:15:49 rick
+* Replace macro ASSERT, which had optional arguments.
+*
+* Revision 1.5 2008/02/26 23:52:44 steve
+* Remove ident for MS compilers.
+*
+* Revision 1.4 2008/02/26 23:44:25 steve
+* Handle the special case of compiling via MS C.
+*
+* Revision 1.3 2008/02/23 08:45:07 rick
+* Changed some types to avoid compiler warnings.
+*
+* Revision 1.2 2008/01/31 23:20:14 rick
+* Fix bug in read_file() affecting color input images.
+*
+* Revision 1.1 2008/01/19 02:30:46 rick
+* Re-implement and extend file interface.
+*
+*/
+
diff --git a/jpegxr/file.h b/jpegxr/file.h
new file mode 100644
index 000000000..dbed9479e
--- /dev/null
+++ b/jpegxr/file.h
@@ -0,0 +1,72 @@
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+***********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: file.h,v 1.2 2008/02/26 23:52:44 steve Exp $")
+#else
+#ident "$Id: file.h,v 1.2 2008/02/26 23:52:44 steve Exp $"
+#endif
+
+void *open_input_file(const char *name, const raw_info *raw_info_t, int *alpha_mode, int *padded_format);
+void *open_output_file(const char *name);
+void get_file_parameters(void *handle, int *wid, int *hei, int *ncomp, int *bpi, short *sf, short *photometric, int *padBytes);
+void read_file(jxr_image_t image, int mx, int my, int *data);
+void write_file(jxr_image_t image, int mx, int my, int *data);
+void write_file_combine_primary_alpha(jxr_image_t image, FILE *fpPrimary, FILE *fpAlpha);
+void separate_primary_alpha(jxr_image_t image, void *input_handle, char *path_out, char * path_primary, char *path_alpha, jxr_container_t container);
+void close_file(void *handle);
+void set_ncomp(void *input_handle, int ncomp);
+
+/*
+* $Log: file.h,v $
+* Revision 1.4 2009/05/29 12:00:00 microsoft
+* Reference Software v1.6 updates.
+*
+* Revision 1.3 2009/04/13 12:00:00 microsoft
+* Reference Software v1.5 updates.
+*
+* Revision 1.2 2008/02/26 23:52:44 steve
+* Remove ident for MS compilers.
+*
+* Revision 1.1 2008/01/19 02:30:46 rick
+* Re-implement and extend file interface.
+*
+*/
+
diff --git a/jpegxr/flags.c b/jpegxr/flags.c
new file mode 100644
index 000000000..dbdec7630
--- /dev/null
+++ b/jpegxr/flags.c
@@ -0,0 +1,155 @@
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+***********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: flags.c,v 1.5 2008/03/06 02:05:48 steve Exp $")
+#else
+#ident "$Id: flags.c,v 1.5 2008/03/06 02:05:48 steve Exp $"
+#endif
+
+# include "jxr_priv.h"
+# include <assert.h>
+
+unsigned jxr_get_IMAGE_WIDTH(jxr_image_t image)
+{
+ return image->width1 + 1;
+}
+
+unsigned jxr_get_IMAGE_HEIGHT(jxr_image_t image)
+{
+ return image->height1 + 1;
+}
+
+unsigned jxr_get_EXTENDED_IMAGE_WIDTH(jxr_image_t image)
+{
+ return image->extended_width;
+}
+
+unsigned jxr_get_EXTENDED_IMAGE_HEIGHT(jxr_image_t image)
+{
+ return image->extended_height;
+}
+
+int jxr_get_TILING_FLAG(jxr_image_t image)
+{
+ if (TILING_FLAG(image))
+ return 1;
+ else
+ return 0;
+}
+
+unsigned jxr_get_TILE_COLUMNS(jxr_image_t image)
+{
+ return image->tile_columns + 1;
+}
+
+unsigned jxr_get_TILE_ROWS(jxr_image_t image)
+{
+ return image->tile_rows + 1;
+}
+
+int jxr_get_TILE_WIDTH(jxr_image_t image, unsigned column)
+{
+ if (column > image->tile_columns) {
+ return 0;
+ } else if (column == image->tile_columns) {
+ if (column == 0)
+ return EXTENDED_WIDTH_BLOCKS(image);
+ else
+ return EXTENDED_WIDTH_BLOCKS(image) - image->tile_column_position[column-1];
+ } else {
+ return image->tile_column_width[column];
+ }
+}
+
+int jxr_get_TILE_HEIGHT(jxr_image_t image, unsigned row)
+{
+ if (row > image->tile_rows) {
+ return 0;
+ } else if (row == image->tile_rows) {
+ if (row == 0)
+ return EXTENDED_HEIGHT_BLOCKS(image);
+ else
+ return EXTENDED_HEIGHT_BLOCKS(image) - image->tile_row_position[row-1];
+ } else {
+ return image->tile_row_height[row];
+ }
+}
+
+int jxr_get_ALPHACHANNEL_FLAG(jxr_image_t image)
+{
+ if (ALPHACHANNEL_FLAG(image))
+ return 1;
+ else
+ return 0;
+}
+
+jxrc_t_pixelFormat jxr_get_pixel_format(jxr_image_t image)
+{
+ return image->ePixelFormat;
+}
+
+/*
+* $Log: flags.c,v $
+*
+* Revision 1.7 2009/05/29 12:00:00 microsoft
+* Reference Software v1.6 updates.
+*
+* Revision 1.6 2009/04/13 12:00:00 microsoft
+* Reference Software v1.5 updates.
+*
+* Revision 1.5 2008/03/06 02:05:48 steve
+* Distributed quantization
+*
+* Revision 1.4 2008/02/26 23:52:44 steve
+* Remove ident for MS compilers.
+*
+* Revision 1.3 2008/02/26 23:28:53 steve
+* Remove C99 requirements from the API.
+*
+* Revision 1.2 2007/11/26 01:47:15 steve
+* Add copyright notices per MS request.
+*
+* Revision 1.1 2007/06/06 17:19:12 steve
+* Introduce to CVS.
+*
+*/
+
diff --git a/jpegxr/init.c b/jpegxr/init.c
new file mode 100644
index 000000000..6123070a8
--- /dev/null
+++ b/jpegxr/init.c
@@ -0,0 +1,504 @@
+
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+***********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: init.c,v 1.23 2008/03/13 21:23:27 steve Exp $")
+#else
+#ident "$Id: init.c,v 1.23 2008/03/13 21:23:27 steve Exp $"
+#endif
+
+# include "jxr_priv.h"
+# include <stdlib.h>
+# include <assert.h>
+
+const int _jxr_abslevel_index_delta[7] = { 1, 0, -1, -1, -1, -1, -1 };
+
+static void clear_vlc_tables(jxr_image_t image)
+{
+ int idx;
+ for (idx = 0 ; idx < AbsLevelInd_COUNT ; idx += 1) {
+ image->vlc_table[idx].discriminant = 0;
+ image->vlc_table[idx].discriminant2 = 0;
+ image->vlc_table[idx].table = 0;
+ image->vlc_table[idx].deltatable = 0;
+ image->vlc_table[idx].delta2table = 0;
+ }
+}
+
+static struct jxr_image* __make_jxr(void)
+{
+ struct jxr_image*image = (struct jxr_image*) calloc(1, sizeof(struct jxr_image));
+ int idx;
+ image->user_flags = 0;
+ image->width1 = 0;
+ image->height1 = 0;
+ image->extended_width = 0;
+ image->extended_height = 0;
+ image->header_flags1 = 0;
+ image->header_flags2 = 0x80; /* SHORT_HEADER_FLAG=1 */
+ image->header_flags_fmt = 0;
+ image->bands_present = 0; /* Default ALL bands present */
+ image->num_channels = 0;
+ image->tile_index_table = 0;
+ image->tile_index_table_length = 0;
+ image->primary = 1;
+
+ clear_vlc_tables(image);
+
+ for (idx = 0 ; idx < MAX_CHANNELS ; idx += 1) {
+ image->strip[idx].up4 = 0;
+ image->strip[idx].up3 = 0;
+ image->strip[idx].up2 = 0;
+ image->strip[idx].up1 = 0;
+ image->strip[idx].cur = 0;
+ }
+
+ image->scaled_flag = 1;
+
+ image->out_fun = 0;
+
+ return image;
+}
+
+static void make_mb_row_buffer(jxr_image_t image, unsigned use_height)
+{
+ size_t block_count = EXTENDED_WIDTH_BLOCKS(image) * use_height;
+ int*data, *pred_dclp;
+ size_t idx;
+ int format_scale;
+ int ch;
+
+ image->mb_row_buffer[0] = (struct macroblock_s*) calloc(block_count, sizeof(struct macroblock_s));
+ data = (int*) calloc(block_count*256, sizeof(int));
+ pred_dclp = (int*) calloc(block_count*7, sizeof(int));
+ assert(image->mb_row_buffer[0]);
+ assert(data);
+ assert(pred_dclp);
+
+ for (idx = 0 ; idx < block_count ; idx += 1) {
+ image->mb_row_buffer[0][idx].data = data + 256*idx;
+ /* 7 (used as mutilpier) = 1 DC + 3 top LP + 3 left LP coefficients used for prediction */
+ image->mb_row_buffer[0][idx].pred_dclp = pred_dclp + 7*idx;
+ }
+
+ format_scale = 256;
+ if (image->use_clr_fmt == 2 /* YUV422 */) {
+ format_scale = 16 + 8*15;
+ } else if (image->use_clr_fmt == 1 /* YUV420 */) {
+ format_scale = 16 + 4*15;
+ }
+
+ for (ch = 1 ; ch < image->num_channels ; ch += 1) {
+ image->mb_row_buffer[ch] = (struct macroblock_s*) calloc(block_count, sizeof(struct macroblock_s));
+ data = (int*) calloc(block_count*format_scale, sizeof(int));
+ pred_dclp = (int*) calloc(block_count*7, sizeof(int));
+ assert(image->mb_row_buffer[ch]);
+ assert(data);
+ assert(pred_dclp);
+
+ for (idx = 0 ; idx < block_count ; idx += 1) {
+ image->mb_row_buffer[ch][idx].data = data + format_scale*idx;
+ image->mb_row_buffer[ch][idx].pred_dclp = pred_dclp + 7*idx;
+ }
+ }
+}
+
+/*
+* Allocate the macroblock strip store. Each macroblock points to 256
+* values that are either the 256 pixel values, or the DC, LP and HP
+* coefficients.
+*
+* DC/LP/HP arrangement -
+* The first word is the DC.
+* The next 15 are the LP coefficients.
+* The remaining 240 are HP coefficients.
+*/
+void _jxr_make_mbstore(jxr_image_t image, int up4_flag)
+{
+ int ch;
+
+ assert(image->strip[0].up4 == 0);
+ assert(image->strip[0].up3 == 0);
+ assert(image->strip[0].up2 == 0);
+ assert(image->strip[0].up1 == 0);
+ assert(image->strip[0].cur == 0);
+
+ assert(image->num_channels > 0);
+
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ unsigned idx;
+ if (up4_flag)
+ image->strip[ch].up4 = (struct macroblock_s*)
+ calloc(EXTENDED_WIDTH_BLOCKS(image), sizeof(struct macroblock_s));
+ image->strip[ch].up3 = (struct macroblock_s*)
+ calloc(EXTENDED_WIDTH_BLOCKS(image), sizeof(struct macroblock_s));
+ image->strip[ch].up2 = (struct macroblock_s*)
+ calloc(EXTENDED_WIDTH_BLOCKS(image), sizeof(struct macroblock_s));
+ image->strip[ch].up1 = (struct macroblock_s*)
+ calloc(EXTENDED_WIDTH_BLOCKS(image), sizeof(struct macroblock_s));
+ image->strip[ch].cur = (struct macroblock_s*)
+ calloc(EXTENDED_WIDTH_BLOCKS(image), sizeof(struct macroblock_s));
+
+ if (up4_flag) {
+ image->strip[ch].up4[0].data = (int*)calloc(256 * EXTENDED_WIDTH_BLOCKS(image), sizeof(int));
+ for (idx = 1 ; idx < EXTENDED_WIDTH_BLOCKS(image) ; idx += 1)
+ image->strip[ch].up4[idx].data = image->strip[ch].up4[idx-1].data + 256;
+ }
+ image->strip[ch].up3[0].data = (int*)calloc(256 * EXTENDED_WIDTH_BLOCKS(image), sizeof(int));
+ for (idx = 1 ; idx < EXTENDED_WIDTH_BLOCKS(image) ; idx += 1)
+ image->strip[ch].up3[idx].data = image->strip[ch].up3[idx-1].data + 256;
+
+ image->strip[ch].up2[0].data = (int*)calloc(256 * EXTENDED_WIDTH_BLOCKS(image), sizeof(int));
+ for (idx = 1 ; idx < EXTENDED_WIDTH_BLOCKS(image) ; idx += 1)
+ image->strip[ch].up2[idx].data = image->strip[ch].up2[idx-1].data + 256;
+
+ image->strip[ch].up1[0].data = (int*)calloc(256 * EXTENDED_WIDTH_BLOCKS(image), sizeof(int));
+ for (idx = 1 ; idx < EXTENDED_WIDTH_BLOCKS(image) ; idx += 1)
+ image->strip[ch].up1[idx].data = image->strip[ch].up1[idx-1].data + 256;
+
+ image->strip[ch].cur[0].data = (int*)calloc(256 * EXTENDED_WIDTH_BLOCKS(image), sizeof(int));
+ for (idx = 1 ; idx < EXTENDED_WIDTH_BLOCKS(image) ; idx += 1)
+ image->strip[ch].cur[idx].data = image->strip[ch].cur[idx-1].data + 256;
+
+ if (up4_flag) {
+ image->strip[ch].up4[0].pred_dclp = (int*)calloc(7*EXTENDED_WIDTH_BLOCKS(image), sizeof(int));
+ for (idx = 1 ; idx < EXTENDED_WIDTH_BLOCKS(image) ; idx += 1)
+ image->strip[ch].up4[idx].pred_dclp = image->strip[ch].up4[idx-1].pred_dclp + 7;
+ }
+
+ image->strip[ch].up3[0].pred_dclp = (int*)calloc(7*EXTENDED_WIDTH_BLOCKS(image), sizeof(int));
+ for (idx = 1 ; idx < EXTENDED_WIDTH_BLOCKS(image) ; idx += 1)
+ image->strip[ch].up3[idx].pred_dclp = image->strip[ch].up3[idx-1].pred_dclp + 7;
+
+ image->strip[ch].up2[0].pred_dclp = (int*)calloc(7*EXTENDED_WIDTH_BLOCKS(image), sizeof(int));
+ for (idx = 1 ; idx < EXTENDED_WIDTH_BLOCKS(image) ; idx += 1)
+ image->strip[ch].up2[idx].pred_dclp = image->strip[ch].up2[idx-1].pred_dclp + 7;
+
+ image->strip[ch].up1[0].pred_dclp = (int*)calloc(7*EXTENDED_WIDTH_BLOCKS(image), sizeof(int));
+ for (idx = 1 ; idx < EXTENDED_WIDTH_BLOCKS(image) ; idx += 1)
+ image->strip[ch].up1[idx].pred_dclp = image->strip[ch].up1[idx-1].pred_dclp + 7;
+
+ image->strip[ch].cur[0].pred_dclp = (int*)calloc(7*EXTENDED_WIDTH_BLOCKS(image), sizeof(int));
+ for (idx = 1 ; idx < EXTENDED_WIDTH_BLOCKS(image) ; idx += 1)
+ image->strip[ch].cur[idx].pred_dclp = image->strip[ch].cur[idx-1].pred_dclp + 7;
+
+ if(ch!= 0)
+ {
+ if(image->use_clr_fmt == 2 || image->use_clr_fmt == 1) /* 422 or 420 */
+ image->strip[ch].upsample_memory_x = (int*)calloc(16, sizeof(int));
+
+ if(image->use_clr_fmt == 1)/* 420 */
+ image->strip[ch].upsample_memory_y = (int*)calloc(8*EXTENDED_WIDTH_BLOCKS(image), sizeof(int));
+ }
+
+ }
+
+ /* If there is tiling (in columns) then allocate a tile buffer
+ that can hold an entire row of tiles. */
+ if (FREQUENCY_MODE_CODESTREAM_FLAG(image)) { /* FREQUENCY MODE */
+
+ make_mb_row_buffer(image, EXTENDED_HEIGHT_BLOCKS(image));
+
+ } else { /* SPATIAL */
+ if (INDEXTABLE_PRESENT_FLAG(image)) {
+ /* This means that the tiling flag is used */
+ unsigned max_tile_height = 0;
+ unsigned idx;
+ int format_scale;
+ int ch;
+ for (idx = 0 ; idx < image->tile_rows ; idx += 1) {
+ if (image->tile_row_height[idx] > max_tile_height)
+ max_tile_height = image->tile_row_height[idx];
+ }
+
+ make_mb_row_buffer(image, max_tile_height);
+
+ /* Save enough context MBs for 4 rows of
+ macroblocks. */
+
+ format_scale = 256;
+ if (image->use_clr_fmt == 2 /* YUV422 */) {
+ format_scale = 16 + 8*15;
+ } else if (image->use_clr_fmt == 1 /* YUV420 */) {
+ format_scale = 16 + 4*15;
+ }
+
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ int count = (ch==0)? 256 : format_scale;
+ image->mb_row_context[ch] = (struct macroblock_s*)
+ calloc(4*EXTENDED_WIDTH_BLOCKS(image), sizeof(struct macroblock_s));
+ image->mb_row_context[ch][0].data = (int*)
+ calloc(4*EXTENDED_WIDTH_BLOCKS(image)*count, sizeof(int));
+ for (idx = 1 ; idx < 4*EXTENDED_WIDTH_BLOCKS(image) ; idx += 1)
+ image->mb_row_context[ch][idx].data = image->mb_row_context[ch][idx-1].data+count;
+ }
+
+ }
+ }
+
+ /* since CBP processing is done at each row, need to save contexts is multiple tile columns */
+ image->model_hp_buffer = 0;
+ image->hp_cbp_model_buffer = 0;
+ if (image->tile_columns > 1) {
+ image->model_hp_buffer = (struct model_s*)
+ calloc(image->tile_columns, sizeof(struct model_s));
+ image->hp_cbp_model_buffer = (struct cbp_model_s*)
+ calloc(image->tile_columns, sizeof(struct cbp_model_s));
+ }
+
+ image->cur_my = -1;
+}
+
+jxr_image_t jxr_create_input(void)
+{
+ struct jxr_image*image = __make_jxr();
+
+ return image;
+}
+
+jxr_image_t jxr_create_image(int width, int height, unsigned char * windowing)
+{
+ struct jxr_image*image = __make_jxr();
+
+ if (width == 0 || height == 0)
+ return 0;
+
+ image = __make_jxr();
+
+ if (windowing[0] == 1) {
+ assert(((width+windowing[2]+windowing[4]) & 0x0f) == 0);
+ assert(((height+windowing[1]+windowing[3]) & 0x0f) == 0);
+ }
+ else {
+ windowing[1] = windowing[2] = 0;
+ windowing[3] = (((height + 15) >> 4) << 4) - height;
+ windowing[4] = (((width + 15) >> 4) << 4) - width;
+ }
+
+ image->width1 = width-1;
+ image->height1 = height-1;
+ image->extended_width = image->width1 + 1 + windowing[2] + windowing[4];
+ image->extended_height = image->height1 + 1 + windowing[1] + windowing[3];
+
+ image->dc_frame_uniform = 1;
+ image->lp_frame_uniform = 1;
+ image->lp_use_dc_qp = 0;
+ image->num_lp_qps = 1;
+ image->hp_use_lp_qp = 0;
+ image->hp_frame_uniform = 1;
+ image->num_hp_qps = 1;
+
+ image->window_extra_top = windowing[1];
+ image->window_extra_left = windowing[2];
+ image->window_extra_bottom = windowing[3];
+ image->window_extra_right = windowing[4];
+
+ return image;
+}
+
+void jxr_flag_SKIP_HP_DATA(jxr_image_t image, int flag)
+{
+ if (flag)
+ image->user_flags |= 0x0001;
+ else
+ image->user_flags &= ~0x0001;
+}
+
+void jxr_flag_SKIP_FLEX_DATA(jxr_image_t image, int flag)
+{
+ if (flag)
+ image->user_flags |= 0x0002;
+ else
+ image->user_flags &= ~0x0002;
+}
+
+void jxr_destroy(jxr_image_t image)
+{
+ int idx, plane_idx = 1;
+ if(image == NULL)
+ return;
+
+ if (ALPHACHANNEL_FLAG(image))
+ plane_idx = 2;
+
+ for (; plane_idx > 0; plane_idx --) {
+ jxr_image_t plane = (plane_idx == 1 ? image : image->alpha);
+
+ for (idx = 0 ; idx < plane->num_channels ; idx += 1) {
+ if (plane->strip[idx].up4) {
+ free(plane->strip[idx].up4[0].data);
+ free(plane->strip[idx].up4);
+ }
+ if (plane->strip[idx].up3) {
+ free(plane->strip[idx].up3[0].data);
+ free(plane->strip[idx].up3);
+ }
+ if (plane->strip[idx].up2) {
+ free(plane->strip[idx].up2[0].data);
+ free(plane->strip[idx].up2);
+ }
+ if (plane->strip[idx].up1) {
+ free(plane->strip[idx].up1[0].data);
+ free(plane->strip[idx].up1);
+ }
+ if (plane->strip[idx].cur) {
+ free(plane->strip[idx].cur[0].data);
+ free(plane->strip[idx].cur);
+ }
+ if(plane->strip[idx].upsample_memory_x)
+ free(plane->strip[idx].upsample_memory_x);
+ if(plane->strip[idx].upsample_memory_y)
+ free(plane->strip[idx].upsample_memory_y);
+
+ }
+
+ for (idx = 0 ; idx < plane->num_channels ; idx += 1) {
+ if (plane->mb_row_buffer[idx]) {
+ free(plane->mb_row_buffer[idx][0].data);
+ free(plane->mb_row_buffer[idx]);
+ }
+
+ if (plane->mb_row_context[idx]) {
+ free(plane->mb_row_context[idx][0].data);
+ free(plane->mb_row_context[idx]);
+ }
+ }
+
+ if (plane->model_hp_buffer) {
+ free(plane->model_hp_buffer);
+ }
+
+ if (plane->hp_cbp_model_buffer) {
+ free(plane->hp_cbp_model_buffer);
+ }
+
+ if(plane_idx == 1){
+ if (plane->tile_index_table)
+ free(plane->tile_index_table);
+ if (plane->tile_column_width)
+ free(plane->tile_column_width);
+ if (plane->tile_row_height)
+ free(plane->tile_row_height);
+ }
+ free(plane);
+ }
+}
+
+/*
+* $Log: init.c,v $
+* Revision 1.25 2009/05/29 12:00:00 microsoft
+* Reference Software v1.6 updates.
+*
+* Revision 1.24 2009/04/13 12:00:00 microsoft
+* Reference Software v1.5 updates.
+*
+* Revision 1.23 2008/03/13 21:23:27 steve
+* Add pipeline step for YUV420.
+*
+* Revision 1.22 2008/03/05 06:58:10 gus
+* *** empty log message ***
+*
+* Revision 1.21 2008/02/28 18:50:31 steve
+* Portability fixes.
+*
+* Revision 1.20 2008/02/26 23:52:44 steve
+* Remove ident for MS compilers.
+*
+* Revision 1.19 2008/01/04 17:07:35 steve
+* API interface for setting QP values.
+*
+* Revision 1.18 2007/11/26 01:47:15 steve
+* Add copyright notices per MS request.
+*
+* Revision 1.17 2007/11/22 19:02:05 steve
+* More fixes of color plane buffer sizes.
+*
+* Revision 1.16 2007/11/21 23:26:14 steve
+* make all strip buffers store MB data.
+*
+* Revision 1.15 2007/11/21 00:34:30 steve
+* Rework spatial mode tile macroblock shuffling.
+*
+* Revision 1.14 2007/11/15 17:44:13 steve
+* Frequency mode color support.
+*
+* Revision 1.13 2007/11/14 23:56:17 steve
+* Fix TILE ordering, using seeks, for FREQUENCY mode.
+*
+* Revision 1.12 2007/11/12 23:21:54 steve
+* Infrastructure for frequency mode ordering.
+*
+* Revision 1.11 2007/11/08 02:52:32 steve
+* Some progress in some encoding infrastructure.
+*
+* Revision 1.10 2007/11/05 02:01:12 steve
+* Add support for mixed row/column tiles.
+*
+* Revision 1.9 2007/11/01 21:09:40 steve
+* Multiple rows of tiles.
+*
+* Revision 1.8 2007/10/30 21:32:46 steve
+* Support for multiple tile columns.
+*
+* Revision 1.7 2007/09/08 01:01:43 steve
+* YUV444 color parses properly.
+*
+* Revision 1.6 2007/09/04 19:10:46 steve
+* Finish level1 overlap filtering.
+*
+* Revision 1.5 2007/08/15 01:54:11 steve
+* Add level2 filter to decoder.
+*
+* Revision 1.4 2007/08/04 00:15:31 steve
+* Allow width/height of 1 pixel.
+*
+* Revision 1.3 2007/07/21 00:25:48 steve
+* snapshot 2007 07 20
+*
+* Revision 1.2 2007/06/28 20:03:11 steve
+* LP processing seems to be OK now.
+*
+* Revision 1.1 2007/06/06 17:19:12 steve
+* Introduce to CVS.
+*
+*/
+
diff --git a/jpegxr/io.c b/jpegxr/io.c
new file mode 100644
index 000000000..aaef80f34
--- /dev/null
+++ b/jpegxr/io.c
@@ -0,0 +1,542 @@
+
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+***********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: io.c,v 1.14 2008/03/05 06:58:10 gus Exp $")
+#else
+#ident "$Id: io.c,v 1.14 2008/03/05 06:58:10 gus Exp $"
+#endif
+
+# include "jxr_priv.h"
+# include <assert.h>
+
+void _jxr_rbitstream_initialize(struct rbitstream*str, FILE*fd)
+{
+ str->bits_avail = 0;
+ str->fd = fd;
+ str->read_count = 0;
+}
+
+size_t _jxr_rbitstream_bitpos(struct rbitstream*str)
+{
+ return str->read_count*8 - str->bits_avail;
+}
+
+void _jxr_rbitstream_mark(struct rbitstream*str)
+{
+ assert(str->bits_avail == 0);
+ str->mark_stream_position = ftell(str->fd);
+ assert(str->mark_stream_position >= 0);
+ str->read_count = 0;
+}
+
+void _jxr_rbitstream_seek(struct rbitstream*str, uint64_t off)
+{
+ int rc;
+ assert(str->bits_avail == 0);
+ /* NOTE: Should be using fseek64? */
+ rc = fseek(str->fd, str->mark_stream_position + (long)off, SEEK_SET);
+ str->read_count = (size_t) off;
+ assert(rc >= 0);
+}
+
+/*
+* Cause the bitstream to consume enough bits that the next bit is on
+* a byte boundary. This is for getting alignment, which is sometimes
+* needed.
+*/
+void _jxr_rbitstream_syncbyte(struct rbitstream*str)
+{
+ str->bits_avail = 0;
+}
+
+/*
+* Get the next 8 bits from the input file and adjust the bitstream
+* pointers so that the bits can be read out.
+*/
+static int get_byte(struct rbitstream*str)
+{
+ int tmp;
+ assert(str->bits_avail == 0);
+ tmp = fgetc(str->fd);
+ if (tmp == EOF)
+ return EOF;
+
+ str->byte = tmp;
+ str->bits_avail = 8;
+ str->read_count += 1;
+#if 0
+ DEBUG(" in byte: 0x%02x (bitpos=%zd)\n",
+ str->byte, str->read_count*8-8);
+#endif
+ return 0;
+}
+
+/*
+* The following read integers of various width from the data input
+* stream. This handles the bit ordering and packing of the bits.
+*/
+int _jxr_rbitstream_uint1(struct rbitstream*str)
+{
+ if (str->bits_avail == 0) {
+ get_byte(str);
+ }
+
+ assert(str->bits_avail > 0);
+
+ str->bits_avail -= 1;
+ return (str->byte & (1 << str->bits_avail))? 1 : 0;
+}
+
+uint8_t _jxr_rbitstream_uint2(struct rbitstream*str)
+{
+ uint8_t tmp = 0;
+
+ tmp |= _jxr_rbitstream_uint1(str);
+ tmp <<= 1;
+ tmp |= _jxr_rbitstream_uint1(str);
+ return tmp;
+}
+
+uint8_t _jxr_rbitstream_uint3(struct rbitstream*str)
+{
+ uint8_t tmp = 0;
+
+ tmp |= _jxr_rbitstream_uint1(str);
+ tmp <<= 1;
+ tmp |= _jxr_rbitstream_uint1(str);
+ tmp <<= 1;
+ tmp |= _jxr_rbitstream_uint1(str);
+ return tmp;
+}
+
+uint8_t _jxr_rbitstream_uint4(struct rbitstream*str)
+{
+ uint8_t tmp;
+ int idx;
+
+ if (str->bits_avail == 0)
+ get_byte(str);
+
+ if (str->bits_avail == 4) {
+ str->bits_avail = 0;
+ return str->byte & 0x0f;
+ }
+
+ tmp = 0;
+ for (idx = 0 ; idx < 4 ; idx += 1) {
+ tmp <<= 1;
+ tmp |= _jxr_rbitstream_uint1(str);
+ }
+
+ return tmp;
+}
+
+uint8_t _jxr_rbitstream_uint6(struct rbitstream*str)
+{
+ uint8_t tmp;
+ int idx;
+
+ tmp = _jxr_rbitstream_uint4(str);
+ for (idx = 4 ; idx < 6 ; idx += 1) {
+ tmp <<= 1;
+ tmp |= _jxr_rbitstream_uint1(str);
+ }
+
+ return tmp;
+}
+
+uint8_t _jxr_rbitstream_uint8(struct rbitstream*str)
+{
+ uint8_t tmp;
+ int idx;
+
+ if (str->bits_avail == 0)
+ get_byte(str);
+
+ if (str->bits_avail == 8) {
+ str->bits_avail = 0;
+ return str->byte;
+ }
+
+ tmp = 0;
+ for (idx = 0 ; idx < 8 ; idx += 1) {
+ tmp <<= 1;
+ tmp |= _jxr_rbitstream_uint1(str);
+ }
+
+ return tmp;
+}
+
+uint16_t _jxr_rbitstream_uint12(struct rbitstream*str)
+{
+ uint16_t tmp = 0;
+
+ tmp = _jxr_rbitstream_uint8(str);
+ tmp <<= 4;
+ tmp |= _jxr_rbitstream_uint4(str);
+ return tmp;
+}
+
+uint16_t _jxr_rbitstream_uint15(struct rbitstream*str)
+{
+ uint16_t tmp = 0;
+
+ tmp = _jxr_rbitstream_uint8(str);
+ tmp <<= 4;
+ tmp |= _jxr_rbitstream_uint4(str);
+ tmp <<= 3;
+ tmp |= _jxr_rbitstream_uint3(str);
+ return tmp;
+}
+
+uint16_t _jxr_rbitstream_uint16(struct rbitstream*str)
+{
+ uint16_t tmp = 0;
+
+ tmp = _jxr_rbitstream_uint8(str);
+ tmp <<= 8;
+ tmp |= _jxr_rbitstream_uint8(str);
+ return tmp;
+}
+
+uint32_t _jxr_rbitstream_uint32(struct rbitstream*str)
+{
+ uint32_t tmp = 0;
+
+ tmp = _jxr_rbitstream_uint16(str);
+ tmp <<= 16;
+ tmp |= _jxr_rbitstream_uint16(str);
+ return tmp;
+}
+
+uint32_t _jxr_rbitstream_uintN(struct rbitstream*str, int N)
+{
+ uint32_t tmp = 0;
+ assert(N <= 32);
+
+ while (N > 0) {
+ tmp <<= 1;
+ tmp |= _jxr_rbitstream_uint1(str);
+ N -= 1;
+ }
+ return tmp;
+}
+
+int _jxr_rbitstream_intE(struct rbitstream*str, int code_size,
+ const unsigned char*codeb, const signed char*codev)
+{
+ int bits = 0;
+ unsigned val = 0;
+
+ while (codeb[val << (code_size-bits)] != bits) {
+ val <<= 1;
+ val |= _jxr_rbitstream_uint1(str);
+ bits += 1;
+ assert(bits <= code_size);
+ }
+
+ return codev[val << (code_size-bits)];
+}
+
+int64_t _jxr_rbitstream_intVLW(struct rbitstream*str)
+{
+ uint64_t val = _jxr_rbitstream_uint8(str);
+ if (val < 0xfb) {
+ uint64_t tmp = _jxr_rbitstream_uint8(str);
+ val = val*256 + tmp;
+
+ } else if (val == 0xfb) {
+ val = _jxr_rbitstream_uint32(str);
+
+ } else if (val == 0xfc) {
+ uint64_t tmp;
+ val = _jxr_rbitstream_uint32(str);
+ tmp = _jxr_rbitstream_uint32(str);
+ val = (val << (uint64_t)32) + tmp;
+
+ } else {
+ return 0;
+ }
+
+ return val;
+}
+
+void _jxr_wbitstream_initialize(struct wbitstream*str, FILE*fd)
+{
+ str->byte = 0;
+ str->bits_ready = 0;
+ str->fd = fd;
+ str->write_count = 0;
+}
+
+size_t _jxr_wbitstream_bitpos(struct wbitstream*str)
+{
+ return str->write_count*8 + str->bits_ready;
+}
+
+static void put_byte(struct wbitstream*str)
+{
+ assert(str->bits_ready == 8);
+ fputc(str->byte, str->fd);
+ str->byte = 0;
+ str->bits_ready = 0;
+ str->write_count += 1;
+}
+
+void _jxr_wbitstream_syncbyte(struct wbitstream*str)
+{
+ if (str->bits_ready > 0)
+ str->bits_ready = 8;
+}
+
+void _jxr_wbitstream_flush(struct wbitstream*str)
+{
+ _jxr_wbitstream_syncbyte(str);
+ if (str->bits_ready > 0)
+ put_byte(str);
+}
+
+void _jxr_wbitstream_uint1(struct wbitstream*str, int val)
+{
+ if (str->bits_ready == 8)
+ put_byte(str);
+
+ if (val)
+ str->byte |= 0x80 >> str->bits_ready;
+ str->bits_ready += 1;
+}
+
+void _jxr_wbitstream_uint2(struct wbitstream*str, uint8_t val)
+{
+ int idx;
+ for (idx = 0 ; idx < 2 ; idx += 1) {
+ _jxr_wbitstream_uint1(str, val & (0x02 >> idx));
+ }
+}
+
+void _jxr_wbitstream_uint3(struct wbitstream*str, uint8_t val)
+{
+ int idx;
+ for (idx = 0 ; idx < 3 ; idx += 1) {
+ _jxr_wbitstream_uint1(str, val & (0x04 >> idx));
+ }
+}
+
+void _jxr_wbitstream_uint4(struct wbitstream*str, uint8_t val)
+{
+ int idx;
+ for (idx = 0 ; idx < 4 ; idx += 1) {
+ _jxr_wbitstream_uint1(str, val & (0x08 >> idx));
+ }
+}
+
+void _jxr_wbitstream_uint6(struct wbitstream*str, uint8_t val)
+{
+ int idx;
+ for (idx = 0 ; idx < 6 ; idx += 1) {
+ _jxr_wbitstream_uint1(str, val & (0x20 >> idx));
+ }
+}
+
+void _jxr_wbitstream_uint8(struct wbitstream*str, uint8_t val)
+{
+ int idx;
+
+ if (str->bits_ready == 8)
+ put_byte(str);
+
+ if (str->bits_ready == 0) {
+ str->bits_ready = 8;
+ str->byte = val;
+ return;
+ }
+ for (idx = 0 ; idx < 8 ; idx += 1) {
+ _jxr_wbitstream_uint1(str, val & (0x80 >> idx));
+ }
+}
+
+void _jxr_wbitstream_uint12(struct wbitstream*str, uint16_t val)
+{
+ int idx;
+ for (idx = 0 ; idx < 12 ; idx += 1) {
+ _jxr_wbitstream_uint1(str, val & (0x800 >> idx));
+ }
+}
+
+void _jxr_wbitstream_uint15(struct wbitstream*str, uint16_t val)
+{
+ int idx;
+ for (idx = 0 ; idx < 15 ; idx += 1) {
+ _jxr_wbitstream_uint1(str, val & (0x4000 >> idx));
+ }
+}
+
+void _jxr_wbitstream_uint16(struct wbitstream*str, uint16_t val)
+{
+ _jxr_wbitstream_uint8(str, val >> 8);
+ _jxr_wbitstream_uint8(str, val >> 0);
+}
+
+void _jxr_wbitstream_uint32(struct wbitstream*str, uint32_t val)
+{
+ _jxr_wbitstream_uint8(str, val >> 24);
+ _jxr_wbitstream_uint8(str, val >> 16);
+ _jxr_wbitstream_uint8(str, val >> 8);
+ _jxr_wbitstream_uint8(str, val >> 0);
+}
+
+void _jxr_wbitstream_uintN(struct wbitstream*str, uint32_t val, int N)
+{
+ assert(N <= 32);
+ while (N > 0) {
+ _jxr_wbitstream_uint1(str, 1 & (val >> (N-1)));
+ N -= 1;
+ }
+}
+
+void _jxr_wbitstream_intVLW(struct wbitstream*str, uint64_t val)
+{
+ if (val == 0) {
+ _jxr_wbitstream_uint8(str, 0xfe);
+ } else if (val < 0xfb00) {
+ _jxr_wbitstream_uint16(str, (uint16_t)val);
+ } else if (val < 0x100000000ULL) {
+ _jxr_wbitstream_uint8(str, 0xfb);
+ _jxr_wbitstream_uint32(str, (uint32_t)val);
+ } else {
+ _jxr_wbitstream_uint8(str, 0xfc);
+ _jxr_wbitstream_uint32(str, val >> 32ULL);
+ _jxr_wbitstream_uint32(str, val >> 0ULL);
+ }
+}
+
+void _jxr_wbitstream_mark(struct wbitstream*str)
+{
+ if (str->bits_ready == 8)
+ _jxr_wbitstream_flush(str);
+
+ assert(str->bits_ready == 0);
+ /* str->mark_stream_position = ftell(str->fd); */
+ str->write_count = 0;
+}
+
+const char* _jxr_vlc_index_name(int vlc)
+{
+ switch (vlc) {
+ case AbsLevelIndDCLum: return "AbsLevelIndDCLum";
+ case AbsLevelIndDCChr: return "AbsLevelIndDCChr";
+ case DecFirstIndLPLum: return "DecFirstIndLPLum";
+ case AbsLevelIndLP0: return "AbsLevelIndLP0";
+ case AbsLevelIndLP1: return "AbsLevelIndLP1";
+ case AbsLevelIndHP0: return "AbsLevelIndHP0";
+ case AbsLevelIndHP1: return "AbsLevelIndHP1";
+ case DecIndLPLum0: return "DecIndLPLum0";
+ case DecIndLPLum1: return "DecIndLPLum1";
+ case DecFirstIndLPChr: return "DecFirstIndLPChr";
+ case DecIndLPChr0: return "DecIndLPChr0";
+ case DecIndLPChr1: return "DecIndLPChr1";
+ case DecNumCBP: return "DecNumCBP";
+ case DecNumBlkCBP: return "DecNumBlkCBP";
+ case DecIndHPLum0: return "DecIndHPLum0";
+ case DecIndHPLum1: return "DecIndHPLum1";
+ case DecFirstIndHPLum: return "DecFirstIndHPLum";
+ case DecFirstIndHPChr: return "DecFirstIndHPChr";
+ case DecIndHPChr0: return "DecIndHPChr0";
+ case DecIndHPChr1: return "DecIndHPChr1";
+ default: return "?????";
+ }
+}
+
+
+/*
+* $Log: io.c,v $
+* Revision 1.16 2009/05/29 12:00:00 microsoft
+* Reference Software v1.6 updates.
+*
+* Revision 1.15 2009/04/13 12:00:00 microsoft
+* Reference Software v1.5 updates.
+*
+* Revision 1.14 2008/03/05 06:58:10 gus
+* *** empty log message ***
+*
+* Revision 1.13 2008/02/28 18:50:31 steve
+* Portability fixes.
+*
+* Revision 1.12 2008/02/26 23:52:44 steve
+* Remove ident for MS compilers.
+*
+* Revision 1.11 2007/12/07 01:20:34 steve
+* Fix adapt not adapting on line ends.
+*
+* Revision 1.10 2007/12/06 17:53:35 steve
+* No longer need bitval dump.
+*
+* Revision 1.9 2007/11/30 01:50:58 steve
+* Compression of DCONLY GRAY.
+*
+* Revision 1.8 2007/11/26 01:47:15 steve
+* Add copyright notices per MS request.
+*
+* Revision 1.7 2007/11/19 18:22:34 steve
+* Skip ESCaped FLEXBITS tiles.
+*
+* Revision 1.6 2007/11/14 23:56:17 steve
+* Fix TILE ordering, using seeks, for FREQUENCY mode.
+*
+* Revision 1.5 2007/11/08 19:38:38 steve
+* Get stub DCONLY compression to work.
+*
+* Revision 1.4 2007/11/08 02:52:32 steve
+* Some progress in some encoding infrastructure.
+*
+* Revision 1.3 2007/08/15 01:54:11 steve
+* Add level2 filter to decoder.
+*
+* Revision 1.2 2007/06/21 17:31:22 steve
+* Successfully parse LP components.
+*
+* Revision 1.1 2007/06/06 17:19:12 steve
+* Introduce to CVS.
+*
+*/
+
diff --git a/jpegxr/jpegxr.c b/jpegxr/jpegxr.c
new file mode 100644
index 000000000..742c0ed56
--- /dev/null
+++ b/jpegxr/jpegxr.c
@@ -0,0 +1,1754 @@
+/*
+**
+** $Id: jpegxr.c,v 1.4 2008/05/25 09:40:46 thor Exp $
+**
+** This is the main program
+**
+*/
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+***********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: jpegxr.c,v 1.4 2008/05/25 09:40:46 thor Exp $")
+#else
+#ident "$Id: jpegxr.c,v 1.4 2008/05/25 09:40:46 thor Exp $"
+#endif
+
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include <ctype.h>
+# include "jpegxr.h"
+# include "file.h"
+# include <assert.h>
+
+/* MSC doesn't include getopt, so if compiling with MSC then get it
+from our local copy. Otherwise use the C library version. */
+#ifdef _MSC_VER
+# include "getopt.h"
+/* MSVC doesn't have strcasecmp. Use _stricmp instead */
+# define strcasecmp _stricmp
+#else
+# include <unistd.h>
+#endif
+
+char*path_out = 0;
+char*path_debug = 0;
+char*quant_uniform = 0;
+
+char*flags[128];
+int nflags = 0;
+
+static jxr_bands_present_t bands_present = JXR_BP_ALL;
+static int trim_flexbits = 0;
+static int overlap_filter = 1;
+static jxr_color_fmt_t internal_color_fmt = JXR_YUV444;
+static int disable_tile_overlap = 0;
+static int frequency_mode_flag = 0;
+static int profile_idc = 111;
+static int level_idc = 255;
+static int long_word_flag_setting = 1;
+static int alpha_mode = 2;
+static int padded_format = 0;
+static unsigned char window_params[5] = {0,0,0,0,0};
+static jxrc_t_pixelFormat pxl_fmt;
+
+/* Set this flag if the encoder should try to use the USE_DC_QP and
+USE_LP_QP flags when it can. */
+static int use_dc_qp_flag = 0;
+
+# define MAX_CHANNELS 16
+static unsigned char quant_per_channel[MAX_CHANNELS];
+static unsigned quant_per_channel_count = 0;
+
+# define MAX_TILES 4096
+static unsigned tile_rows = 1;
+static unsigned tile_columns = 1;
+static unsigned tile_width_in_MB[MAX_TILES * 2] = {0};
+static unsigned tile_height_in_MB[MAX_TILES * 2] = {0};
+
+static unsigned char shift_bits = 0;
+static unsigned char len_mantissa = 10;
+static char exp_bias = 4;
+
+static raw_info raw_info_t;
+
+static int main_compress(const char*path);
+static int main_decompress(const char*path);
+
+/* This function parses a qp input file and returns an array of
+jxr_tile_qp with the results. The parser needs to know the tile
+dimensions of the image in order to get the right number of
+tiles. */
+extern int qp_parse_file(FILE*fd, jxr_image_t image);
+/* Path to the input quant file. */
+static const char*quant_path = 0;
+
+int main(int argc, char*argv[])
+{
+ int compress_flag = 0;
+ int flag;
+ int derive_flag = 0;
+ char*cp_temp;
+ int idx;
+
+ /* initialize raw input */
+ raw_info_t.is_raw = 0;
+ raw_info_t.raw_width = 0;
+ raw_info_t.raw_height = 0;
+ raw_info_t.raw_format = 3;
+ raw_info_t.raw_bpc = 8;
+
+ while ((flag = getopt(argc, argv, "b:cphmwdra:D:f:F:l:o:U:C:R:P:L:q:Q:X:W:H:M:B:s:")) != -1) {
+ switch (flag) {
+ case 'b': /* Bands present */
+ if (strcasecmp(optarg,"ALL") == 0)
+ bands_present = JXR_BP_ALL;
+ else if (strcasecmp(optarg,"NOFLEXBITS") == 0)
+ bands_present = JXR_BP_NOFLEXBITS;
+ else if (strcasecmp(optarg,"NOHIGHPASS") == 0)
+ bands_present = JXR_BP_NOHIGHPASS;
+ else if (strcasecmp(optarg,"DCONLY") == 0)
+ bands_present = JXR_BP_DCONLY;
+ else {
+ fprintf(stderr, "Invalid bands flag: %s\n", optarg);
+ fprintf(stderr, "Should be one of: ALL, NOFLEXBITS, NOHIGHPASS, DCONLY\n");
+ return 1;
+ }
+ break;
+
+ case 'c':
+ compress_flag = 1;
+ break;
+
+ case 'd':
+ derive_flag = 1;
+ break;
+
+ case 'D':
+ path_debug = optarg;
+ break;
+
+ case 'p':
+ padded_format = 1;
+ break;
+
+ case 'f':
+ if (strcmp(optarg, "USE_DC_QP") == 0) {
+ use_dc_qp_flag = 1;
+ } else if (strcmp(optarg,"YUV444") == 0) {
+ internal_color_fmt = JXR_YUV444;
+ } else if (strcmp(optarg,"YUV422") == 0) {
+ internal_color_fmt = JXR_YUV422;
+ } else if (strcmp(optarg,"YUV420") == 0) {
+ internal_color_fmt = JXR_YUV420;
+ } else {
+ }
+ break;
+
+ case 'F':
+ trim_flexbits = strtoul(optarg, 0, 10);
+ if (trim_flexbits > 15) {
+ trim_flexbits = 15;
+ }
+ break;
+
+ case 'h':
+ disable_tile_overlap = 1;
+ break;
+
+ case 'm':
+ frequency_mode_flag = 1;
+ break;
+
+ case 'w':
+ long_word_flag_setting = 0;
+ break;
+
+ case 'l':
+ overlap_filter = strtoul(optarg, 0, 10);
+ if (overlap_filter >= 3) {
+ fprintf(stderr, "Invalid overlap filter flag. Got %d\n", overlap_filter);
+ return 1;
+ }
+ break;
+
+ case 'X':
+ flags[nflags] = optarg;
+ nflags += 1;
+ break;
+
+ case 'o':
+ path_out = optarg;
+ break;
+
+ case 's':
+ cp_temp = optarg;
+ window_params[0] = 1;
+ unsigned read_value;
+ for (idx = 0 ; idx < 4 ; idx += 1) {
+ read_value = (unsigned) strtoul(cp_temp, &cp_temp, 10);
+ assert(read_value >= 0 && read_value < 64);
+ window_params[idx + 1] = (unsigned char) read_value;
+ if (*cp_temp == ':')
+ cp_temp += 1;
+ }
+ break;
+
+ case 'U':
+ cp_temp = optarg;
+ tile_rows = (unsigned) strtoul(cp_temp, &cp_temp, 10);
+ if (tile_rows > MAX_TILES)
+ tile_rows = MAX_TILES;
+ if (*cp_temp == ':') {
+ cp_temp += 1;
+ tile_columns = (unsigned) strtoul(cp_temp, &cp_temp, 10);
+ if (tile_columns > MAX_TILES)
+ tile_columns = MAX_TILES;
+ }
+ else {
+ tile_columns = tile_rows;
+ }
+
+ break;
+
+ case 'a':
+ alpha_mode = strtoul(optarg, 0, 10);
+ if(alpha_mode <0 || alpha_mode > 2)
+ assert(0);
+ break;
+
+ case 'C':
+ cp_temp = optarg;
+ for (tile_columns = 0 ; tile_columns < MAX_TILES ; tile_columns++) {
+ tile_width_in_MB[tile_columns] = (unsigned) strtoul(cp_temp, &cp_temp, 10);
+ if (*cp_temp == ':')
+ cp_temp += 1;
+ else
+ break;
+ }
+ tile_columns++;
+ break;
+
+ case 'R':
+ cp_temp = optarg;
+ for (tile_rows = 0 ; tile_rows < MAX_TILES ; tile_rows++) {
+ tile_height_in_MB[tile_rows] = (unsigned) strtoul(cp_temp, &cp_temp, 10);
+ if (*cp_temp == ':')
+ cp_temp += 1;
+ else
+ break;
+ }
+ tile_rows++;
+ break;
+
+
+ case 'q': { /* Uniform quantization */
+ quant_uniform = optarg;
+ quant_per_channel_count = 0;
+ int last_q = 0;
+ cp_temp = optarg;
+ for (idx = 0 ; idx < MAX_CHANNELS ; idx += 1) {
+ if (*cp_temp == 0) {
+ quant_per_channel[idx] = quant_per_channel[last_q];
+ continue;
+ }
+ last_q = idx;
+ quant_per_channel_count += 1;
+ quant_per_channel[idx] = (unsigned char) strtoul(cp_temp, &cp_temp, 10);
+ if (*cp_temp == ':')
+ cp_temp += 1;
+ }
+ break;
+ }
+
+ case 'Q':
+ quant_path = optarg;
+ break;
+
+ case 'P':
+ profile_idc = strtoul(optarg, 0, 10);
+ if (profile_idc > 255) {
+ profile_idc = 255;
+ }
+ if (profile_idc < 0) {
+ profile_idc = 0;
+ }
+ break;
+
+ case 'L':
+ level_idc = strtoul(optarg, 0, 10);
+ if (level_idc > 255) {
+ level_idc = 255;
+ }
+ if (level_idc < 0) {
+ level_idc = 0;
+ }
+ break;
+
+ case 'r':
+ raw_info_t.is_raw = 1;
+ break;
+
+ case 'W':
+ raw_info_t.raw_width = (unsigned int)atoi(optarg);
+ break;
+
+ case 'H':
+ raw_info_t.raw_height = (unsigned int)atoi(optarg);
+ break;
+
+ case 'M':
+ raw_info_t.raw_format = (unsigned char)atoi(optarg);
+ if ((raw_info_t.raw_format < 3) || (raw_info_t.raw_format > 34)) {
+ fprintf(stderr, "Invalid raw format.\n");
+ return -1;
+ }
+ break;
+
+ case 'B':
+ raw_info_t.raw_bpc = (unsigned char)atoi(optarg);
+ if ((8 != raw_info_t.raw_bpc) && (10 != raw_info_t.raw_bpc) && (16 != raw_info_t.raw_bpc)) {
+ fprintf(stderr, "Invalid bit/channel.\n");
+ return -1;
+ }
+ break;
+
+ case '?':
+ fprintf(stderr, "Abort from bad flag.\n");
+ return -1;
+ }
+ }
+
+ if (optind >= argc) {
+ fprintf(stderr,"Usage: %s <flags> <input_file.jxr>\n"
+ " DECODER FLAGS:\n"
+ " [-o <path>] [-w] [-P 44|55|66|111] [-L 4|8|16|32|64|128|255]\n"
+ "\n"
+ "\t-o: selects output file name (.raw/.tif/.pnm)\n"
+ "\t (PNM output can be used only for 24bpp RGB and 8bpp gray Output)\n"
+ "\t (TIF output can be used for all formats except the following:\n"
+ "\t N channels, BGR, RGBE, YCC, CMYKDirect & Premultiplied RGB)\n"
+ "\t (RAW output can be used for all formats)\n"
+ "\t-w: tests whether LONG_WORD_FLAG needs to be equal to TRUE\n"
+ "\t (will still decode the image)\n"
+ "\t-P: selects the maximum accepted profile value\n"
+ "\t (44:Sub-Baseline|55:Baseline|66:Main|111:Advanced)\n"
+ "\t-L: selects the maximum accepted level value\n"
+ "\t (4|8|16|32|64|128)\n"
+ "\n"
+ " ENCODER FLAGS: (Temporary (.tmp) files may be used in encoding)\n"
+ " -c [-o <path>] [-b ALL|NOFLEXBITS|NOHIGHPASS|DCONLY] [-a 0|1|2] [-p]\n"
+ " [-f YUV444|YUV422|YUV420] [-F bits] [-h] [-m] [-l 0|1|2]\n"
+ " [-q q1[:q2[:q3]]] [-Q <path>] [-d] [-w] [-U rows:columns]\n"
+ " [-C width1[:width2>[:width3...]]] [-R height1[:height2[:height3...]]]\n"
+ " [-P 44|55|66|111] [-L 4|8|16|32|64|128|255] [-s top|left|bottom|right]\n"
+ " [-r -W width -H height -M 3|4|...|18 [-B 8|16]]\n"
+ "\n"
+ "\t-c: selects encoding instead of decoding\n"
+ "\t this flag is necessary for encoding\n"
+ "\t-o: selects the output file name (.jxr)\n"
+ "\t-b: selects the bands to encode\n"
+ "\t (ALL<Default>|NOFLEXBITS|NOHIGHPASS|DCONLY)\n"
+ "\t-a: selects encoder alpha mode\n"
+ "\t (0: no alpha|1:interleaved alpha|2:separate alpha) \n"
+ "\t Default: For tif input files, based on the information in the\n"
+ "\t PhotometricInterpretation and SamplesPerPixel tags in the container,\n"
+ "\t the encoder chooses an input pixel format. If the number\n"
+ "\t of components is 4 and photometric is 2, RGBA input is inferred and \n"
+ "\t the encoder assumes the presence of an alpha channel while encoding.\n"
+ "\t If the number of components is 5 and photometric is 5, CMYKA input is\n"
+ "\t inferred. In both these cases, the encoder infers a pixel format with\n"
+ "\t an alpha channel. In such cases, the default alpha encoder mode is 2.\n"
+ "\t For raw input files, when the -M parameter specified by the user is\n"
+ "\t 9, 10, 11, 12 13, 14, 23, 24, 25, 26 or 28,\n"
+ "\t the default alpha encoder mode is 2\n"
+ "\t In all other cases, the default alpha encoder mode is 0.\n"
+ "\t-p: selects an input pixel format with a padding channel\n"
+ "\t With tif input, when the encoder infers that the input file has an\n"
+ "\t alpha channel (see explanation for -a), this flag causes the encoder\n"
+ "\t to treat the alpha channel as a padding channel instead\n"
+ "\t-f: selects the internal color format\n"
+ "\t (YUV444<Default>|YUV422|YUV420)\n"
+ "\t-F: selects the number of flexbits to trim\n"
+ "\t (0<default> - 15)\n"
+ "\t-h: selects hard tile boundaries\n"
+ "\t (soft tile boundaries by default)\n"
+ "\t-m: encode in frequency order codestream\n"
+ "\t (spatial order by default)\n"
+ "\t-l: selects the overlapped block filtering\n"
+ "\t (0:off|1:HP only<Default>|2:all)\n"
+ "\n"
+ "\t-q: sets the quantization values separately, or one per band\n"
+ "\t (0<default, lossless> - 255)\n"
+ "\t-Q: specifies a file containing detailed quantization information\n"
+ "\t See sample.qp\n"
+ "\t-d: selects quantization for U/V channels derived from Y channel\n"
+ "\n"
+ "\t-U: selects uniform tile sizes\n"
+ "\t-C: selects the number of tile columns and the width of each\n"
+ "\t-R: selects the number of tile rows and the height of each\n"
+ "\n"
+ "\t-w: sets LONG_WORD_FLAG equal to FALSE\n"
+ "\t-P: selects the profile value\n"
+ "\t (44:Sub-Baseline|55:Baseline|66:Main|111:Advanced)\n"
+ "\t-L: selects the level value\n"
+ "\t (4|8|16|32|64|128)\n"
+ "\t-s: sets the top, left, bottom, and right margins\n"
+ "\n"
+ "\t-r: selects encoding with RAW images\n"
+ "\t must also specify -W, -H and -M, optional -B\n"
+ "\t-W: RAW image width when encoding with RAW images\n"
+ "\t-H: RAW image height when encoding with RAW images\n"
+ "\t-M: RAW image format when encoding with RAW images\n"
+ "\t 3: 3-channel\n"
+ "\t 4: 4-channel\n"
+ "\t 5: 5-channel\n"
+ "\t 6: 6-channel\n"
+ "\t 7: 7-channel\n"
+ "\t 8: 8-channel\n"
+ "\t 9: 3-channel Alpha\n"
+ "\t 10: 4-channel Alpha\n"
+ "\t 11: 5-channel Alpha\n"
+ "\t 12: 6-channel Alpha\n"
+ "\t 13: 7-channel Alpha\n"
+ "\t 14: 8-channel Alpha\n"
+ "\t 15: 32bppRGBE\n"
+ "\t 16: 16bppBGR555\n"
+ "\t 17: 16bppBGR565\n"
+ "\t 18: 32bppBGR101010\n"
+ "\t 19: YCC420\n"
+ "\t 20: YCC422\n"
+ "\t 21: YCC444\n"
+ "\t 22: YCC444 Fixed Point\n"
+ "\t 23: YCC420 Alpha\n"
+ "\t 24: YCC422 Alpha\n"
+ "\t 25: YCC444 Alpha\n"
+ "\t 26: YCC444 Fixed Point Alpha\n"
+ "\t 27: CMYKDIRECT\n"
+ "\t 28: CMYKDIRECT Alpha\n"
+ "\t 29: 24bppBGR\n"
+ "\t 30: 32bppBGR\n"
+ "\t 31: 32bppBGRA\n"
+ "\t 32: 32bppPBGRA\n"
+ "\t 33: 64bppPRGBA\n"
+ "\t 34: 128bppPRGBAFloat\n"
+ "\t-B: RAW image bit/channel when encoding with RAW images\n"
+ "\t 8: 8-bit/channel (default)\n"
+ "\t 10: 10-bit/channel\n"
+ "\t 16: 16-bit/channel\n"
+ "\n",
+ argv[0]);
+ return 1;
+ }
+
+ /*
+ ** start mod thor: Derived quantization as in the DPK
+ */
+ if (derive_flag) {
+ int idx = quant_per_channel[0];
+ int idxuv = idx;
+ switch (internal_color_fmt) {
+ case JXR_YUV444:
+ if (idx < 16) {
+ idxuv = idx * 2;
+ } else if (idx <= 48) {
+ idxuv = idx + 18;
+ } else {
+ idxuv = idx + 18 + 2;
+ }
+ quant_per_channel_count = 3;
+ break;
+ case JXR_YUV422:
+ if (idx < 16) {
+ idxuv = idx + ((idx + 1) >> 1);
+ } else if (idx <= 48) {
+ idxuv = idx + 8;
+ } else {
+ idxuv = idx + 8 + 2;
+ }
+ quant_per_channel_count = 3;
+ break;
+ case JXR_YUV420:
+ if (idx < 16) {
+ idxuv = idx + ((idx + 2) >> 2);
+ } else if (idx <= 48) {
+ idxuv = idx + 4;
+ } else {
+ idxuv = idx + 4 + 2;
+ }
+ quant_per_channel_count = 3;
+ break;
+ default:
+ idxuv = idx;
+ break;
+ }
+ for(idx = 1;idx < MAX_CHANNELS;idx++) {
+ quant_per_channel[idx] = idxuv;
+ }
+ }
+ /*
+ ** End mod thor
+ */
+
+ if(disable_tile_overlap)
+ assert(compress_flag);
+
+ if (frequency_mode_flag)
+ assert(compress_flag);
+
+ if (compress_flag)
+ return main_compress(argv[optind]);
+ else
+ return main_decompress(argv[optind]);
+}
+
+int setup_image_params(jxr_image_t *ptr_image, void *input_handle, int alpha_mode, int alpha_plane)
+{
+ int rc = 0;
+
+ int wid, hei, ncomp, bpi;
+ short sf, photometric;
+ int padBytes;
+ get_file_parameters(input_handle, &wid, &hei, &ncomp, &bpi, &sf, &photometric, &padBytes);
+
+ wid -= (window_params[2] + ((window_params[4] >> 4) << 4));
+ assert(wid > 0);
+ hei -= (window_params[1] + ((window_params[3] >> 4) << 4));
+ assert(hei > 0);
+
+ /* Create a stub image. */
+ jxr_image_t image = jxr_create_image(wid, hei, window_params);
+ *ptr_image = image;
+
+ if (!raw_info_t.is_raw) {
+ /* Guess a color format from the number of components. */
+ if(!alpha_plane)
+ {
+ switch (ncomp + padBytes) {
+ case 1:
+ jxr_set_INTERNAL_CLR_FMT(image, JXR_YONLY, 1);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_YONLY);
+ break;
+ case 3:
+ jxr_set_INTERNAL_CLR_FMT(image, internal_color_fmt, 3);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_RGB);
+ break;
+ case 4:
+ if (photometric == 5){
+ jxr_set_INTERNAL_CLR_FMT(image, JXR_YUVK, 4);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_CMYK);
+ }
+ else if (photometric == 2){ /* RGB_NULL */
+ jxr_set_INTERNAL_CLR_FMT(image, internal_color_fmt, 3);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_RGB);
+ }
+ break;
+ case 5:
+ if (photometric == 5){ /* CMYKA */
+ jxr_set_INTERNAL_CLR_FMT(image, JXR_YUVK, 4);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_CMYK);
+ }
+ break;
+ default:
+ jxr_set_INTERNAL_CLR_FMT(image, JXR_NCOMPONENT, ncomp);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_NCOMPONENT);
+ break;
+ }
+ }
+ else
+ {
+ jxr_set_INTERNAL_CLR_FMT(image, JXR_YONLY, 1);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_YONLY);
+ }
+
+ switch (bpi) {
+ case 1:
+ if (photometric) /*white is 1 */
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD1WHITE1);
+ else
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD1BLACK1);
+ break;
+ case 8:
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD8);
+ break;
+ case 16:
+ if (sf == 1) {
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD16);
+ jxr_set_SHIFT_BITS(image, shift_bits);
+ }
+ else if (sf == 2) {
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD16S);
+ jxr_set_SHIFT_BITS(image, shift_bits);
+ }
+ else if (sf == 3)
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD16F);
+ break;
+ case 32:
+ if (sf == 2) {
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD32S);
+ jxr_set_SHIFT_BITS(image, shift_bits);
+ }
+ else if (sf == 3) {
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD32F);
+ jxr_set_FLOAT(image, len_mantissa, exp_bias);
+ }
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+ else { /* raw */
+ if ((raw_info_t.raw_format >= 3) && (raw_info_t.raw_format <= 14)) { /* N-channel and N-channel Alpha*/
+ if(!alpha_plane)
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_NCOMPONENT);
+ else
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_YONLY);
+ if (raw_info_t.raw_format <= 8)
+ jxr_set_INTERNAL_CLR_FMT(image, JXR_NCOMPONENT, ncomp); /* N-channel */
+ else
+ {
+ if(!alpha_plane)
+ jxr_set_INTERNAL_CLR_FMT(image, JXR_NCOMPONENT, ncomp - 1); /* N-channel Alpha */
+ else
+ jxr_set_INTERNAL_CLR_FMT(image, JXR_YONLY, 1); /* N-channel Alpha */
+ }
+ if (8 == raw_info_t.raw_bpc)
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD8);
+ else
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD16);
+ }
+ else if (raw_info_t.raw_format == 15) {
+ jxr_set_INTERNAL_CLR_FMT(image, JXR_YUV444, 1);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_RGBE);
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD8);
+ }
+ else if (raw_info_t.raw_format == 16) {
+ jxr_set_INTERNAL_CLR_FMT(image, internal_color_fmt, 1);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_RGB);
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD5);
+ }
+ else if (raw_info_t.raw_format == 17) {
+ jxr_set_INTERNAL_CLR_FMT(image, internal_color_fmt, 1);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_RGB);
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD565);
+ }
+ else if (raw_info_t.raw_format == 18) {
+ jxr_set_INTERNAL_CLR_FMT(image, internal_color_fmt, 1);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_RGB);
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD10);
+ }
+ else if (raw_info_t.raw_format == 19 || raw_info_t.raw_format == 23) {
+ if(!alpha_plane)
+ {
+ jxr_set_INTERNAL_CLR_FMT(image, JXR_YUV420, 3);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_YUV420);
+ }
+ else {
+ jxr_set_INTERNAL_CLR_FMT(image, JXR_YONLY, 1);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_YONLY);
+ }
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD8);
+ }
+ else if (raw_info_t.raw_format == 20 || raw_info_t.raw_format == 24) {
+ if(!alpha_plane)
+ {
+ jxr_set_INTERNAL_CLR_FMT(image, JXR_YUV422, 3);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_YUV422);
+ }
+ else
+ {
+ jxr_set_INTERNAL_CLR_FMT(image, JXR_YONLY, 1);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_YONLY);
+ }
+ if (8 == raw_info_t.raw_bpc)
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD8);
+ else if (10 == raw_info_t.raw_bpc)
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD10);
+ else
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD16);
+ }
+ else if (raw_info_t.raw_format == 21 || raw_info_t.raw_format == 25) {
+ if(!alpha_plane)
+ {
+ jxr_set_INTERNAL_CLR_FMT(image, internal_color_fmt, 3);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_YUV444);
+ }
+ else
+ {
+ jxr_set_INTERNAL_CLR_FMT(image, JXR_YONLY, 1);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_YONLY);
+ }
+ if (8 == raw_info_t.raw_bpc)
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD8);
+ else if (10 == raw_info_t.raw_bpc)
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD10);
+ else
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD16);
+ }
+ else if (raw_info_t.raw_format == 22 || raw_info_t.raw_format == 26) {
+ if(!alpha_plane)
+ {
+ jxr_set_INTERNAL_CLR_FMT(image, JXR_YUV444, 3);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_YUV444);
+ }
+ else
+ {
+ jxr_set_INTERNAL_CLR_FMT(image, JXR_YONLY, 1);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_YONLY);
+ }
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD16S);
+ }
+ else if (raw_info_t.raw_format == 27 || raw_info_t.raw_format == 28) {
+ if(!alpha_plane)
+ {
+ jxr_set_INTERNAL_CLR_FMT(image, JXR_YUVK, 4);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_CMYKDIRECT);
+ }
+ else
+ {
+ jxr_set_INTERNAL_CLR_FMT(image, JXR_YONLY, 1);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_YONLY);
+ }
+ if (8 == raw_info_t.raw_bpc)
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD8);
+ else
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD16);
+ }
+ else if (raw_info_t.raw_format == 29) {
+ jxr_set_INTERNAL_CLR_FMT(image, internal_color_fmt, 3);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_RGB);
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD8);
+ }
+ else if (raw_info_t.raw_format == 30) {
+ jxr_set_INTERNAL_CLR_FMT(image, internal_color_fmt, 3);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_RGB);
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD8);
+ }
+ else if (raw_info_t.raw_format == 31) {
+ if(!alpha_plane)
+ {
+ jxr_set_INTERNAL_CLR_FMT(image, internal_color_fmt, 3);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_RGB);
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD8);
+ }
+ else
+ {
+ jxr_set_INTERNAL_CLR_FMT(image, JXR_YONLY, 1);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_YONLY);
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD8);
+ }
+ }
+ else if (raw_info_t.raw_format == 32) {
+ if(!alpha_plane)
+ {
+ jxr_set_INTERNAL_CLR_FMT(image, internal_color_fmt, 3);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_RGB);
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD8);
+ }
+ else
+ {
+ jxr_set_INTERNAL_CLR_FMT(image, JXR_YONLY, 1);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_YONLY);
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD8);
+ }
+ }
+ else if (raw_info_t.raw_format == 33)
+ {
+ if(!alpha_plane)
+ {
+ jxr_set_INTERNAL_CLR_FMT(image, internal_color_fmt, 3);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_RGB);
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD16);
+ }
+ else
+ {
+ jxr_set_INTERNAL_CLR_FMT(image, JXR_YONLY, 1);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_YONLY);
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD16);
+ }
+ }
+ else if (raw_info_t.raw_format == 34) {
+ if(!alpha_plane)
+ {
+ jxr_set_INTERNAL_CLR_FMT(image, internal_color_fmt, 3);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_RGB);
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD32F);
+ jxr_set_FLOAT(image, len_mantissa, exp_bias);
+ }
+ else
+ {
+ jxr_set_INTERNAL_CLR_FMT(image, JXR_YONLY, 1);
+ jxr_set_OUTPUT_CLR_FMT(image, JXR_OCF_YONLY);
+ jxr_set_OUTPUT_BITDEPTH(image, JXR_BD32F);
+ jxr_set_FLOAT(image, len_mantissa, exp_bias);
+ }
+
+ }
+
+ if(alpha_mode == 2 && !alpha_plane)
+ {
+ set_ncomp(input_handle, ncomp - 1);
+ }
+ else if(alpha_mode == 2 && alpha_plane)
+ {
+ set_ncomp(input_handle, 1);
+ }
+ }
+
+
+
+ jxr_set_BANDS_PRESENT(image, bands_present);
+ jxr_set_TRIM_FLEXBITS(image, trim_flexbits);
+ jxr_set_OVERLAP_FILTER(image, overlap_filter);
+ jxr_set_DISABLE_TILE_OVERLAP(image, disable_tile_overlap);
+ jxr_set_FREQUENCY_MODE_CODESTREAM_FLAG(image, frequency_mode_flag);
+ jxr_set_PROFILE_IDC(image, profile_idc);
+ jxr_set_LEVEL_IDC(image, level_idc);
+ jxr_set_LONG_WORD_FLAG(image, long_word_flag_setting);
+ jxr_set_ALPHA_IMAGE_PLANE_FLAG(image, alpha_mode == 1 ? 1 : 0);
+
+ jxr_set_NUM_VER_TILES_MINUS1(image, tile_columns);
+ jxr_set_TILE_WIDTH_IN_MB(image, tile_width_in_MB);
+ jxr_set_NUM_HOR_TILES_MINUS1(image, tile_rows);
+ jxr_set_TILE_HEIGHT_IN_MB(image, tile_height_in_MB);
+ jxr_set_pixel_format(image, pxl_fmt);
+
+ if (quant_uniform) {
+ if (quant_per_channel_count == 1) {
+ jxr_set_QP_UNIFORM(image, quant_per_channel[0]);
+ } else if (ncomp >= 3 && quant_per_channel_count == 2) {
+ jxr_set_QP_SEPARATE(image, quant_per_channel);
+ } else {
+ int idx;
+ for (idx = ncomp ; idx < (int) quant_per_channel_count ; idx += 1)
+ quant_per_channel[idx] = quant_per_channel[ncomp-1];
+
+ jxr_set_QP_INDEPENDENT(image, quant_per_channel);
+ }
+ } else if (quant_path) {
+ FILE*quant_fd = fopen(quant_path, "r");
+ if (quant_fd == 0) {
+ perror(quant_path);
+ return 1;
+ }
+ int rc = qp_parse_file(quant_fd, image);
+ if (rc < 0) return 1;
+
+ } else {
+ jxr_set_QP_LOSSLESS(image);
+ }
+
+ rc = jxr_test_PROFILE_IDC(image, 0);
+ if (rc < 0) {
+ return 1;
+ }
+
+ rc = jxr_test_LEVEL_IDC(image, 0);
+ if (rc < 0) {
+ return 1;
+ }
+ return 0;
+}
+
+
+int setup_container_params(jxr_container_t container, void *input_handle)
+{
+ int wid, hei, ncomp, bpi;
+ short sf, photometric;
+ int padBytes;
+ get_file_parameters(input_handle, &wid, &hei, &ncomp, &bpi, &sf, &photometric, &padBytes);
+ int alpha_present = 0;
+ if (!raw_info_t.is_raw) {
+ switch (ncomp + padBytes) {
+ case 1:
+ if (bpi == 1) {
+ pxl_fmt = JXRC_FMT_BlackWhite;
+ }
+ else if (bpi == 8) {
+ pxl_fmt = JXRC_FMT_8bppGray;
+ }
+ else if (bpi == 16) {
+ if(sf == 1)
+ pxl_fmt = JXRC_FMT_16bppGray;
+ else if(sf == 2)
+ pxl_fmt = JXRC_FMT_16bppGrayFixedPoint;
+ else if(sf == 3)
+ pxl_fmt = JXRC_FMT_16bppGrayHalf;
+ }
+ else if (bpi == 32) {
+ if(sf == 2)
+ pxl_fmt = JXRC_FMT_32bppGrayFixedPoint;
+ else if(sf == 3)
+ pxl_fmt = JXRC_FMT_32bppGrayFloat;
+ }
+ break;
+ case 3: /* Assume RGB */
+ if (bpi == 8)
+ pxl_fmt = (JXRC_FMT_24bppRGB);
+ else if (bpi == 16) {
+ if(sf == 1)
+ pxl_fmt = JXRC_FMT_48bppRGB;
+ else if(sf == 2)
+ pxl_fmt = JXRC_FMT_48bppRGBFixedPoint;
+ else if(sf == 3)
+ pxl_fmt = JXRC_FMT_48bppRGBHalf;
+ }
+ else if (bpi == 32) {
+ if(sf == 2)
+ pxl_fmt = JXRC_FMT_96bppRGBFixedPoint;
+ /* no 96bppRGBFloat */
+ }
+ break;
+ case 4: /* CMYK or RGBA or RGB_Null*/
+ if (bpi == 8) {
+ if (photometric == 5)
+ pxl_fmt = JXRC_FMT_32bppCMYK;
+ }
+ else if (bpi == 16) {
+ if (photometric == 5)
+ pxl_fmt = JXRC_FMT_64bppCMYK;
+ else if (photometric == 2) {
+ if (sf == 1)
+ {
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_64bppRGBA; /* no 64bppRGB */
+ }
+ else if (sf == 2) {
+ if (ncomp == 3)
+ pxl_fmt = JXRC_FMT_64bppRGBFixedPoint;
+ else if (ncomp == 4)
+ {
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_64bppRGBAFixedPoint;
+ }
+ }
+ else if (sf == 3) {
+ if (ncomp == 3)
+ pxl_fmt = JXRC_FMT_64bppRGBHalf;
+ else if (ncomp == 4)
+ {
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_64bppRGBAHalf;
+ }
+ }
+ }
+ }
+ else if (bpi == 32) {
+ if (photometric == 2) {
+ if (sf == 2) {
+ if (ncomp == 3)
+ pxl_fmt = JXRC_FMT_128bppRGBFixedPoint;
+ if (ncomp == 4)
+ {
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_128bppRGBAFixedPoint;
+ }
+ }
+ else if(sf == 3) {
+ if (ncomp == 3)
+ pxl_fmt = JXRC_FMT_128bppRGBFloat;
+ else if (ncomp == 4)
+ {
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_128bppRGBAFloat;
+ }
+ }
+ }
+ /* add 128bppRGBAFloat here */
+ }
+ break;
+ case 5: /* CMYKA */
+ if (bpi == 8) {
+ if (photometric == 5) {
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_40bppCMYKAlpha;
+ }
+ }
+ else if (bpi == 16) {
+ if (photometric == 5) {
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_80bppCMYKAlpha;
+ }
+ }
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+ else { /* raw */
+ if ((raw_info_t.raw_format >= 3) && (raw_info_t.raw_format <= 14)) { /* N-channel */
+ if (8 == raw_info_t.raw_bpc) {
+ switch (raw_info_t.raw_format) {
+ case 3:
+ pxl_fmt = JXRC_FMT_24bpp3Channels;
+ break;
+ case 4:
+ pxl_fmt = JXRC_FMT_32bpp4Channels;
+ break;
+ case 5:
+ pxl_fmt = JXRC_FMT_40bpp5Channels;
+ break;
+ case 6:
+ pxl_fmt = JXRC_FMT_48bpp6Channels;
+ break;
+ case 7:
+ pxl_fmt = JXRC_FMT_56bpp7Channels;
+ break;
+ case 8:
+ pxl_fmt = JXRC_FMT_64bpp8Channels;
+ break;
+ case 9:
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_32bpp3ChannelsAlpha;
+ break;
+ case 10:
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_40bpp4ChannelsAlpha;
+ break;
+ case 11:
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_48bpp5ChannelsAlpha;
+ break;
+ case 12:
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_56bpp6ChannelsAlpha;
+ break;
+ case 13:
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_64bpp7ChannelsAlpha;
+ break;
+ case 14:
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_72bpp8ChannelsAlpha;
+ break;
+ default:
+ assert(0);
+ break;
+
+ }
+ }
+ else { /* 16bpc */
+ switch (raw_info_t.raw_format) {
+ case 3:
+ pxl_fmt = JXRC_FMT_48bpp3Channels;
+ break;
+ case 4:
+ pxl_fmt = JXRC_FMT_64bpp4Channels;
+ break;
+ case 5:
+ pxl_fmt = JXRC_FMT_80bpp5Channels;
+ break;
+ case 6:
+ pxl_fmt = JXRC_FMT_96bpp6Channels;
+ break;
+ case 7:
+ pxl_fmt = JXRC_FMT_112bpp7Channels;
+ break;
+ case 8:
+ pxl_fmt = JXRC_FMT_128bpp8Channels;
+ break;
+ case 9:
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_64bpp3ChannelsAlpha;
+ break;
+ case 10:
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_80bpp4ChannelsAlpha;
+ break;
+ case 11:
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_96bpp5ChannelsAlpha;
+ break;
+ case 12:
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_112bpp6ChannelsAlpha;
+ break;
+ case 13:
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_128bpp7ChannelsAlpha;
+ break;
+ case 14:
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_144bpp8ChannelsAlpha;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+ }
+ else if (raw_info_t.raw_format == 15) { /* RGBE */
+ pxl_fmt = JXRC_FMT_32bppRGBE;
+ }
+ else if (raw_info_t.raw_format == 16) {
+ pxl_fmt = JXRC_FMT_16bppBGR555;
+ }
+ else if (raw_info_t.raw_format == 17) {
+ pxl_fmt = JXRC_FMT_16bppBGR565;
+ }
+ else if (raw_info_t.raw_format == 18) {
+ pxl_fmt = JXRC_FMT_32bppBGR101010;
+ }
+ else if ((raw_info_t.raw_format >= 19) && (raw_info_t.raw_format <= 26)) { /* YCC */
+ if (8 == raw_info_t.raw_bpc) {
+ switch (raw_info_t.raw_format) {
+ case 19:
+ pxl_fmt = JXRC_FMT_12bppYCC420;
+ break;
+ case 20:
+ pxl_fmt = JXRC_FMT_16bppYCC422;
+ break;
+ case 21:
+ pxl_fmt = JXRC_FMT_24bppYCC444;
+ break;
+ case 23:
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_20bppYCC420Alpha;
+ break;
+ case 24:
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_24bppYCC422Alpha;
+ break;
+ case 25:
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_32bppYCC444Alpha;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+ else if (10 == raw_info_t.raw_bpc) {
+ switch (raw_info_t.raw_format) {
+ case 20:
+ pxl_fmt = JXRC_FMT_20bppYCC422;
+ break;
+ case 21:
+ pxl_fmt = JXRC_FMT_30bppYCC444;
+ break;
+ case 24:
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_30bppYCC422Alpha;
+ break;
+ case 25:
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_40bppYCC444Alpha;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+ else if (16 == raw_info_t.raw_bpc) { /* 16bpc */
+ switch (raw_info_t.raw_format) {
+ case 20:
+ pxl_fmt = JXRC_FMT_32bppYCC422;
+ break;
+ case 21:
+ pxl_fmt = JXRC_FMT_48bppYCC444;
+ break;
+ case 22:
+ pxl_fmt = JXRC_FMT_48bppYCC444FixedPoint;
+ break;
+ case 24:
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_48bppYCC422Alpha;
+ break;
+ case 25:
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_64bppYCC444Alpha;
+ break;
+ case 26:
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_64bppYCC444AlphaFixedPoint;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+ else
+ assert(0);
+ }
+ else if ((raw_info_t.raw_format >= 27) && (raw_info_t.raw_format <= 28)) { /* CMYKDIRECT */
+ if (8 == raw_info_t.raw_bpc) {
+ switch (raw_info_t.raw_format) {
+ case 27:
+ pxl_fmt = JXRC_FMT_32bppCMYKDIRECT;
+ break;
+ case 28:
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_40bppCMYKDIRECTAlpha;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+ else if (16 == raw_info_t.raw_bpc) { /* 16bpc */
+ switch (raw_info_t.raw_format) {
+ case 27:
+ pxl_fmt = JXRC_FMT_64bppCMYKDIRECT;
+ break;
+ case 28:
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_80bppCMYKDIRECTAlpha;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+ else
+ assert(0);
+ }
+ else if (raw_info_t.raw_format == 29) {
+ pxl_fmt = JXRC_FMT_24bppBGR;
+ }
+ else if (raw_info_t.raw_format == 30) {
+ pxl_fmt = JXRC_FMT_32bppBGR;
+ }
+ else if (raw_info_t.raw_format == 31) {
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_32bppBGRA;
+ }
+ else if (raw_info_t.raw_format == 32) {
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_32bppPBGRA;
+ }
+ else if (raw_info_t.raw_format == 33) {
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_64bppPRGBA;
+ }
+ else if (raw_info_t.raw_format == 34) {
+ alpha_present = 1;
+ pxl_fmt = JXRC_FMT_128bppPRGBAFloat;
+ }
+ else
+ assert(0);
+ }
+
+ jxrc_set_pixel_format(container, pxl_fmt);
+
+ if(alpha_present)
+ {
+ if(alpha_mode == 0) /* No -a option was used at command line, so by default, turn on Separate alpha */
+ {
+ alpha_mode = 2; /* Separate alpha */
+ fprintf(stderr, " Setting alpha_mode to 2\n");
+ }
+ else
+ {
+ fprintf(stderr, " Using alpha_mode = %d\n ", alpha_mode);
+ }
+
+ }
+ else /* Current output format has no alpha information, so turn off alpha_mode */
+ {
+ if(alpha_mode != 0)
+ {
+ alpha_mode = 0;
+ fprintf(stderr, " Setting alpha_mode to 0\n");
+ }
+ }
+
+ jxrc_set_image_shape(container, wid, hei);
+ jxrc_set_image_band_presence(container, (unsigned) bands_present); /* another call will need to be added for separate alpha */
+ return 0;
+
+
+}
+
+static int main_compress(const char*path)
+{
+ int rc = 0;
+ jxr_image_t image = NULL;
+ void *input_handle = NULL;
+ jxr_container_t container = NULL;
+
+ if (path_out == 0)
+ path_out = "out.jxr";
+
+ FILE*fd = fopen(path_out, "wb");
+ if (fd == 0) {
+ perror(path_out);
+ rc = -1;
+ goto exit;
+ }
+
+ input_handle = open_input_file(path, &raw_info_t, &alpha_mode, &padded_format);
+ char path_primary[2048];
+ char path_alpha[2048];
+ int wid, hei, ncomp, bpi;
+ short sf, photometric;
+ int padBytes;
+ get_file_parameters(input_handle, &wid, &hei, &ncomp, &bpi, &sf, &photometric, &padBytes);
+
+
+ /* Create the file container and bind the FD to it. */
+ container = jxr_create_container();
+ jxrc_start_file(container, fd);
+
+ /* Start the next ifd entry and load it with information about
+ the image to be processed. */
+ rc = jxrc_begin_ifd_entry(container);
+ if(rc != 0)
+ goto exit;
+ rc = setup_container_params(container, input_handle);
+ if(rc != 0)
+ goto exit;
+
+ /* Create a stub image. */
+ if(alpha_mode == 2)
+ rc = setup_image_params(&image, input_handle, 0, 0); /* Set up parameters for a regular image, fix later after separating primary and alpha */
+ else
+ rc = setup_image_params(&image, input_handle, alpha_mode, 0);
+
+ if(rc != 0)
+ goto exit;
+
+ if(alpha_mode == 2)
+ {
+ /* Open handle to dump primary in tif format */
+ separate_primary_alpha(image, input_handle, path_out, path_primary, path_alpha, container);//jxrc_image_pixelformat(container, 0));
+ close_file(input_handle);
+ input_handle = NULL;
+ input_handle = open_input_file(path_primary, &raw_info_t, &alpha_mode, &padded_format);
+ get_file_parameters(input_handle, &wid, &hei, &ncomp, &bpi, &sf, &photometric, &padBytes);
+ rc = setup_image_params(&image, input_handle, alpha_mode, 0);
+ if(rc != 0)
+ goto exit;
+ jxrc_set_separate_alpha_image_plane(container, 1);
+ }
+ else
+ {
+ jxrc_set_separate_alpha_image_plane(container, 0);
+ }
+
+ jxr_set_pixel_format(image, jxrc_get_pixel_format(container));
+
+ /* Close out the current IFD and start with the actual image
+ data to be written. */
+ jxrc_begin_image_data(container);
+
+ jxr_set_block_input(image, read_file);
+ jxr_set_user_data(image, input_handle);
+
+ /* Write image to the destination file. */
+ rc = jxr_write_image_bitstream(image, fd);
+ if (rc != 0) {
+ goto exit;
+ }
+
+ /* Finalize IFDs for image. */
+ jxrc_write_container_post(container);
+
+ close_file(input_handle);
+ input_handle = NULL;
+ jxr_destroy(image);
+ image = NULL;
+
+ if(alpha_mode == 2)
+ {
+ input_handle = open_input_file(path_alpha, &raw_info_t, &alpha_mode, &padded_format);
+ get_file_parameters(input_handle, &wid, &hei, &ncomp, &bpi, &sf, &photometric, &padBytes);
+
+ rc = setup_image_params(&image, input_handle, alpha_mode, 1);
+ jxr_set_pixel_format(image, jxrc_get_pixel_format(container));
+ if(rc != 0)
+ {
+ goto exit;
+ }
+
+ jxr_set_block_input(image, read_file);
+ jxr_set_user_data(image, input_handle);
+
+ /* Write image to the destination file. */
+ rc = jxr_write_image_bitstream(image, fd);
+ if (rc != 0) {
+ goto exit;
+ }
+ /* Finalize IFDs for alpha plane. */
+ jxrc_write_container_post_alpha(container);
+ remove(path_alpha);
+ remove(path_primary);
+ }
+
+
+
+exit:
+ close_file(input_handle);
+ jxr_destroy(image);
+ if(fd)
+ fclose(fd);
+ jxr_destroy_container(container);
+ return rc;
+}
+
+static int decompress_image(FILE *fd, jxr_container_t container, void *output_handle, jxr_image_t *pImage, unsigned char alpha)
+{
+ int rc, idx;
+ *pImage = jxr_create_input();
+ jxr_set_block_output(*pImage, write_file);
+ jxr_set_pixel_format(*pImage, jxrc_image_pixelformat(container, 0));
+ jxr_set_user_data(*pImage, output_handle);
+ jxr_set_PROFILE_IDC(*pImage, profile_idc);
+ jxr_set_LEVEL_IDC(*pImage, level_idc);
+ jxr_set_container_parameters(*pImage,
+ jxrc_image_pixelformat(container, 0),
+ jxrc_image_width(container, 0), jxrc_image_height(container, 0),
+ jxrc_alpha_offset(container, 0),
+ jxrc_image_band_presence(container,0), jxrc_alpha_band_presence(container,0), alpha);
+
+ for (idx = 0 ; idx < nflags ; idx += 1) {
+ if (strcmp(flags[idx],"SKIP_HP_DATA") == 0) {
+ jxr_flag_SKIP_HP_DATA(*pImage, 1);
+ continue;
+ }
+ if (strcmp(flags[idx],"SKIP_FLEX_DATA") == 0) {
+ jxr_flag_SKIP_FLEX_DATA(*pImage, 1);
+ continue;
+ }
+ }
+
+ /* Process as an image bitstream. */
+ rc = jxr_read_image_bitstream(*pImage, fd);
+ if (rc < 0) {
+ switch (rc) {
+ case JXR_EC_BADMAGIC:
+ fprintf(stderr, "No valid magic number. Not an JPEG XR container or bitstream.\n");
+ break;
+ default:
+ fprintf(stderr, " Error %d reading image bitstream\n", rc);
+ break;
+ }
+ }
+ else
+ rc = jxr_test_LONG_WORD_FLAG(*pImage, long_word_flag_setting);
+ return rc;
+
+}
+#define SAFE_FREE(h) {if(h)free(h); h = NULL;}
+#define SAFE_CLOSE(h) {if(h)close_file(h); h = NULL;}
+#define SAFE_JXR_DESTROY(h) {if(h) jxr_destroy(h); h = NULL;}
+
+static int main_decompress(const char*path_in)
+{
+ int rc;
+ int codedImages = 1;
+ unsigned int alphaCodedImagePresent = 0;
+ void *output_handle_primary = NULL;
+ void *output_handle_alpha = NULL;
+ char path_out_primary[2048];
+ char path_out_alpha[2048];
+ unsigned long off;
+ jxr_image_t imageAlpha=NULL, image=NULL;
+ if (path_out == 0)
+ path_out = "out.raw";
+
+ FILE*fd = fopen(path_in, "rb");
+ if (fd == 0) {
+ perror(path_in);
+ return -1;
+ }
+
+ void *output_handle = open_output_file(path_out);
+
+ jxr_container_t ifile = jxr_create_container();
+ rc = jxr_read_image_container(ifile, fd);
+ if (rc >= 0) {
+ assert(rc >= 0);
+# if defined(DETAILED_DEBUG)
+ printf("Detected jxr image container\n");
+ printf("XXXX Bytes of contained image: %ld\n", jxrc_image_bytecount(ifile, 0));
+#endif
+ off = jxrc_image_offset(ifile, 0);
+#if defined(DETAILED_DEBUG)
+ printf("XXXX Offset of contained image: %ld\n", off);
+#endif
+ rc = fseek(fd, off, SEEK_SET);
+ assert(rc >= 0);
+ if(jxrc_alpha_offset(ifile, 0))
+ {
+ alphaCodedImagePresent = 1;
+# if defined(DETAILED_DEBUG)
+ printf("XXXX Bytes of alpha image: %ld\n", jxrc_alpha_bytecount(ifile, 0));
+ printf("XXXX Offset of contained image: %ld\n", jxrc_alpha_offset(ifile, 0));
+#endif
+ }
+ } else {
+#if defined(DETAILED_DEBUG)
+ printf("No container found, assuming unwrapped bistream with no alpha coded image\n");
+#endif
+ rc = fseek(fd, 0, SEEK_SET);
+ assert(rc >= 0);
+ }
+
+ /* read optional IFD tags to make certain of conformance */
+ char * document_name = 0, * image_description = 0, * equipment_make = 0, * equipment_model = 0, * page_name = 0;
+ char * software_name_version = 0, * date_time = 0, * artist_name = 0, * host_computer = 0, * copyright_notice = 0;
+ unsigned char profile, level;
+ unsigned short page_number[2] = {0, 0}, color_space;
+ unsigned long spatial_xfrm, image_type;
+ float width_res, height_res;
+ unsigned char image_band_present, alpha_band_present, buf[4];
+
+ rc = jxrc_document_name(ifile, 0, &document_name);
+ rc = jxrc_image_description(ifile, 0, &image_description);
+ rc = jxrc_equipment_make(ifile, 0, &equipment_make);
+ rc = jxrc_equipment_model(ifile, 0, &equipment_model);
+ rc = jxrc_page_name(ifile, 0, &page_name);
+ rc = jxrc_page_number(ifile, 0, page_number);
+ rc = jxrc_software_name_version(ifile, 0, &software_name_version);
+ rc = jxrc_date_time(ifile, 0, &date_time);
+ rc = jxrc_artist_name(ifile, 0, &artist_name);
+ rc = jxrc_host_computer(ifile, 0, &host_computer);
+ rc = jxrc_copyright_notice(ifile, 0, &copyright_notice);
+ color_space = jxrc_color_space(ifile, 0);
+ spatial_xfrm = jxrc_spatial_xfrm_primary(ifile, 0);
+ image_type = jxrc_image_type(ifile, 0);
+ rc = jxrc_ptm_color_info(ifile, 0, buf);
+ rc = jxrc_profile_level_container(ifile, 0, &profile, &level);
+ if (rc < 0) {
+ profile = 111;
+ level = 255;
+ }
+ width_res = jxrc_width_resolution(ifile, 0);
+ height_res = jxrc_height_resolution(ifile, 0);
+ image_band_present = jxrc_image_band_presence(ifile, 0);
+ alpha_band_present = jxrc_alpha_band_presence(ifile, 0);
+ rc = jxrc_padding_data(ifile, 0);
+
+
+ if(alphaCodedImagePresent)
+ {
+ /* Open handle to dump decoded primary in raw format */
+ strcpy(path_out_primary, path_out);
+ strcat(path_out_primary, "_primary.raw");
+ output_handle_primary = open_output_file(path_out_primary);
+ }
+ else
+ {
+ output_handle_primary = open_output_file(path_out);
+ }
+ /*Decode image */
+ rc = decompress_image(fd, ifile, output_handle_primary, &image, 0);
+ SAFE_CLOSE(output_handle_primary);
+ if(rc < 0)
+ goto exit;
+
+ if(!alphaCodedImagePresent)
+ goto exit;
+
+ /* Open handle to dump decoded alpha in raw format*/
+ strcpy(path_out_alpha, path_out);
+ strcat(path_out_alpha, "_alpha.raw");
+ output_handle_alpha = open_output_file(path_out_alpha);
+
+ /*Seek to alpha offset */
+ off = jxrc_alpha_offset(ifile, 0);
+ rc = fseek(fd, off, SEEK_SET);
+ assert(rc >= 0);
+ /* Decode alpha */
+ rc = decompress_image(fd, ifile, output_handle_alpha, &imageAlpha, 1);
+ SAFE_CLOSE(output_handle_alpha);
+ if(rc < 0)
+ goto exit;
+
+ /* For YCC and CMYKDirect formats, concatenate alpha and primary images */
+ /* For other output pixel formats, interleave alphad and primary images */
+ {
+ output_handle = open_output_file(path_out);
+ FILE *fpPrimary = fopen(path_out_primary,"rb");
+ assert(fpPrimary);
+ FILE *fpAlpha = fopen(path_out_alpha,"rb");
+ assert(fpAlpha);
+ jxr_set_user_data(image, output_handle);
+ write_file_combine_primary_alpha(image, fpPrimary, fpAlpha);
+ fclose(fpPrimary);
+ fclose(fpAlpha);
+ remove(path_out_primary);
+ remove(path_out_alpha);
+ SAFE_CLOSE(output_handle);
+ }
+
+exit:
+ SAFE_FREE(document_name);
+ SAFE_FREE(image_description);
+ SAFE_FREE(equipment_make);
+ SAFE_FREE(equipment_model);
+ SAFE_FREE(page_name);
+ SAFE_FREE(software_name_version);
+ SAFE_FREE(date_time);
+ SAFE_FREE(artist_name);
+ SAFE_FREE(host_computer);
+ SAFE_FREE(copyright_notice);
+ SAFE_JXR_DESTROY(image);
+ SAFE_JXR_DESTROY(imageAlpha);
+ fclose(fd);
+ return 0;
+}
+
+/*
+* $Log: jpegxr.c,v $
+* Revision 1.39 2009/05/29 12:00:00 microsoft
+* Reference Software v1.6 updates.
+*
+* Revision 1.38 2009/04/13 12:00:00 microsoft
+* Reference Software v1.5 updates.
+*
+* Revision 1.37 2008/05/25 09:40:46 thor
+* Added a -d command line option to enable derived quantization.
+*
+* Revision 1.36 2008/05/13 13:47:11 thor
+* Some experiments with a smarter selection for the quantization size,
+* does not yet compile.
+*
+* Revision 1.35 2008-05-09 19:57:48 thor
+* Reformatted for unix LF.
+*
+* Revision 1.34 2008-04-15 14:28:12 thor
+* Start of the repository for the jpegxr reference software.
+*
+* Revision 1.33 2008/03/21 18:05:53 steve
+* Proper CMYK formatting on input.
+*
+* Revision 1.32 2008/03/18 18:36:56 steve
+* Support compress of CMYK images.
+*
+* Revision 1.31 2008/03/11 22:12:49 steve
+* Encode YUV422 through DC.
+*
+* Revision 1.30 2008/03/06 02:05:48 steve
+* Distributed quantization
+*
+* Revision 1.29 2008/03/05 06:58:10 gus
+* *** empty log message ***
+*
+* Revision 1.28 2008/03/05 04:04:30 steve
+* Clarify constraints on USE_DC_QP in image plane header.
+*
+* Revision 1.27 2008/03/05 01:27:15 steve
+* QP_UNIFORM may use USE_DC_LP optionally.
+*
+* Revision 1.26 2008/03/04 23:01:28 steve
+* Cleanup QP API in preparation for distributed QP
+*
+* Revision 1.25 2008/03/02 19:56:27 steve
+* Infrastructure to read write BD16 files.
+*
+* Revision 1.24 2008/03/01 02:46:09 steve
+* Add support for JXR container.
+*
+* Revision 1.23 2008/02/29 01:03:31 steve
+* MSC doesnt have strcasecmp. Use stricmp instead.
+*
+* Revision 1.22 2008/02/29 00:57:59 steve
+* VisualStudio files
+*
+* Revision 1.21 2008/02/26 23:52:44 steve
+* Remove ident for MS compilers.
+*
+* Revision 1.20 2008/02/01 22:49:53 steve
+* Handle compress of YUV444 color DCONLY
+*
+* Revision 1.19 2008/01/19 02:30:46 rick
+* Re-implement and extend file interface.
+*
+* Revision 1.18 2008/01/08 01:06:20 steve
+* Add first pass overlap filtering.
+*
+* Revision 1.17 2008/01/06 01:29:28 steve
+* Add support for TRIM_FLEXBITS in compression.
+*
+* Revision 1.16 2008/01/04 17:07:35 steve
+* API interface for setting QP values.
+*
+* Revision 1.15 2007/12/06 00:24:25 steve
+* Zero fill strip buffer, so that right pad is zeros.
+*
+* Revision 1.14 2007/12/04 22:06:10 steve
+* Infrastructure for encoding LP.
+*
+* Revision 1.13 2007/11/30 01:57:00 steve
+* Handle comments in PNM files.
+*
+* Revision 1.12 2007/11/30 01:50:58 steve
+* Compression of DCONLY GRAY.
+*
+* Revision 1.11 2007/11/26 01:47:15 steve
+* Add copyright notices per MS request.
+*
+* Revision 1.10 2007/11/08 02:52:32 steve
+* Some progress in some encoding infrastructure.
+*
+* Revision 1.9 2007/11/07 18:11:02 steve
+* Useful error message for bad magic numbers.
+*
+* Revision 1.8 2007/10/22 23:08:55 steve
+* Protect prints with DETAILED_DEBUG.
+*
+* Revision 1.7 2007/09/18 17:02:49 steve
+* Slight PNM header format change.
+*
+* Revision 1.6 2007/09/08 01:01:43 steve
+* YUV444 color parses properly.
+*
+* Revision 1.5 2007/08/03 22:49:10 steve
+* Do not write out the line padding.
+*
+* Revision 1.4 2007/07/30 23:09:57 steve
+* Interleave FLEXBITS within HP block.
+*
+* Revision 1.3 2007/07/21 00:25:48 steve
+* snapshot 2007 07 20
+*
+* Revision 1.2 2007/06/07 18:53:06 steve
+* Parse HP coeffs that are all 0.
+*
+* Revision 1.1 2007/06/06 17:19:12 steve
+* Introduce to CVS.
+*
+*/
+
diff --git a/jpegxr/jpegxr.h b/jpegxr/jpegxr.h
new file mode 100644
index 000000000..a474f87b2
--- /dev/null
+++ b/jpegxr/jpegxr.h
@@ -0,0 +1,794 @@
+
+# ifndef __jpegxr_h
+# define __jpegxr_h
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+***********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: jpegxr.h,v 1.26 2008/03/18 18:36:56 steve Exp $")
+#else
+#ident "$Id: jpegxr.h,v 1.26 2008/03/18 18:36:56 steve Exp $"
+#endif
+
+# include <stdio.h>
+
+#ifdef _MSC_VER
+# ifdef JXR_DLL_EXPORTS
+# define JXR_EXTERN extern "C" __declspec(dllexport)
+# else
+# define JXR_EXTERN extern "C" __declspec(dllimport)
+# endif
+#else
+# ifdef _cplusplus
+# define JXR_EXTERN extern "C"
+# else
+# define JXR_EXTERN extern
+# endif
+#endif
+
+/* JPEG XR CONTAINER */
+
+/*
+* The container type represents an optional container that may
+* contain 1 or more JPEG XR images. Create the jxr_create_container
+* function and free them with jxr_destroy_container. The functions
+* below can be used to extract the image from the container.
+*/
+typedef struct jxr_container *jxr_container_t;
+
+JXR_EXTERN jxr_container_t jxr_create_container(void);
+JXR_EXTERN void jxr_destroy_container(jxr_container_t c);
+
+#define NUM_GUIDS 79
+extern unsigned char jxr_guids[NUM_GUIDS][16];
+
+typedef enum JXRC_GUID_e{
+ JXRC_FMT_24bppRGB = 0,
+ JXRC_FMT_24bppBGR,
+ JXRC_FMT_32bppBGR,
+ JXRC_FMT_48bppRGB,
+ JXRC_FMT_48bppRGBFixedPoint,
+ JXRC_FMT_48bppRGBHalf,
+ JXRC_FMT_96bppRGBFixedPoint,
+ JXRC_FMT_64bppRGBFixedPoint,
+ JXRC_FMT_64bppRGBHalf,
+ JXRC_FMT_128bppRGBFixedPoint,
+ JXRC_FMT_128bppRGBFloat,
+ JXRC_FMT_32bppBGRA,
+ JXRC_FMT_64bppRGBA,
+ JXRC_FMT_64bppRGBAFixedPoint,
+ JXRC_FMT_64bppRGBAHalf,
+ JXRC_FMT_128bppRGBAFixedPoint,
+ JXRC_FMT_128bppRGBAFloat,
+ JXRC_FMT_32bppPBGRA,
+ JXRC_FMT_64bppPRGBA,
+ JXRC_FMT_128bppPRGBAFloat,
+ JXRC_FMT_32bppCMYK,
+ JXRC_FMT_40bppCMYKAlpha,
+ JXRC_FMT_64bppCMYK,
+ JXRC_FMT_80bppCMYKAlpha,
+ JXRC_FMT_24bpp3Channels,
+ JXRC_FMT_32bpp4Channels,
+ JXRC_FMT_40bpp5Channels,
+ JXRC_FMT_48bpp6Channels,
+ JXRC_FMT_56bpp7Channels,
+ JXRC_FMT_64bpp8Channels,
+ JXRC_FMT_32bpp3ChannelsAlpha,
+ JXRC_FMT_40bpp4ChannelsAlpha,
+ JXRC_FMT_48bpp5ChannelsAlpha,
+ JXRC_FMT_56bpp6ChannelsAlpha,
+ JXRC_FMT_64bpp7ChannelsAlpha,
+ JXRC_FMT_72bpp8ChannelsAlpha,
+ JXRC_FMT_48bpp3Channels,
+ JXRC_FMT_64bpp4Channels,
+ JXRC_FMT_80bpp5Channels,
+ JXRC_FMT_96bpp6Channels,
+ JXRC_FMT_112bpp7Channels,
+ JXRC_FMT_128bpp8Channels,
+ JXRC_FMT_64bpp3ChannelsAlpha,
+ JXRC_FMT_80bpp4ChannelsAlpha,
+ JXRC_FMT_96bpp5ChannelsAlpha,
+ JXRC_FMT_112bpp6ChannelsAlpha,
+ JXRC_FMT_128bpp7ChannelsAlpha,
+ JXRC_FMT_144bpp8ChannelsAlpha,
+ JXRC_FMT_8bppGray,
+ JXRC_FMT_16bppGray,
+ JXRC_FMT_16bppGrayFixedPoint,
+ JXRC_FMT_16bppGrayHalf,
+ JXRC_FMT_32bppGrayFixedPoint,
+ JXRC_FMT_32bppGrayFloat,
+ JXRC_FMT_BlackWhite,
+ JXRC_FMT_16bppBGR555,
+ JXRC_FMT_16bppBGR565,
+ JXRC_FMT_32bppBGR101010,
+ JXRC_FMT_32bppRGBE,
+ JXRC_FMT_32bppCMYKDIRECT,
+ JXRC_FMT_64bppCMYKDIRECT,
+ JXRC_FMT_40bppCMYKDIRECTAlpha,
+ JXRC_FMT_80bppCMYKDIRECTAlpha,
+ JXRC_FMT_12bppYCC420,
+ JXRC_FMT_16bppYCC422,
+ JXRC_FMT_20bppYCC422,
+ JXRC_FMT_32bppYCC422,
+ JXRC_FMT_24bppYCC444,
+ JXRC_FMT_30bppYCC444,
+ JXRC_FMT_48bppYCC444,
+ JXRC_FMT_48bppYCC444FixedPoint,
+ JXRC_FMT_20bppYCC420Alpha,
+ JXRC_FMT_24bppYCC422Alpha,
+ JXRC_FMT_30bppYCC422Alpha,
+ JXRC_FMT_48bppYCC422Alpha,
+ JXRC_FMT_32bppYCC444Alpha,
+ JXRC_FMT_40bppYCC444Alpha,
+ JXRC_FMT_64bppYCC444Alpha,
+ JXRC_FMT_64bppYCC444AlphaFixedPoint,
+}jxrc_t_pixelFormat;
+
+
+#define UNDEF_GUID (NUM_GUIDS + 1)
+/*
+* Given a clean container handle, read the specified file (open for
+* read) to get all the characteristics of the container. This just
+* opens and parses the container, it does *not* decompress the
+* image, or even necessarily read the image data. That is left for
+* the jxr_read_image_bitstream below. Instead, this function just
+* collects all the data in the container tags and makes it available
+* via the jxrc_* functions below.
+*
+* JXR_EC_BADMAGIC
+* The magic number is wrong, implying that it is not an JPEG XR
+* container. Perhaps it is a bitstream?
+*/
+JXR_EXTERN int jxr_read_image_container(jxr_container_t c, FILE*fd);
+
+/*
+* jxr_c_image_count returns the number of images in this
+* container. The images are then numbers starting from 0, with 0
+* intended to be the default view.
+*/
+JXR_EXTERN int jxrc_image_count(jxr_container_t c);
+
+/* File position for image in container. */
+JXR_EXTERN unsigned long jxrc_image_offset(jxr_container_t c, int image);
+/* Byte count for image in container. */
+JXR_EXTERN unsigned long jxrc_image_bytecount(jxr_container_t c, int image);
+/* File position for alpha image plane in container. */
+JXR_EXTERN unsigned long jxrc_alpha_offset(jxr_container_t c, int image);
+/* Byte count for alpha image in container. */
+JXR_EXTERN unsigned long jxrc_alpha_bytecount(jxr_container_t c, int image);
+/* Pixel format for image in container */
+JXR_EXTERN jxrc_t_pixelFormat jxrc_image_pixelformat(jxr_container_t c, int imagenum);
+/* Image width in container*/
+JXR_EXTERN unsigned long jxrc_image_width(jxr_container_t container, int image);
+/* Profile/Level in the container */
+JXR_EXTERN int jxrc_profile_level_container(jxr_container_t container, int image, unsigned char * profile, unsigned char * level);
+/* Image height in container*/
+JXR_EXTERN unsigned long jxrc_image_height(jxr_container_t container, int image);
+/* Spatial transfrom primary in container*/
+JXR_EXTERN unsigned long jxrc_spatial_xfrm_primary(jxr_container_t container, int image);
+/* Width resolution in container */
+JXR_EXTERN float jxrc_width_resolution(jxr_container_t container, int image);
+/* Height resolution in container */
+JXR_EXTERN float jxrc_height_resolution(jxr_container_t container, int image);
+/* Image band presence in container */
+JXR_EXTERN unsigned char jxrc_image_band_presence(jxr_container_t container, int image);
+/* Alpha band presence in container */
+JXR_EXTERN unsigned char jxrc_alpha_band_presence(jxr_container_t container, int image);
+/* Image type in container */
+JXR_EXTERN unsigned long jxrc_image_type(jxr_container_t container, int image);
+/* PTM Color Info in container */
+JXR_EXTERN int jxrc_ptm_color_info(jxr_container_t container, int image, unsigned char * buf);
+/* Color space info in container */
+JXR_EXTERN unsigned short jxrc_color_space(jxr_container_t container, int image);
+/* UTF8 strings in container */
+JXR_EXTERN int jxrc_document_name(jxr_container_t container, int image, char ** string);
+JXR_EXTERN int jxrc_image_description(jxr_container_t container, int image, char ** string);
+JXR_EXTERN int jxrc_equipment_make(jxr_container_t container, int image, char ** string);
+JXR_EXTERN int jxrc_equipment_model(jxr_container_t container, int image, char ** string);
+JXR_EXTERN int jxrc_page_name(jxr_container_t container, int image, char ** string);
+JXR_EXTERN int jxrc_software_name_version(jxr_container_t container, int image, char ** string);
+JXR_EXTERN int jxrc_date_time(jxr_container_t container, int image, char ** string);
+JXR_EXTERN int jxrc_artist_name(jxr_container_t container, int image, char ** string);
+JXR_EXTERN int jxrc_host_computer(jxr_container_t container, int image, char ** string);
+JXR_EXTERN int jxrc_copyright_notice(jxr_container_t container, int image, char ** string);
+/* page number in container */
+JXR_EXTERN int jxrc_page_number(jxr_container_t container, int image, unsigned short * value);
+/* padding data in container */
+JXR_EXTERN int jxrc_padding_data(jxr_container_t container, int image);
+
+/*
+* When writing an image file, start with a call to
+* jxrc_start_file. This binds the FILE pointer to the container and
+* gets the file pointers started.
+*
+* Then use the jxrc_begin_ifd_entry() function to create the next ifd
+* entry. This makes the next IFD ready for its settings. Load the
+* settings to reflect the image using the jxrc_set_* functions.
+*
+* When ready to start writing the image, use the jxr_begin_image_data
+* to close the ifd and start writing the image data. At this point
+* the caller can write the bit stream data itself.
+*
+* The jxrc_write_container_post, finalizes the
+* IFD value for IMAGE_BYTE_COUNT and IMAGE_OFFSET and leaves the pointer ready for the end of the image.
+*
+* The jxrc_write_container_post_alpha, finalizes the
+* IFD value for ALPHA_BYTE_COUNT and ALPHA_OFFSET and leaves the pointer ready for the end of the image.
+*
+*/
+
+JXR_EXTERN int jxrc_start_file(jxr_container_t c, FILE*fd);
+
+JXR_EXTERN int jxrc_begin_ifd_entry(jxr_container_t c);
+JXR_EXTERN int jxrc_set_pixel_format(jxr_container_t c, jxrc_t_pixelFormat fmt);
+JXR_EXTERN jxrc_t_pixelFormat jxrc_get_pixel_format(jxr_container_t c);
+JXR_EXTERN int jxrc_set_image_shape(jxr_container_t c, unsigned wid, unsigned hei);
+JXR_EXTERN int jxrc_set_image_band_presence(jxr_container_t cp, unsigned bands);
+JXR_EXTERN int jxrc_set_separate_alpha_image_plane(jxr_container_t cp, unsigned int alpha_present);
+
+JXR_EXTERN int jxrc_begin_image_data(jxr_container_t c);
+JXR_EXTERN int jxrc_write_container_post(jxr_container_t c);
+JXR_EXTERN int jxrc_write_container_post_alpha(jxr_container_t c);
+
+/* JPEG XR BITSTREAM */
+
+/*
+* The jxr_image_t is an opaque image type that represents an JPEG-XR
+* bitstream image. It holds the state for various of the following
+* operations.
+*
+* For reading (decompress), the general process goes like this:
+*
+* - Create an jxr_image_t object with the jxr_create_input() function,
+*
+* - Attach a callback function to receive blocks of image data with
+* the jxr_set_block_output() function, then
+*
+* - Run the decompress with the jxr_read_image_bitstream() function.
+*
+* - Destroy the jxr_image_T object with the jxr_destroy() function.
+*
+* The jxr_read_image_bitstream() function calls the user block
+* function periodically with data for a macroblock (16x16 pixels) of
+* the image. The callback function dispatches the data, for example
+* by formatting it into an image buffer or writing it to an output
+* file or rendering it to the screen.
+*/
+typedef struct jxr_image *jxr_image_t;
+
+/*
+* Create (destroy) an JPEG XR image cookie.
+*
+* jxr_create_image -
+* Create an jxr_image_t handle that will be used for writing an
+* image out.
+*
+* jxr_create_input -
+* Create an jxr_image_t handle that can be used to read an image.
+*
+* jxr_destroy -
+* Destroy an jxr_image_t object.
+*/
+JXR_EXTERN jxr_image_t jxr_create_image(int width, int height, unsigned char * windowing);
+JXR_EXTERN jxr_image_t jxr_create_input(void);
+JXR_EXTERN void jxr_destroy(jxr_image_t image);
+
+/*
+* Some user-controlled flags.
+*/
+JXR_EXTERN void jxr_flag_SKIP_HP_DATA(jxr_image_t image, int flag);
+JXR_EXTERN void jxr_flag_SKIP_FLEX_DATA(jxr_image_t image, int flag);
+
+/*
+* Applications may attach a single pointer to the jxr_image_t handle,
+* and retrieve it anytime, including within callbacks. The user data
+* is intended to be used by the callbacks to get information about
+* the context of the image process.
+*/
+JXR_EXTERN void jxr_set_user_data(jxr_image_t image, void*data);
+JXR_EXTERN void*jxr_get_user_data(jxr_image_t image);
+
+/*
+* Functions for getting/setting various flags of the image. These
+* either reflect the image that has been read, or controls how to
+* write the image out.
+*
+* IMAGE_WIDTH/IMAGE_HEIGHT
+* Dimensions of the image.
+*
+* IMAGE_CHANNELS
+* Number of channels in the image (not including alpha). For
+* example, 1==GRAY, 3==RGB.
+*
+* TILING_FLAG
+* TRUE if tiles are present in the image.
+*
+* FREQUENCY_MODE_CODESTREAM_FLAG
+* 0 == Spatial mode
+* 1 == Frequency mode
+*
+* TILE_WIDTH/TILE_HEIGHT
+* Dimensions of the tile rows/columns if present in the image, or
+* 0 otherwise. The widths/heights of all the columns/rows will
+* always be a multiple of 16 (the size of a macroblock).
+*
+* WINDOWING_FLAG
+* TRUE if there are windowin parameters in the image.
+*
+* ALPHACHANNEL_FLAG
+* TRUE if there is an alpha channel present.
+*
+* NOTE about setting flags: In many cases, the order that you set
+* things matters as internal configuration is devined from previous
+* values. So the order that jxr_set_* functions are listed in this
+* file is the order they should be applied to a file that is being
+* built up for output.
+*/
+JXR_EXTERN unsigned jxr_get_IMAGE_WIDTH(jxr_image_t image);
+JXR_EXTERN unsigned jxr_get_IMAGE_HEIGHT(jxr_image_t image);
+JXR_EXTERN unsigned jxr_get_EXTENDED_IMAGE_WIDTH(jxr_image_t image);
+JXR_EXTERN unsigned jxr_get_EXTENDED_IMAGE_HEIGHT(jxr_image_t image);
+JXR_EXTERN int jxr_get_IMAGE_CHANNELS(jxr_image_t image);
+JXR_EXTERN int jxr_get_TILING_FLAG(jxr_image_t image);
+JXR_EXTERN int jxr_get_FREQUENCY_MODE_CODESTREAM_FLAG(jxr_image_t image);
+JXR_EXTERN unsigned jxr_get_TILE_COLUMNS(jxr_image_t image);
+JXR_EXTERN unsigned jxr_get_TILE_ROWS(jxr_image_t image);
+JXR_EXTERN int jxr_get_TILE_WIDTH(jxr_image_t image, unsigned column);
+JXR_EXTERN int jxr_get_TILE_HEIGHT(jxr_image_t image, unsigned row);
+
+JXR_EXTERN int jxr_get_ALPHACHANNEL_FLAG(jxr_image_t image);
+JXR_EXTERN jxrc_t_pixelFormat jxr_get_pixel_format(jxr_image_t image);
+
+/*
+* This is the "Internal" color format of the image. It is the color
+* mode that is used to encode the image data. These are the only
+* formats that JPEG XR supports directly. This is not the same as
+* the EXTERNAL color format, which is the format that the user
+* presents/receives the data in. The available external formats are a
+* larger set.
+*/
+typedef enum jxr_color_fmt_e{
+ JXR_YONLY = 0,
+ JXR_YUV420 = 1,
+ JXR_YUV422 = 2,
+ JXR_YUV444 = 3,
+ JXR_YUVK = 4,
+ JXR_fmt_reserved5 = 5,
+ JXR_NCOMPONENT = 6,
+ JXR_fmt_reserved7 = 7
+}jxr_color_fmt_t;
+
+JXR_EXTERN void jxr_set_INTERNAL_CLR_FMT(jxr_image_t image, jxr_color_fmt_t fmt, int channels);
+
+/*
+* This is the "output" color format of the image.
+*/
+typedef enum jxr_output_clr_fmt_e{
+ JXR_OCF_YONLY = 0,
+ JXR_OCF_YUV420 = 1,
+ JXR_OCF_YUV422 = 2,
+ JXR_OCF_YUV444 = 3,
+ JXR_OCF_CMYK = 4,
+ JXR_OCF_CMYKDIRECT = 5,
+ JXR_OCF_NCOMPONENT = 6,
+ JXR_OCF_RGB = 7,
+ JXR_OCF_RGBE = 8,
+ JXR_OCF_fmt_reserved9 = 9,
+ JXR_OCF_fmt_reserved10 = 10,
+ JXR_OCF_fmt_reserved11 = 11,
+ JXR_OCF_fmt_reserved12 = 12,
+ JXR_OCF_fmt_reserved13 = 13,
+ JXR_OCF_fmt_reserved14 = 14,
+ JXR_OCF_fmt_reserved15 = 15
+}jxr_output_clr_fmt_t;
+
+JXR_EXTERN void jxr_set_OUTPUT_CLR_FMT(jxr_image_t image, jxr_output_clr_fmt_t fmt);
+JXR_EXTERN jxr_output_clr_fmt_t jxr_get_OUTPUT_CLR_FMT(jxr_image_t image);
+
+
+/*
+* This is the bit depth to use.
+*/
+typedef enum jxr_bitdepth_e{
+ JXR_BD1WHITE1 = 0,
+ JXR_BD8 = 1,
+ JXR_BD16 = 2,
+ JXR_BD16S = 3,
+ JXR_BD16F = 4,
+ JXR_BDRESERVED = 5,
+ JXR_BD32S = 6,
+ JXR_BD32F = 7,
+ JXR_BD5 = 8,
+ JXR_BD10 = 9,
+ JXR_BD565 = 10,
+ JXR_BD1BLACK1 = 15
+}jxr_bitdepth_t;
+
+JXR_EXTERN jxr_bitdepth_t jxr_get_OUTPUT_BITDEPTH(jxr_image_t image);
+JXR_EXTERN void jxr_set_OUTPUT_BITDEPTH(jxr_image_t image, jxr_bitdepth_t bd);
+JXR_EXTERN void jxr_set_SHIFT_BITS(jxr_image_t image, unsigned char shift_bits);
+JXR_EXTERN void jxr_set_FLOAT(jxr_image_t image, unsigned char len_mantissa, char exp_bias);
+
+/*
+* This sets the frequency bands that are to be included in the
+* image. The more bands are included, the higher the fidelity of the
+* compression, but also the larger the image result.
+*
+* If FLEXBITS are included, the TRIM_FLEXBITS value can be used to
+* reduce the amount of FLEXBIT data included. If 0 (the default) then
+* all the flexbit data is included, if trim==1, then 1 bit of flexbit
+* data is trimmed, and so on. TRIM_FLECBITS must be 0 <= TRIM_FLEXBITS <= 15.
+*/
+typedef enum jxr_bands_present_e{
+ JXR_BP_ALL = 0,
+ JXR_BP_NOFLEXBITS = 1,
+ JXR_BP_NOHIGHPASS = 2,
+ JXR_BP_DCONLY = 3,
+ JXR_BP_ISOLATED = 4
+}jxr_bands_present_t;
+
+JXR_EXTERN void jxr_set_BANDS_PRESENT(jxr_image_t image, jxr_bands_present_t bp);
+JXR_EXTERN void jxr_set_TRIM_FLEXBITS(jxr_image_t image, int trim);
+/* Filtering
+* Control overlap filtering with this function.
+*
+* - 0
+* No overlap filtering. (The default)
+*
+* - 1
+* Filter only the first stage, right before the first lifting pass.
+*
+* - 2
+* Filter first and second stage.
+*
+* - 3
+* Reserved
+*
+* All other values for flag are out of range.
+*/
+JXR_EXTERN void jxr_set_OVERLAP_FILTER(jxr_image_t image, int flag);
+
+/* HardTiles
+* Controls overlap filtering on tile boundaries
+*
+* - 0
+* Corresonds to soft tiles. Overlap Filtering is appiled across tile boundaries. (The default)
+*
+* -1
+* Corresonds to hard tiles. Overlap Filtering is not appiled across tile boundaries. (The default)
+* Instead, tile boundaries and corners are treated like image boundaries and image corners
+*
+* All other values are out of range
+*/
+JXR_EXTERN void jxr_set_DISABLE_TILE_OVERLAP(jxr_image_t image, int flag);
+JXR_EXTERN void jxr_set_FREQUENCY_MODE_CODESTREAM_FLAG(jxr_image_t image, int flag);
+JXR_EXTERN void jxr_set_INDEX_TABLE_PRESENT_FLAG(jxr_image_t image, int flag);
+JXR_EXTERN void jxr_set_ALPHA_IMAGE_PLANE_FLAG(jxr_image_t image, int flag);
+JXR_EXTERN void jxr_set_PROFILE_IDC(jxr_image_t image, int profile_idc);
+JXR_EXTERN void jxr_set_LEVEL_IDC(jxr_image_t image, int level_idc);
+JXR_EXTERN void jxr_set_LONG_WORD_FLAG(jxr_image_t image, int flag);
+JXR_EXTERN int jxr_test_PROFILE_IDC(jxr_image_t image, int flag);
+JXR_EXTERN int jxr_test_LEVEL_IDC(jxr_image_t image, int flag);
+
+JXR_EXTERN void jxr_set_NUM_VER_TILES_MINUS1(jxr_image_t image, unsigned num);
+JXR_EXTERN void jxr_set_TILE_WIDTH_IN_MB(jxr_image_t image, unsigned* list);
+JXR_EXTERN void jxr_set_NUM_HOR_TILES_MINUS1(jxr_image_t image, unsigned num);
+JXR_EXTERN void jxr_set_TILE_HEIGHT_IN_MB(jxr_image_t image, unsigned* list);
+JXR_EXTERN void jxr_set_TILING_FLAG(jxr_image_t image, int flag);
+JXR_EXTERN void jxr_set_container_parameters(jxr_image_t image, jxrc_t_pixelFormat pixel_format, unsigned wid, unsigned hei, unsigned separate, unsigned char image_presence, unsigned char alpha_presence, unsigned char alpha);
+
+/*
+* It is a consequence of the JXR format that an image can have no
+* more then 16 channels. This is because the channels count field is
+* only 4 bits wide. This is also true of NUM_LP_QPS and
+* NUM_HP_QPS. These constants can thus be used to size so tables.
+*/
+
+# define MAX_CHANNELS 16
+# define MAX_LP_QPS 16
+# define MAX_HP_QPS 16
+
+/* Quantization
+* These are functions to set up the quantization to be used for
+* encoding. Only one of these can be used for a given image. The
+* control over the QP values depends on which function you use.
+*
+* - set_QP_LOSSLESS()
+* Configure the QP values for lossless compression. This will also
+* set up the SCALED_FLAG appropriately. Note that this is not really
+* lossless unless all the bands are present.
+*
+* NOTE 1: DC/LP/HP_IMAGEPLANE_UNIFORM is set to true because the
+* quantization value is uniform identity.
+*
+* NOTE 2: Grayscale images will be configured with channel mode
+* UNIFORM.
+*
+* NOTE 3: Although lossless can be achieved with channel modes of
+* UNIFORM, SEPARATE and INDEPENDENT, this function will set
+* the channel mode to SEPARATE for color images.
+*
+* - set_QP_UNIFORM()
+* All the bands/channels are set with the same QP value. If the
+* use_dc_only flag it false, then the DC/LP/HP values are identical,
+* but encoded distinctly.
+*
+* NOTE 1: DC/LP/HP_IMAGEPLANE_UNIFORM is set to true so that the QP
+* are kept in the plane header.
+*
+* - set_QP_SEPARATE
+* All the bands are set with the same QP value, depending on the
+* component. The Y component gets the first quant value, and the
+* remaining channels get the other quant value.
+*
+* NOTE 1: DC/LP/HP_IMAGEPLANE_UNIFORM is set to true so that the QP
+* are kept in the plane header.
+*
+* NOTE 2: This should NOT be applied to grayscale images. Images
+* with 1 channel must have channel mode UNIFORM.
+*
+* - set_QP_INDEPENDENT
+* All the bands are set with the same QP value, but each channel gets
+* its own QP value.
+*
+* NOTE 1: DC/LP/HP_IMAGEPLANE_UNIFORM is set to true so that the QP
+* are kept in the plane header.
+*
+* NOTE 2: For single channel images (i.e. grayscale) this actually
+* sets the channel mode to UNIFORM. Only the UNIFORM
+* channel mode is valid for grayscale.
+*
+* - set_QP_DISTRIBUTED
+* This is the most complex form. Every tile/channel can have its own
+* QP set, and that QP set is mapped onto each
+* tile/channel/macroblock. The argument to the set_QP_DISTRIBUTED
+* function is an array of jxr_time_qp objects, one object per tile in
+* the complete image.
+*
+* NOTE 1: The tile configuration must be set before this function is
+* called. If no tile configuration is set, then there is
+* exactly 1 tile.
+* NOTE 2: set_QP_DISTRIBUTED causes DC/LP/HP_IMAGEPLANE_UNIFORM to be
+* false so that the QP values are moved to tile headers.
+*/
+
+JXR_EXTERN void jxr_set_QP_LOSSLESS(jxr_image_t image);
+JXR_EXTERN void jxr_set_QP_UNIFORM(jxr_image_t image, unsigned char quant);
+JXR_EXTERN void jxr_set_QP_SEPARATE(jxr_image_t image, unsigned char*quant_y_uv);
+JXR_EXTERN void jxr_set_QP_INDEPENDENT(jxr_image_t image, unsigned char*quant_per_channel);
+
+
+struct jxr_tile_channel_qp{
+ /* These are all the QP values available for the tile. A
+ tile/channel can have only 1 unique DC QP value, and up to
+ 16 (each) LP and HP QP values. */
+ unsigned char dc_qp;
+ unsigned char num_lp, num_hp; /* Number for LP/HP QP values. */
+ unsigned char lp_qp[16];
+ unsigned char hp_qp[16];
+};
+
+typedef enum jxr_component_mode_e{
+ JXR_CM_UNIFORM = 0,
+ JXR_CM_SEPARATE = 1,
+ JXR_CM_INDEPENDENT = 2,
+ JXR_CM_Reserved = 3
+}jxr_component_mode_t;
+
+struct jxr_tile_qp{
+ /* For every channel, have an jxr_tile_qp for all the tiles in
+ the image. Each jxr_tile_channel_qp represents the QP
+ values for a tile/channel. There are (up to) 16 channels,
+ and each channel points to an array of jxr_tile_qp
+ objects, depending on the component_mode. If the mode is
+ UNIFORM, then there is only one channel of data that is
+ shared for all components, etc. */
+ jxr_component_mode_t component_mode;
+ struct jxr_tile_channel_qp channel[16];
+ /* Map the LP/HP QP values to the macroblocks. There are as
+ many bytes in each array as there are macroblocks in the
+ tile, and the value at each byte is the index into the
+ table above. This is how the QP values are mapped to
+ macroblocks. */
+ unsigned char*lp_map;
+ unsigned char*hp_map;
+ /* Per tile Quantization parameters for up to 16 channels. This is required when quantization step sizes vary across tiles */
+ unsigned char dc_quant_ch[MAX_CHANNELS];
+ unsigned char lp_quant_ch[MAX_CHANNELS][MAX_LP_QPS];
+ unsigned char hp_quant_ch[MAX_CHANNELS][MAX_HP_QPS];
+};
+
+typedef struct raw_info {
+ unsigned int is_raw;
+ unsigned int raw_width;
+ unsigned int raw_height;
+ unsigned char raw_format;
+ unsigned char raw_bpc;
+} raw_info;
+
+JXR_EXTERN void jxr_set_QP_DISTRIBUTED(jxr_image_t image, struct jxr_tile_qp*qp);
+
+
+/*
+* Callbacks
+*
+* jxr_set_block_output -
+* During read of a compressed bitstream, the block_output function
+* is used to report that a 16x16 macroblock is complete. The
+* application is called back via a function of type block_fun_t to
+* receive and dispense with the data.
+*/
+typedef void (*block_fun_t)(jxr_image_t image, int mx, int my, int*data);
+
+JXR_EXTERN void jxr_set_block_input (jxr_image_t image, block_fun_t fun);
+JXR_EXTERN void jxr_set_block_output(jxr_image_t image, block_fun_t fun);
+
+JXR_EXTERN void jxr_set_pixel_format(jxr_image_t image, jxrc_t_pixelFormat pixelFormat);
+/*
+* After the jxr_image_t object is all set up, the
+* jxr_read_image_bitstream function is called to read the bitstream
+* and decompress it. This function assumes that the fd is open for
+* read and set to the beginning of the bitstream (where the magic
+* number starts).
+*
+* JXR_EC_BADMAGIC
+* The magic number is wrong, implying that it is not an JPEG XR
+* bitstream.
+*/
+JXR_EXTERN int jxr_read_image_bitstream(jxr_image_t image, FILE*fd);
+
+/*
+* After decoder is run, test desired LONG_WORD_FLAG against
+* calculations done in decoder
+*/
+JXR_EXTERN int jxr_test_LONG_WORD_FLAG(jxr_image_t image, int flag);
+
+/*
+* Given an image cookie that represents an image, and an fd opened
+* for write, write the entire JPEG XR bit stream.
+*/
+JXR_EXTERN int jxr_write_image_bitstream(jxr_image_t image, FILE*fd);
+
+
+/*
+* jxr error codes. Many of the above functions return a positive
+* (>=0) value or a negative error code. The error codes are:
+*/
+
+# define JXR_EC_OK (0) /* No error */
+# define JXR_EC_ERROR (-1) /* Unspecified error */
+# define JXR_EC_BADMAGIC (-2) /* Stream lacks proper magic number. */
+# define JXR_EC_FEATURE_NOT_IMPLEMENTED (-3)
+# define JXR_EC_IO (-4) /* Error reading/writing data */
+# define JXR_EC_BADFORMAT (-5) /* Bad file format */
+
+
+#undef JXR_EXTERN
+
+/*
+* $Log: jpegxr.h,v $
+* Revision 1.28 2009/05/29 12:00:00 microsoft
+* Reference Software v1.6 updates.
+*
+* Revision 1.27 2009/04/13 12:00:00 microsoft
+* Reference Software v1.5 updates.
+*
+* Revision 1.26 2008/03/18 18:36:56 steve
+* Support compress of CMYK images.
+*
+* Revision 1.25 2008/03/18 15:50:08 steve
+* Gray images must be UNIFORM
+*
+* Revision 1.24 2008/03/06 02:05:48 steve
+* Distributed quantization
+*
+* Revision 1.23 2008/03/05 04:04:30 steve
+* Clarify constraints on USE_DC_QP in image plane header.
+*
+* Revision 1.22 2008/03/05 01:27:15 steve
+* QP_UNIFORM may use USE_DC_LP optionally.
+*
+* Revision 1.21 2008/03/05 00:31:17 steve
+* Handle UNIFORM/IMAGEPLANE_UNIFORM compression.
+*
+* Revision 1.20 2008/03/04 23:01:28 steve
+* Cleanup QP API in preparation for distributed QP
+*
+* Revision 1.19 2008/03/02 19:56:27 steve
+* Infrastructure to read write BD16 files.
+*
+* Revision 1.18 2008/03/01 02:46:09 steve
+* Add support for JXR container.
+*
+* Revision 1.17 2008/02/29 01:29:57 steve
+* Mark more extern functions for MSC.
+*
+* Revision 1.16 2008/02/28 18:50:31 steve
+* Portability fixes.
+*
+* Revision 1.15 2008/02/26 23:52:44 steve
+* Remove ident for MS compilers.
+*
+* Revision 1.14 2008/02/26 23:28:53 steve
+* Remove C99 requirements from the API.
+*
+* Revision 1.13 2008/02/01 22:49:53 steve
+* Handle compress of YUV444 color DCONLY
+*
+* Revision 1.12 2008/01/08 01:06:20 steve
+* Add first pass overlap filtering.
+*
+* Revision 1.11 2008/01/06 01:29:28 steve
+* Add support for TRIM_FLEXBITS in compression.
+*
+* Revision 1.10 2008/01/04 17:07:35 steve
+* API interface for setting QP values.
+*
+* Revision 1.9 2007/11/30 01:50:58 steve
+* Compression of DCONLY GRAY.
+*
+* Revision 1.8 2007/11/26 01:47:15 steve
+* Add copyright notices per MS request.
+*
+* Revision 1.7 2007/11/08 02:52:32 steve
+* Some progress in some encoding infrastructure.
+*
+* Revision 1.6 2007/11/07 18:11:45 steve
+* Missing error code.
+*
+* Revision 1.5 2007/11/06 22:32:34 steve
+* Documentation for the jpegxr library use.
+*
+* Revision 1.4 2007/09/08 01:01:43 steve
+* YUV444 color parses properly.
+*
+* Revision 1.3 2007/07/30 23:09:57 steve
+* Interleave FLEXBITS within HP block.
+*
+* Revision 1.2 2007/07/21 00:25:48 steve
+* snapshot 2007 07 20
+*
+* Revision 1.1 2007/06/06 17:19:12 steve
+* Introduce to CVS.
+*
+*/
+
+#endif
diff --git a/jpegxr/jpegxr_pixelformat.c b/jpegxr/jpegxr_pixelformat.c
new file mode 100644
index 000000000..b68d28be8
--- /dev/null
+++ b/jpegxr/jpegxr_pixelformat.c
@@ -0,0 +1,156 @@
+/*
+**
+** $Id: jpegxr_priv.c,v 1.0 2009-02-23 13:47:11 Radhika Exp $
+**
+**
+*/
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+***********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: jpegxr_priv.c,v 1.0 2009-02-23 13:47:11 Radhika Exp $")
+#else
+#ident "$Id: jpegxr_priv.c,v 1.0 2009-02-23 13:47:11 Radhika Exp $"
+#endif
+#include "jxr_priv.h"
+#include <string.h>
+/*
+* This file contains functions for pixel format parsing
+*/
+unsigned char jxr_guids[NUM_GUIDS][16]=
+{
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x0D},/* JXR_24bppRGB = 0, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x0C},/* JXR_24bppBGR, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x0E},/* JXR_32bppBGR, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x15},/* JXR_48bppRGB, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x12},/* JXR_48bppRGBFixedPoint, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x3B},/* JXR_48bppRGBHalf, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x18},/* JXR_96bppRGBFixedPoint, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x40},/* JXR_64bppRGBFixedPoint, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x42},/* JXR_64bppRGBHalf, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x41},/* JXR_128bppRGBFixedPoint, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x1B},/* JXR_128bppRGBFloat, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x0F},/* JXR_32bppBGRA, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x16},/* JXR_64bppRGBA, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x1D},/* JXR_64bppRGBAFixedPoint, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x3A},/* JXR_64bppRGBAHalf, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x1E},/* JXR_128bppRGBAFixedPoint, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x19},/* JXR_128bppRGBAFloat, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x10},/* JXR_32bppPBGRA, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x17},/* JXR_64bppPRGBA, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x1A},/* JXR_128bppPRGBAFloat, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x1C},/* JXR_32bppCMYK, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x2C},/* JXR_40bppCMYKAlpha, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x1F},/* JXR_64bppCMYK, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x2D},/* JXR_80bppCMYKAlpha, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x20},/* JXR_24bpp3Channels, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x21},/* JXR_32bpp4Channels, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x22},/* JXR_40bpp5Channels, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x23},/* JXR_48bpp6Channels, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x24},/* JXR_56bpp7Channels, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x25},/* JXR_64bpp8Channels, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x2E},/* JXR_32bpp3ChannelsAlpha, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x2F},/* JXR_40bpp4ChannelsAlpha, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x30},/* JXR_48bpp5ChannelsAlpha, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x31},/* JXR_56bpp6ChannelsAlpha, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x32},/* JXR_64bpp7ChannelsAlpha, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x33},/* JXR_72bpp8ChannelsAlpha, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x26},/* JXR_48bpp3Channels, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x27},/* JXR_64bpp4Channels, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x28},/* JXR_80bpp5Channels, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x29},/* JXR_96bpp6Channels, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x2A},/* JXR_112bpp7Channels, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x2B},/* JXR_128bpp8Channels, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x34},/* JXR_64bpp3ChannelsAlpha, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x35},/* JXR_80bpp4ChannelsAlpha, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x36},/* JXR_96bpp5ChannelsAlpha, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x37},/* JXR_112bpp6ChannelsAlpha, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x38},/* JXR_128bpp7ChannelsAlpha, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x39},/* JXR_144bpp8ChannelsAlpha, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x08},/* JXR_8bppGray, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x0B},/* JXR_16bppGray, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x13},/* JXR_16bppGrayFixedPoint, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x3E},/* JXR_16bppGrayHalf, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x3F},/* JXR_32bppGrayFixedPoint, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x11},/* JXR_32bppGrayFloat, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x05},/* JXR_BlackWhite, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x09},/* JXR_16bppBGR555, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x0A},/* JXR_16bppBGR565, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x14},/* JXR_32bppBGR101010, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x3D},/* JXR_32bppRGBE, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x54},/* JXR_32bppCMYKDIRECT, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x55},/* JXR_64bppCMYKDIRECT, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x56},/* JXR_40bppCMYKDIRECTAlpha, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x43},/* JXR_80bppCMYKDIRECTAlpha, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x44},/* JXR_12bppYCC420, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x45},/* JXR_16bppYCC422, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x46},/* JXR_20bppYCC422, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x47},/* JXR_32bppYCC422, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x48},/* JXR_24bppYCC444, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x49},/* JXR_30bppYCC444, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x4A},/* JXR_48bppYCC444, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x4B},/* JXR_48bppYCC444FixedPoint, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x4C},/* JXR_20bppYCC420Alpha, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x4D},/* JXR_24bppYCC422Alpha, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x4E},/* JXR_30bppYCC422Alpha, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x4F},/* JXR_48bppYCC422Alpha, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x50},/* JXR_32bppYCC444Alpha, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x51},/* JXR_40bppYCC444Alpha, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x52},/* JXR_64bppYCC444Alpha, */
+ {0x24, 0xC3, 0xDD, 0x6F, 03, 0x4E, 0xFE, 0x4B, 0xB1, 0x85, 0x3D, 0x77, 0x76, 0x8D, 0xC9, 0x53} /* JXR_64bppYCC444AlphaFixedPoint, */
+};
+
+unsigned int isEqualGUID(unsigned char guid1[16], unsigned char guid2[16])
+{
+ return memcmp(guid1,guid2,16) == 0;
+}
+
+
+/*
+* $Log: jpegxr_pixelformat.c,v $
+* Revision 1.2 2009/05/29 12:00:00 microsoft
+* Reference Software v1.6 updates.
+*
+* Revision 1.1 2009/04/13 12:00:00 microsoft
+* Reference Software v1.5 updates.
+*
+*/
+
diff --git a/jpegxr/jxr_priv.h b/jpegxr/jxr_priv.h
new file mode 100644
index 000000000..a46134746
--- /dev/null
+++ b/jpegxr/jxr_priv.h
@@ -0,0 +1,821 @@
+#ifndef __jxr_priv_H
+#define __jxr_priv_H
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+***********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: jxr_priv.h,v 1.3 2008-05-13 13:47:11 thor Exp $")
+#else
+#ident "$Id: jxr_priv.h,v 1.3 2008-05-13 13:47:11 thor Exp $"
+#endif
+
+# include "jpegxr.h"
+
+#ifndef _MSC_VER
+# include <stdint.h>
+#else
+/* MSVC (as of 2008) does not support C99 or the stdint.h header
+file. So include a private little header file here that does the
+minimal typedefs that we need. */
+# include "stdint_minimal.h"
+#endif
+
+/* define this to check if range of values exceeds signed 16-bit */
+#define VERIFY_16BIT
+
+#ifdef VERIFY_16BIT
+#define CHECK1(flag, a) if(((a) < -0x8000) || ((a) >= 0x8000)) flag = 1
+#else
+#define CHECK1(flag, a) do { } while(0)
+#endif
+
+#define CHECK2(flag, a, b) CHECK1(flag, a); CHECK1(flag, b)
+#define CHECK3(flag, a, b, c) CHECK2(flag, a, b); CHECK1(flag, c)
+#define CHECK4(flag, a, b, c, d) CHECK3(flag, a, b, c); CHECK1(flag, d)
+#define CHECK5(flag, a, b, c, d, e) CHECK4(flag, a, b, c, d); CHECK1(flag, e)
+#define CHECK6(flag, a, b, c, d, e, f) CHECK5(flag, a, b, c, d, e); CHECK1(flag, f)
+
+struct macroblock_s{
+ int*data;
+ /* This is used to temporarily hold Predicted values. */
+ int*pred_dclp;
+ /* */
+ unsigned lp_quant : 8;
+ unsigned hp_quant : 8;
+ int mbhp_pred_mode : 3;
+ int have_qnt : 1;/* THOR: If set, the quant values are valid */
+ /* Stash HP CBP values for the macroblock. */
+ int hp_cbp, hp_diff_cbp;
+ /* model_bits for current HP. HP uses this to pass model_bits
+ to FLEXBITS parsing. */
+ unsigned hp_model_bits[2];
+};
+
+struct adaptive_vlc_s{
+ int discriminant;
+ int discriminant2;
+ int table;
+ int deltatable;
+ int delta2table;
+};
+
+struct cbp_model_s{
+ int state[2];
+ int count0[2];
+ int count1[2];
+};
+
+typedef enum abs_level_vlc_index_e{
+ AbsLevelIndDCLum,
+ AbsLevelIndDCChr,
+ DecFirstIndLPLum,
+ AbsLevelIndLP0,
+ AbsLevelIndLP1,
+ AbsLevelIndHP0,
+ AbsLevelIndHP1,
+ DecIndLPLum0,
+ DecIndLPLum1,
+ DecFirstIndLPChr,
+ DecIndLPChr0,
+ DecIndLPChr1,
+ DecNumCBP,
+ DecNumBlkCBP,
+ DecIndHPLum0,
+ DecIndHPLum1,
+ DecFirstIndHPLum,
+ DecFirstIndHPChr,
+ DecIndHPChr0,
+ DecIndHPChr1,
+ AbsLevelInd_COUNT
+}abs_level_vlc_index_t;
+
+struct model_s{
+ int bits[2];
+ int state[2];
+};
+
+struct jxr_image{
+ int user_flags;
+
+ /* These store are the width/height minus 1 (so that 4Gwidth
+ is OK but 0 width is not.) This, by the way, is how the
+ width/height is stored in the HPPhoto stream too. */
+ uint32_t width1;
+ uint32_t height1;
+ uint32_t extended_width;
+ uint32_t extended_height;
+
+ uint8_t header_flags1;
+ uint8_t header_flags2;
+ /* Color format of the source image data */
+ uint8_t header_flags_fmt;
+ jxr_output_clr_fmt_t output_clr_fmt;
+ /* Color format to use internally. */
+ /* 0=YONLY, 1=YUV420, 2=YUV422, 3=YUV444, 4=CMYK, 5=CMYKDIRECT, 6=NCOMPONENT */
+ uint8_t use_clr_fmt;
+
+ /* pixel format */
+ jxrc_t_pixelFormat ePixelFormat;
+
+ /* If TRIM_FLEXBITS_FLAG, then this is the bits to trim. */
+ unsigned trim_flexbits : 4;
+
+ /* 0==ALL, 1==NOFLEXBITS, 2==NOHIGHPASS, 3==DCONLY, 4==ISOLATED */
+ uint8_t bands_present;
+ uint8_t bands_present_of_primary; /* stores value of primary image plane to apply restriction on value of alpha image plane */
+
+ uint8_t chroma_centering_x;
+ uint8_t chroma_centering_y;
+
+ uint8_t num_channels;
+
+ /* Disable overlap flag, true for hard tiles, false for soft tiles*/
+ unsigned disableTileOverlapFlag;
+
+ unsigned tile_rows;
+ unsigned tile_columns;
+ unsigned*tile_row_height;
+ unsigned*tile_column_width;
+ /* This is the position in image macroblocks. */
+ unsigned*tile_column_position;
+ unsigned*tile_row_position;
+ /* The numbers collected by INDEX_TABLE */
+ int64_t*tile_index_table;
+ int64_t tile_index_table_length;
+
+ uint16_t window_extra_top;
+ uint16_t window_extra_left;
+ uint16_t window_extra_bottom;
+ uint16_t window_extra_right;
+
+ /* Information from the plane header. */
+
+ unsigned scaled_flag : 1;
+ unsigned dc_frame_uniform : 1;
+ unsigned lp_use_dc_qp : 1;
+ unsigned lp_frame_uniform : 1;
+ unsigned hp_use_lp_qp : 1;
+ unsigned hp_frame_uniform : 1;
+
+ unsigned char shift_bits;
+ unsigned char len_mantissa;
+ char exp_bias;
+
+ /* Per-tile information (changes as tiles are processed) */
+ unsigned num_lp_qps;
+ unsigned num_hp_qps;
+
+ /* State variables used by encoder/decoder. */
+ int cur_my; /* Address of strip_cur */
+ struct{
+ struct macroblock_s*up4;
+ struct macroblock_s*up3;
+ struct macroblock_s*up2;
+ struct macroblock_s*up1;
+ struct macroblock_s*cur;
+ int *upsample_memory_y; /* Number of elements is dependent on number of MBs in each MB row */
+ int *upsample_memory_x; /* Always contains 16 elements */
+ }strip[MAX_CHANNELS];
+
+ /* SPATIAL: Hold previous strips of current tile */
+ /* FREQUENCY: mbs for the entire image. */
+ struct macroblock_s*mb_row_buffer[MAX_CHANNELS];
+ /* Hold final 4 strips of previous tile */
+ struct macroblock_s*mb_row_context[MAX_CHANNELS];
+
+ struct adaptive_vlc_s vlc_table[AbsLevelInd_COUNT];
+ int count_max_CBPLP;
+ int count_zero_CBPLP;
+
+ struct cbp_model_s hp_cbp_model;
+
+ unsigned lopass_scanorder[15];
+ unsigned lopass_scantotals[15];
+
+ unsigned hipass_hor_scanorder[15];
+ unsigned hipass_hor_scantotals[15];
+ unsigned hipass_ver_scanorder[15];
+ unsigned hipass_ver_scantotals[15];
+
+ jxr_component_mode_t dc_component_mode, lp_component_mode, hp_component_mode;
+
+ /* Quantization parameters for up to 16 channels. */
+ unsigned char dc_quant_ch[MAX_CHANNELS];
+ unsigned char lp_quant_ch[MAX_CHANNELS][MAX_LP_QPS];
+ unsigned char hp_quant_ch[MAX_CHANNELS][MAX_HP_QPS];
+# define HP_QUANT_Y hp_quant_ch[0]
+
+ /* Per-tile quantization data (used during encode) */
+ struct jxr_tile_qp*tile_quant;
+# define GET_TILE_QUANT(image,tx,ty) ((image)->tile_quant + (ty)*((image)->tile_rows+1) + (tx))
+
+ struct model_s model_dc, model_lp, model_hp;
+
+ struct model_s*model_hp_buffer;
+ struct cbp_model_s*hp_cbp_model_buffer;
+
+ block_fun_t out_fun;
+ block_fun_t inp_fun;
+ void*user_data;
+
+ struct jxr_image * alpha; /* interleaved alpha image plane */
+ int primary; /* primary channel or alpha channel */
+
+ uint8_t profile_idc;
+ uint8_t level_idc;
+
+ uint8_t lwf_test; /* flag to track whether long_word_flag needs to be TRUE */
+
+ /* store container values */
+ uint32_t container_width;
+ uint32_t container_height;
+ uint8_t container_nc;
+ uint8_t container_alpha;
+ uint8_t container_separate_alpha;
+ jxr_bitdepth_t container_bpc;
+ jxr_output_clr_fmt_t container_color;
+ uint8_t container_image_band_presence;
+ uint8_t container_alpha_band_presence;
+ uint8_t container_current_separate_alpha;
+};
+
+extern unsigned char _jxr_select_lp_index(jxr_image_t image, unsigned tx, unsigned ty,
+ unsigned mx, unsigned my);
+extern unsigned char _jxr_select_hp_index(jxr_image_t image, unsigned tx, unsigned ty,
+ unsigned mx, unsigned my);
+
+/* User flags for controlling encode/decode */
+# define SKIP_HP_DATA(image) ((image)->user_flags & 0x0001)
+# define SKIP_FLEX_DATA(image) ((image)->user_flags & 0x0002)
+
+/* Get the width of the image in macroblocks. Round up. */
+# define WIDTH_BLOCKS(image) (((image)->width1 + 16) >> 4)
+# define HEIGHT_BLOCKS(image) (((image)->height1 + 16) >> 4)
+
+# define EXTENDED_WIDTH_BLOCKS(image) (((image)->extended_width) >> 4)
+# define EXTENDED_HEIGHT_BLOCKS(image) (((image)->extended_height) >> 4)
+
+/* TRUE if tiling is supported in this image. */
+# define TILING_FLAG(image) ((image)->header_flags1 & 0x80)
+/* TRUE if the bitstream format is frequency mode (FREQUENCY_MODE_CODESTREAM_FLAG is true), FALSE for spatial mode */
+# define FREQUENCY_MODE_CODESTREAM_FLAG(image) ((image)->header_flags1 & 0x40)
+/* TRUE if the INDEXTABLE_PRESENT_FLAG is set for the image. */
+# define INDEXTABLE_PRESENT_FLAG(image) ((image)->header_flags1 & 0x04)
+/* OVERLAP value: 0, 1, 2 or 3 */
+# define OVERLAP_INFO(image) ((image)->header_flags1 & 0x03)
+/* LONG_WORD_FLAG */
+# define LONG_WORD_FLAG(image) ((image)->header_flags2 & 0x40)
+
+/* TRUE if the SHORT_HEADER flag is set. */
+# define SHORT_HEADER_FLAG(image) ((image)->header_flags2 & 0x80)
+/* TRUE if windowing is allowed, 0 otherwise. */
+# define WINDOWING_FLAG(image) ((image)->header_flags2 & 0x20)
+# define TRIM_FLEXBITS_FLAG(image) ((image)->header_flags2 & 0x10)
+# define ALPHACHANNEL_FLAG(image) ((image)->header_flags2 & 0x01)
+
+# define SOURCE_CLR_FMT(image) (((image)->header_flags_fmt >> 4) & 0x0f)
+
+/* SOURCE_BITDEPTH (aka OUTPUT_BITDEPTH) can be:
+* 0 BD1WHITE1
+* 1 BD8
+* 2 BD16
+* 3 BD16S
+* 4 BD16F
+* 5 RESERVED
+* 6 BD32S
+* 7 BD32F
+* 8 BD5
+* 9 BD10
+* 10 BD565
+* 11 RESERVED
+* 12 RESERVED
+* 13 RESERVED
+* 14 RESERVED
+* 15 BD1BLACK1
+*/
+# define SOURCE_BITDEPTH(image) (((image)->header_flags_fmt >> 0) & 0x0f)
+
+/*
+* Given the tile index and macroblock index within the tile, return
+* the l-value macroblock structure.
+*/
+# define MACROBLK_CUR(image,c,tx,mx) ((image)->strip[c].cur[(image)->tile_column_position[tx]+mx])
+# define MACROBLK_UP1(image,c,tx,mx) ((image)->strip[c].up1[(image)->tile_column_position[tx]+mx])
+# define MACROBLK_UP2(image,c,tx,mx) ((image)->strip[c].up2[(image)->tile_column_position[tx]+mx])
+# define MACROBLK_UP3(image,c,tx,mx) ((image)->strip[c].up3[(image)->tile_column_position[tx]+mx])
+# define MACROBLK_UP4(image,c,tx,mx) ((image)->strip[c].up4[(image)->tile_column_position[tx]+mx])
+
+/* Return the l-value of the DC coefficient in the macroblock. */
+# define MACROBLK_UP2_DC(image, c, tx, mx) (MACROBLK_UP2(image,c,tx,mx).data[0])
+# define MACROBLK_UP_DC(image, c, tx, mx) (MACROBLK_UP1(image,c,tx,mx).data[0])
+# define MACROBLK_CUR_DC(image, c, tx, mx) (MACROBLK_CUR(image,c,tx,mx).data[0])
+/* Return the l-value of the LP coefficient in the macroblock.
+The k value can range from 0-14. (There are 15 LP coefficients.) */
+# define MACROBLK_CUR_LP(image,c,tx,mx,k) (MACROBLK_CUR(image,c,tx,mx).data[1+k])
+# define MACROBLK_UP_LP(image,c,tx,mx,k) (MACROBLK_UP1(image,c,tx,mx).data[1+k])
+# define MACROBLK_UP2_LP(image,c,tx,mx,k) (MACROBLK_UP2(image,c,tx,mx).data[1+k])
+
+# define MACROBLK_CUR_LP_QUANT(image,c,tx,mx) (MACROBLK_CUR(image,c,tx,mx).lp_quant)
+# define MACROBLK_UP1_LP_QUANT(image,c,tx,mx) (MACROBLK_UP1(image,c,tx,mx).lp_quant)
+# define MACROBLK_UP2_LP_QUANT(image,c,tx,mx) (MACROBLK_UP2(image,c,tx,mx).lp_quant)
+
+/* Return the l-value of the HP coefficient in the macroblk.
+The blk value is 0-15 and identifies the block within the macroblk.
+The k value is 0-14 and addresses the coefficient within the blk. */
+# define MACROBLK_CUR_HP(image,c,tx,mx,blk,k) (MACROBLK_CUR(image,c,tx,mx).data[16+15*(blk)+(k)])
+# define MACROBLK_UP1_HP(image,c,tx,mx,blk,k) (MACROBLK_UP1(image,c,tx,mx).data[16+15*(blk)+(k)])
+# define MACROBLK_UP2_HP(image,c,tx,mx,blk,k) (MACROBLK_UP2(image,c,tx,mx).data[16+15*(blk)+(k)])
+
+# define MACROBLK_CUR_HP_QUANT(image,c,tx,mx) (MACROBLK_CUR(image,c,tx,mx).hp_quant)
+# define MACROBLK_UP1_HP_QUANT(image,c,tx,mx) (MACROBLK_UP1(image,c,tx,mx).hp_quant)
+# define MACROBLK_UP2_HP_QUANT(image,c,tx,mx) (MACROBLK_UP2(image,c,tx,mx).hp_quant)
+
+/* Return the l-value of the HP CBP value. */
+# define MACROBLK_CUR_HPCBP(image,c,tx,mx) (MACROBLK_CUR(image,c,tx,mx).hp_cbp)
+# define MACROBLK_UP1_HPCBP(image,c,tx,mx) (MACROBLK_UP1(image,c,tx,mx).hp_cbp)
+
+extern void _jxr_make_mbstore(jxr_image_t image, int include_up4);
+extern void _jxr_fill_strip(jxr_image_t image);
+extern void _jxr_rflush_mb_strip(jxr_image_t image, int tx, int ty, int my);
+extern void _jxr_wflush_mb_strip(jxr_image_t image, int tx, int ty, int my, int read_new);
+
+/* Common strip handling functions. */
+extern void _jxr_clear_strip_cur(jxr_image_t image);
+extern void _jxr_r_rotate_mb_strip(jxr_image_t image);
+
+/* Wrap up an image collected in frequency mode. */
+extern void _jxr_frequency_mode_render(jxr_image_t image);
+
+/* Application interface functions */
+extern void _jxr_send_mb_to_output(jxr_image_t image, int mx, int my, int*data);
+
+/* I/O functions. */
+
+struct rbitstream{
+ unsigned char byte;
+ int bits_avail;
+ FILE*fd;
+ size_t read_count;
+
+ long mark_stream_position;
+};
+
+/* Get the current *bit* position, for diagnostic use. */
+extern void _jxr_rbitstream_initialize(struct rbitstream*str, FILE*fd);
+extern size_t _jxr_rbitstream_bitpos(struct rbitstream*str);
+
+extern void _jxr_rbitstream_syncbyte(struct rbitstream*str);
+extern int _jxr_rbitstream_uint1(struct rbitstream*str);
+extern uint8_t _jxr_rbitstream_uint2(struct rbitstream*str);
+extern uint8_t _jxr_rbitstream_uint3(struct rbitstream*str);
+extern uint8_t _jxr_rbitstream_uint4(struct rbitstream*str);
+extern uint8_t _jxr_rbitstream_uint6(struct rbitstream*str);
+extern uint8_t _jxr_rbitstream_uint8(struct rbitstream*str);
+extern uint16_t _jxr_rbitstream_uint12(struct rbitstream*str);
+extern uint16_t _jxr_rbitstream_uint15(struct rbitstream*str);
+extern uint16_t _jxr_rbitstream_uint16(struct rbitstream*str);
+extern uint32_t _jxr_rbitstream_uint32(struct rbitstream*str);
+extern uint32_t _jxr_rbitstream_uintN(struct rbitstream*str, int N);
+/* Return <0 if there is an escape code. */
+extern int64_t _jxr_rbitstream_intVLW(struct rbitstream*str);
+
+extern int _jxr_rbitstream_intE(struct rbitstream*str, int code_size,
+ const unsigned char*codeb,
+ const signed char*codev);
+extern const char* _jxr_vlc_index_name(int vlc);
+
+/*
+* These functions provided limited random access into the file
+* stream. The mark() function causes a given point to be marked as
+* "zero", then the seek() function can go to a *byte* position
+* relative the zeo mark. These functions can only be called when the
+* stream is on a byte boundary.
+*/
+extern void _jxr_rbitstream_mark(struct rbitstream*str);
+extern void _jxr_rbitstream_seek(struct rbitstream*str, uint64_t off);
+
+struct wbitstream{
+ unsigned char byte;
+ int bits_ready;
+ FILE*fd;
+ size_t write_count;
+};
+
+extern void _jxr_wbitstream_initialize(struct wbitstream*str, FILE*fd);
+extern size_t _jxr_wbitstream_bitpos(struct wbitstream*str);
+extern void _jxr_wbitstream_syncbyte(struct wbitstream*str);
+extern void _jxr_wbitstream_uint1(struct wbitstream*str, int val);
+extern void _jxr_wbitstream_uint2(struct wbitstream*str, uint8_t val);
+extern void _jxr_wbitstream_uint3(struct wbitstream*str, uint8_t val);
+extern void _jxr_wbitstream_uint4(struct wbitstream*str, uint8_t val);
+extern void _jxr_wbitstream_uint6(struct wbitstream*str, uint8_t val);
+extern void _jxr_wbitstream_uint8(struct wbitstream*str, uint8_t val);
+extern void _jxr_wbitstream_uint12(struct wbitstream*str, uint16_t val);
+extern void _jxr_wbitstream_uint15(struct wbitstream*str, uint16_t val);
+extern void _jxr_wbitstream_uint16(struct wbitstream*str, uint16_t val);
+extern void _jxr_wbitstream_uint32(struct wbitstream*str, uint32_t val);
+extern void _jxr_wbitstream_uintN(struct wbitstream*str, uint32_t val, int N);
+extern void _jxr_wbitstream_intVLW(struct wbitstream*str, uint64_t val);
+extern void _jxr_wbitstream_flush(struct wbitstream*str);
+
+extern void _jxr_wbitstream_mark(struct wbitstream*str);
+extern void _jxr_wbitstream_seek(struct wbitstream*str, uint64_t off);
+
+extern void _jxr_w_TILE_SPATIAL(jxr_image_t image, struct wbitstream*str,
+ unsigned tx, unsigned ty);
+extern void _jxr_w_TILE_DC(jxr_image_t image, struct wbitstream*str,
+ unsigned tx, unsigned ty);
+extern void _jxr_w_TILE_LP(jxr_image_t image, struct wbitstream*str,
+ unsigned tx, unsigned ty);
+extern void _jxr_w_TILE_HP_FLEX(jxr_image_t image, struct wbitstream*str,
+ unsigned tx, unsigned ty);
+extern void _jxr_w_TILE_HEADER_DC(jxr_image_t image, struct wbitstream*str,
+ int alpha_flag, unsigned tx, unsigned ty);
+extern void _jxr_w_TILE_HEADER_LOWPASS(jxr_image_t image, struct wbitstream*str,
+ int alpha_flag, unsigned tx, unsigned ty);
+extern void _jxr_w_TILE_HEADER_HIGHPASS(jxr_image_t image, struct wbitstream*str,
+ int alpha_flag, unsigned tx, unsigned ty);
+extern void _jxr_w_MB_DC(jxr_image_t image, struct wbitstream*str,
+ int alpha_flag,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my);
+extern void _jxr_w_MB_LP(jxr_image_t image, struct wbitstream*str,
+ int alpha_flag,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my);
+extern int _jxr_w_MB_HP(jxr_image_t image, struct wbitstream*str,
+ int alpha_flag,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my, struct wbitstream*strFB);
+extern void _jxr_w_MB_CBP(jxr_image_t image, struct wbitstream*str,
+ int alpha_flag,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my);
+extern void _jxr_w_DC_QP(jxr_image_t image, struct wbitstream*str);
+extern void _jxr_w_LP_QP(jxr_image_t image, struct wbitstream*str);
+extern void _jxr_w_HP_QP(jxr_image_t image, struct wbitstream*str);
+extern void _jxr_w_ENCODE_QP_INDEX(jxr_image_t image, struct wbitstream*str,
+ unsigned tx, unsigned ty, unsigned mx, unsigned my,
+ unsigned num_qps, unsigned qp_index);
+
+
+extern int _jxr_r_TILE_SPATIAL(jxr_image_t image, struct rbitstream*str,
+ unsigned tx, unsigned ty);
+extern int _jxr_r_TILE_DC(jxr_image_t image, struct rbitstream*str,
+ unsigned tx, unsigned ty);
+extern int _jxr_r_TILE_LP(jxr_image_t image, struct rbitstream*str,
+ unsigned tx, unsigned ty);
+extern int _jxr_r_TILE_HP(jxr_image_t image, struct rbitstream*str,
+ unsigned tx, unsigned ty);
+extern int _jxr_r_TILE_FLEXBITS(jxr_image_t image, struct rbitstream*str,
+ unsigned tx, unsigned ty);
+extern int _jxr_r_TILE_FLEXBITS_ESCAPE(jxr_image_t image,
+ unsigned tx, unsigned ty);
+extern void _jxr_r_TILE_HEADER_DC(jxr_image_t image, struct rbitstream*str,
+ int alpha_flag, unsigned tx, unsigned ty);
+extern void _jxr_r_TILE_HEADER_LOWPASS(jxr_image_t image, struct rbitstream*str,
+ int alpha_flag, unsigned tx, unsigned ty);
+extern void _jxr_r_TILE_HEADER_HIGHPASS(jxr_image_t image, struct rbitstream*str,
+ int alpha_flag, unsigned tx, unsigned ty);
+
+extern void _jxr_r_MB_DC(jxr_image_t image, struct rbitstream*str,
+ int alpha_flag,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my);
+extern void _jxr_r_MB_LP(jxr_image_t image, struct rbitstream*str,
+ int alpha_flag,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my);
+extern int _jxr_r_MB_HP(jxr_image_t image, struct rbitstream*str,
+ int alpha_flag,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my);
+extern int _jxr_r_MB_CBP(jxr_image_t image, struct rbitstream*str,
+ int alpha_flag,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my);
+int _jxr_r_MB_FLEXBITS(jxr_image_t image, struct rbitstream*str,
+ int alpha_flag,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my);
+
+extern int _jxr_r_DC_QP(jxr_image_t image, struct rbitstream*str);
+extern int _jxr_r_LP_QP(jxr_image_t image, struct rbitstream*str);
+
+extern unsigned _jxr_DECODE_QP_INDEX(struct rbitstream*str,
+ unsigned index_count);
+extern int r_DECODE_BLOCK(jxr_image_t image, struct rbitstream*str,
+ int chroma_flag, int coeff[16], int band, int location);
+
+/* algorithm functions */
+/*
+* In these functions, the mx and my are the position of the MB
+* within a tile (i.e. mx=my=0 is the top left MB in the TILE not
+* necessarily the image). The mx and my are given it units of MB. The
+* pixel position is mx*16, my*16.
+*/
+
+extern int _jxr_quant_map(jxr_image_t image, int x, int shift);
+extern int _jxr_InitContext(jxr_image_t image, unsigned tx, unsigned ty,
+ unsigned mx, unsigned my);
+extern int _jxr_ResetContext(jxr_image_t image, unsigned tx, unsigned mx);
+extern int _jxr_ResetTotals(jxr_image_t image, unsigned mx);
+extern int _jxr_vlc_select(int band, int chroma_flag);
+extern void _jxr_InitVLCTable(jxr_image_t image, int vlc_select);
+extern void _jxr_AdaptVLCTable(jxr_image_t image, int vlc_select);
+extern void _jxr_AdaptLP(jxr_image_t image);
+extern void _jxr_AdaptHP(jxr_image_t image);
+extern void _jxr_InitializeModelMB(struct model_s*model, int band);
+extern void _jxr_UpdateModelMB(jxr_image_t image, int lap_mean[2],
+struct model_s*model, int band);
+
+extern void _jxr_InitializeCountCBPLP(jxr_image_t image);
+extern void _jxr_UpdateCountCBPLP(jxr_image_t image, int cbplp, int max);
+
+extern void _jxr_InitLPVLC(jxr_image_t image);
+extern void _jxr_InitCBPVLC(jxr_image_t image);
+extern void _jxr_InitHPVLC(jxr_image_t image);
+
+extern void _jxr_InitializeCBPModel(jxr_image_t image);
+extern void _jxr_w_PredCBP444(jxr_image_t image,
+ int ch, unsigned tx,
+ unsigned mx, int my);
+extern void _jxr_w_PredCBP422(jxr_image_t image,
+ int ch, unsigned tx,
+ unsigned mx, int my);
+extern void _jxr_w_PredCBP420(jxr_image_t image,
+ int ch, unsigned tx,
+ unsigned mx, int my);
+extern int _jxr_PredCBP444(jxr_image_t image, int*diff_cbp,
+ int channel, unsigned tx, unsigned mx, unsigned my);
+extern int _jxr_PredCBP422(jxr_image_t image, int*diff_cbp,
+ int channel, unsigned tx, unsigned mx, unsigned my);
+extern int _jxr_PredCBP420(jxr_image_t image, int*diff_cbp,
+ int channel, unsigned tx, unsigned mx, unsigned my);
+extern void _jxr_UpdateCBPModel(jxr_image_t image);
+
+extern void _jxr_InitializeAdaptiveScanLP(jxr_image_t image);
+extern void _jxr_ResetTotalsAdaptiveScanLP(jxr_image_t image);
+
+extern void _jxr_InitializeAdaptiveScanHP(jxr_image_t image);
+extern void _jxr_ResetTotalsAdaptiveScanHP(jxr_image_t image);
+
+extern void _jxr_complete_cur_dclp(jxr_image_t image, int tx, int mx, int my);
+extern void _jxr_propagate_hp_predictions(jxr_image_t image,
+ int ch, unsigned tx, unsigned mx,
+ int mbhp_pred_mode);
+
+extern void _jxr_4OverlapFilter(int*a, int*b, int*c, int*d);
+extern void _jxr_4x4OverlapFilter(int*a, int*b, int*c, int*d,
+ int*e, int*f, int*g, int*h,
+ int*i, int*j, int*k, int*l,
+ int*m, int*n, int*o, int*p);
+extern void _jxr_2OverlapFilter(int*a, int*b);
+
+extern void _jxr_2x2OverlapFilter(int*a, int*b, int*c, int*d);
+
+extern void _jxr_4PreFilter(int*a, int*b, int*c, int*d);
+extern void _jxr_4x4PreFilter(int*a, int*b, int*c, int*d,
+ int*e, int*f, int*g, int*h,
+ int*i, int*j, int*k, int*l,
+ int*m, int*n, int*o, int*p);
+
+extern void _jxr_2PreFilter(int*a, int*b);
+
+extern void _jxr_2x2PreFilter(int*a, int*b, int*c, int*d);
+
+extern const int _jxr_abslevel_index_delta[7];
+
+/*
+* All the blocks of HP data (16 blocks, 15 coefficients per block) in
+* a macroblock are stored together. The data is written into the
+* stream in this order:
+*
+* 0 1 4 5
+* 2 3 6 7
+* 8 9 12 13
+* 10 11 14 15
+*/
+extern const int _jxr_hp_scan_map[16];
+
+extern uint8_t _jxr_read_lwf_test_flag();
+extern void _jxr_4x4IPCT(int*coeff);
+extern void _jxr_2x2IPCT(int*coeff);
+extern void _jxr_2ptT(int*a, int*b);
+extern void _jxr_2ptFwdT(int*a, int*b);
+extern void _jxr_InvPermute2pt(int*a, int*b);
+extern void _jxr_4x4PCT(int*coeff);
+extern void _jxr_2x2PCT(int*coeff);
+
+
+extern int _jxr_floor_div2(int x);
+extern int _jxr_ceil_div2(int x);
+
+# define SWAP(x,y) do { int tmp = (x); (x) = (y); (y) = tmp; } while(0)
+
+
+/* ***
+* Container types
+* ***/
+
+struct ifd_table{
+ uint16_t tag;
+ uint16_t type;
+ uint32_t cnt;
+
+ union{
+ uint8_t v_byte[4];
+ uint16_t v_short[2];
+ uint32_t v_long;
+ int8_t v_sbyte[4];
+ int16_t v_sshort[2];
+ int32_t v_slong;
+ float v_float;
+
+ uint8_t *p_byte;
+ uint16_t *p_short;
+ uint32_t *p_long;
+ uint64_t *p_rational;
+ int8_t *p_sbyte;
+ int16_t *p_sshort;
+ int32_t *p_slong;
+ int64_t *p_srational;
+ float *p_float;
+ double *p_double;
+ }value_;
+};
+
+/*
+* This is the container itself. It contains pointers to the tables.
+*/
+struct jxr_container{
+ /* Number of images in the container. */
+ int image_count;
+
+ /* IFDs for all the images. */
+ unsigned*table_cnt;
+ struct ifd_table**table;
+
+ /* Members for managing output. */
+
+ FILE*fd; /* File to write to. */
+ uint32_t file_mark;
+ uint32_t next_ifd_mark;
+ uint32_t image_count_mark;
+ uint32_t image_offset_mark;
+ uint32_t alpha_count_mark;
+ uint32_t alpha_offset_mark;
+ uint32_t alpha_begin_mark; /* Required to calculate bytes used up by the alpha plane */
+
+ uint8_t image_band, alpha_band; /* for bands present */
+ uint32_t wid, hei;
+ unsigned char pixel_format[16];
+
+ uint8_t separate_alpha_image_plane;
+};
+
+extern int jxr_read_image_pixelformat(jxr_container_t c);
+
+extern unsigned int isEqualGUID(unsigned char guid1[16], unsigned char guid2[16]);
+
+#if defined(DETAILED_DEBUG)
+# define DEBUG(...) fprintf(stdout, __VA_ARGS__)
+#else
+# define DEBUG(...) do { } while(0)
+#endif
+
+extern const char*_jxr_vld_index_name(int vlc);
+
+/*
+* $Log: jxr_priv.h,v $
+* Revision 1.67 2009/05/29 12:00:00 microsoft
+* Reference Software v1.6 updates.
+*
+* Revision 1.66 2009/04/13 12:00:00 microsoft
+* Reference Software v1.5 updates.
+*
+* Revision 1.65 2008-05-13 13:47:11 thor
+* Some experiments with a smarter selection for the quantization size,
+* does not yet compile.
+*
+* Revision 1.64 2008-05-09 19:57:48 thor
+* Reformatted for unix LF.
+*
+* Revision 1.63 2008-04-15 14:28:12 thor
+* Start of the repository for the jpegxr reference software.
+*
+* Revision 1.62 2008/03/20 22:38:53 steve
+* Use MB HPQP instead of first HPQP in decode.
+*
+* Revision 1.61 2008/03/14 00:54:08 steve
+* Add second prefilter for YUV422 and YUV420 encode.
+*
+* Revision 1.60 2008/03/13 21:23:27 steve
+* Add pipeline step for YUV420.
+*
+* Revision 1.59 2008/03/13 17:49:31 steve
+* Fix problem with YUV422 CBP prediction for UV planes
+*
+* Add support for YUV420 encoding.
+*
+* Revision 1.58 2008/03/11 22:12:48 steve
+* Encode YUV422 through DC.
+*
+* Revision 1.57 2008/03/06 02:05:48 steve
+* Distributed quantization
+*
+* Revision 1.56 2008/03/05 00:31:17 steve
+* Handle UNIFORM/IMAGEPLANE_UNIFORM compression.
+*
+* Revision 1.55 2008/03/02 18:35:27 steve
+* Add support for BD16
+*
+* Revision 1.54 2008/03/01 02:46:08 steve
+* Add support for JXR container.
+*
+* Revision 1.53 2008/02/28 18:50:31 steve
+* Portability fixes.
+*
+* Revision 1.52 2008/02/26 23:44:25 steve
+* Handle the special case of compiling via MS C.
+*
+* Revision 1.51 2008/02/01 22:49:52 steve
+* Handle compress of YUV444 color DCONLY
+*
+* Revision 1.50 2008/01/08 01:06:20 steve
+* Add first pass overlap filtering.
+*
+* Revision 1.49 2008/01/06 01:29:28 steve
+* Add support for TRIM_FLEXBITS in compression.
+*
+* Revision 1.48 2008/01/04 17:07:35 steve
+* API interface for setting QP values.
+*
+* Revision 1.47 2008/01/01 01:07:26 steve
+* Add missing HP prediction.
+*
+* Revision 1.46 2007/12/30 00:16:00 steve
+* Add encoding of HP values.
+*
+* Revision 1.45 2007/12/14 17:10:39 steve
+* HP CBP Prediction
+*
+* Revision 1.44 2007/12/13 18:01:09 steve
+* Stubs for HP encoding.
+*
+* Revision 1.43 2007/12/07 01:20:34 steve
+* Fix adapt not adapting on line ends.
+*
+* Revision 1.42 2007/12/06 23:12:41 steve
+* Stubs for LP encode operations.
+*
+* Revision 1.41 2007/12/04 22:06:10 steve
+* Infrastructure for encoding LP.
+*
+* Revision 1.40 2007/11/30 01:50:58 steve
+* Compression of DCONLY GRAY.
+*
+* Revision 1.39 2007/11/26 01:47:15 steve
+* Add copyright notices per MS request.
+*
+* Revision 1.38 2007/11/21 23:26:14 steve
+* make all strip buffers store MB data.
+*/
+#endif
diff --git a/jpegxr/my_getopt-1.5/LICENSE b/jpegxr/my_getopt-1.5/LICENSE
new file mode 100644
index 000000000..2224aba0c
--- /dev/null
+++ b/jpegxr/my_getopt-1.5/LICENSE
@@ -0,0 +1,22 @@
+my_getopt - a command-line argument parser
+Copyright 1997-2001, Benjamin Sittler
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use, copy,
+modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/jpegxr/my_getopt-1.5/getopt.h b/jpegxr/my_getopt-1.5/getopt.h
new file mode 100644
index 000000000..06b8c9d17
--- /dev/null
+++ b/jpegxr/my_getopt-1.5/getopt.h
@@ -0,0 +1,56 @@
+/*
+* getopt.h - cpp wrapper for my_getopt to make it look like getopt.
+* Copyright 1997, 2000, 2001, 2002, Benjamin Sittler
+*
+* Permission is hereby granted, free of charge, to any person
+* obtaining a copy of this software and associated documentation
+* files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy,
+* modify, merge, publish, distribute, sublicense, and/or sell copies
+* of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef MY_WRAPPER_GETOPT_H_INCLUDED
+#define MY_WRAPPER_GETOPT_H_INCLUDED
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#include "my_getopt.h"
+
+#undef getopt
+#define getopt my_getopt
+#undef getopt_long
+#define getopt_long my_getopt_long
+#undef getopt_long_only
+#define getopt_long_only my_getopt_long_only
+#undef _getopt_internal
+#define _getopt_internal _my_getopt_internal
+#undef opterr
+#define opterr my_opterr
+#undef optind
+#define optind my_optind
+#undef optopt
+#define optopt my_optopt
+#undef optarg
+#define optarg my_optarg
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MY_WRAPPER_GETOPT_H_INCLUDED */
diff --git a/jpegxr/my_getopt-1.5/my_getopt.c b/jpegxr/my_getopt-1.5/my_getopt.c
new file mode 100644
index 000000000..edc4a3465
--- /dev/null
+++ b/jpegxr/my_getopt-1.5/my_getopt.c
@@ -0,0 +1,281 @@
+/*
+* my_getopt.c - my re-implementation of getopt.
+* Copyright 1997, 2000, 2001, 2002, 2006, Benjamin Sittler
+*
+* Permission is hereby granted, free of charge, to any person
+* obtaining a copy of this software and associated documentation
+* files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy,
+* modify, merge, publish, distribute, sublicense, and/or sell copies
+* of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*/
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "my_getopt.h"
+
+int my_optind=1, my_opterr=1, my_optopt=0;
+char *my_optarg=0;
+
+/* reset argument parser to start-up values */
+int my_getopt_reset(void)
+{
+ my_optind = 1;
+ my_opterr = 1;
+ my_optopt = 0;
+ my_optarg = 0;
+ return 0;
+}
+
+/* this is the plain old UNIX getopt, with GNU-style extensions. */
+/* if you're porting some piece of UNIX software, this is all you need. */
+/* this supports GNU-style permution and optional arguments */
+
+int my_getopt(int argc, char * argv[], const char *opts)
+{
+ static int charind=0;
+ const char *s;
+ char mode, colon_mode;
+ int off = 0, opt = -1;
+
+ if(getenv("POSIXLY_CORRECT")) colon_mode = mode = '+';
+ else {
+ if((colon_mode = *opts) == ':') off ++;
+ if(((mode = opts[off]) == '+') || (mode == '-')) {
+ off++;
+ if((colon_mode != ':') && ((colon_mode = opts[off]) == ':'))
+ off ++;
+ }
+ }
+ my_optarg = 0;
+ if(charind) {
+ my_optopt = argv[my_optind][charind];
+ for(s=opts+off; *s; s++) if(my_optopt == *s) {
+ charind++;
+ if((*(++s) == ':') || ((my_optopt == 'W') && (*s == ';'))) {
+ if(argv[my_optind][charind]) {
+ my_optarg = &(argv[my_optind++][charind]);
+ charind = 0;
+ } else if(*(++s) != ':') {
+ charind = 0;
+ if(++my_optind >= argc) {
+ if(my_opterr) fprintf(stderr,
+ "%s: option requires an argument -- %c\n",
+ argv[0], my_optopt);
+ opt = (colon_mode == ':') ? ':' : '?';
+ goto my_getopt_ok;
+ }
+ my_optarg = argv[my_optind++];
+ }
+ }
+ opt = my_optopt;
+ goto my_getopt_ok;
+ }
+ if(my_opterr) fprintf(stderr,
+ "%s: illegal option -- %c\n",
+ argv[0], my_optopt);
+ opt = '?';
+ if(argv[my_optind][++charind] == '\0') {
+ my_optind++;
+ charind = 0;
+ }
+my_getopt_ok:
+ if(charind && ! argv[my_optind][charind]) {
+ my_optind++;
+ charind = 0;
+ }
+ } else if((my_optind >= argc) ||
+ ((argv[my_optind][0] == '-') &&
+ (argv[my_optind][1] == '-') &&
+ (argv[my_optind][2] == '\0'))) {
+ my_optind++;
+ opt = -1;
+ } else if((argv[my_optind][0] != '-') ||
+ (argv[my_optind][1] == '\0')) {
+ char *tmp;
+ int i, j, k;
+
+ if(mode == '+') opt = -1;
+ else if(mode == '-') {
+ my_optarg = argv[my_optind++];
+ charind = 0;
+ opt = 1;
+ } else {
+ for(i=j=my_optind; i<argc; i++) if((argv[i][0] == '-') &&
+ (argv[i][1] != '\0')) {
+ my_optind=i;
+ opt=my_getopt(argc, argv, opts);
+ while(i > j) {
+ tmp=argv[--i];
+ for(k=i; k+1<my_optind; k++) argv[k]=argv[k+1];
+ argv[--my_optind]=tmp;
+ }
+ break;
+ }
+ if(i == argc) opt = -1;
+ }
+ } else {
+ charind++;
+ opt = my_getopt(argc, argv, opts);
+ }
+ if (my_optind > argc) my_optind = argc;
+ return opt;
+}
+
+/* this is the extended getopt_long{,_only}, with some GNU-like
+* extensions. Implements _getopt_internal in case any programs
+* expecting GNU libc getopt call it.
+*/
+
+int _my_getopt_internal(int argc, char * argv[], const char *shortopts,
+ const struct option *longopts, int *longind,
+ int long_only)
+{
+ char mode, colon_mode = *shortopts;
+ int shortoff = 0, opt = -1;
+
+ if(getenv("POSIXLY_CORRECT")) colon_mode = mode = '+';
+ else {
+ if((colon_mode = *shortopts) == ':') shortoff ++;
+ if(((mode = shortopts[shortoff]) == '+') || (mode == '-')) {
+ shortoff++;
+ if((colon_mode != ':') && ((colon_mode = shortopts[shortoff]) == ':'))
+ shortoff ++;
+ }
+ }
+ my_optarg = 0;
+ if((my_optind >= argc) ||
+ ((argv[my_optind][0] == '-') &&
+ (argv[my_optind][1] == '-') &&
+ (argv[my_optind][2] == '\0'))) {
+ my_optind++;
+ opt = -1;
+ } else if((argv[my_optind][0] != '-') ||
+ (argv[my_optind][1] == '\0')) {
+ char *tmp;
+ int i, j, k;
+
+ opt = -1;
+ if(mode == '+') return -1;
+ else if(mode == '-') {
+ my_optarg = argv[my_optind++];
+ return 1;
+ }
+ for(i=j=my_optind; i<argc; i++) if((argv[i][0] == '-') &&
+ (argv[i][1] != '\0')) {
+ my_optind=i;
+ opt=_my_getopt_internal(argc, argv, shortopts,
+ longopts, longind,
+ long_only);
+ while(i > j) {
+ tmp=argv[--i];
+ for(k=i; k+1<my_optind; k++)
+ argv[k]=argv[k+1];
+ argv[--my_optind]=tmp;
+ }
+ break;
+ }
+ } else if((!long_only) && (argv[my_optind][1] != '-'))
+ opt = my_getopt(argc, argv, shortopts);
+ else {
+ int charind, offset;
+ int found = 0, ind, hits = 0;
+
+ if(((my_optopt = argv[my_optind][1]) != '-') && ! argv[my_optind][2]) {
+ int c;
+
+ ind = shortoff;
+ while((c = shortopts[ind++])) {
+ if(((shortopts[ind] == ':') ||
+ ((c == 'W') && (shortopts[ind] == ';'))) &&
+ (shortopts[++ind] == ':'))
+ ind ++;
+ if(my_optopt == c) return my_getopt(argc, argv, shortopts);
+ }
+ }
+ offset = 2 - (argv[my_optind][1] != '-');
+ for(charind = offset;
+ (argv[my_optind][charind] != '\0') &&
+ (argv[my_optind][charind] != '=');
+ charind++);
+ for(ind = 0; longopts[ind].name && !hits; ind++)
+ if((strlen(longopts[ind].name) == (size_t) (charind - offset)) &&
+ (strncmp(longopts[ind].name,
+ argv[my_optind] + offset, charind - offset) == 0))
+ found = ind, hits++;
+ if(!hits) for(ind = 0; longopts[ind].name; ind++)
+ if(strncmp(longopts[ind].name,
+ argv[my_optind] + offset, charind - offset) == 0)
+ found = ind, hits++;
+ if(hits == 1) {
+ opt = 0;
+
+ if(argv[my_optind][charind] == '=') {
+ if(longopts[found].has_arg == 0) {
+ opt = '?';
+ if(my_opterr) fprintf(stderr,
+ "%s: option `--%s' doesn't allow an argument\n",
+ argv[0], longopts[found].name);
+ } else {
+ my_optarg = argv[my_optind] + ++charind;
+ charind = 0;
+ }
+ } else if(longopts[found].has_arg == 1) {
+ if(++my_optind >= argc) {
+ opt = (colon_mode == ':') ? ':' : '?';
+ if(my_opterr) fprintf(stderr,
+ "%s: option `--%s' requires an argument\n",
+ argv[0], longopts[found].name);
+ } else my_optarg = argv[my_optind];
+ }
+ if(!opt) {
+ if (longind) *longind = found;
+ if(!longopts[found].flag) opt = longopts[found].val;
+ else *(longopts[found].flag) = longopts[found].val;
+ }
+ my_optind++;
+ } else if(!hits) {
+ if(offset == 1) opt = my_getopt(argc, argv, shortopts);
+ else {
+ opt = '?';
+ if(my_opterr) fprintf(stderr,
+ "%s: unrecognized option `%s'\n",
+ argv[0], argv[my_optind++]);
+ }
+ } else {
+ opt = '?';
+ if(my_opterr) fprintf(stderr,
+ "%s: option `%s' is ambiguous\n",
+ argv[0], argv[my_optind++]);
+ }
+ }
+ if (my_optind > argc) my_optind = argc;
+ return opt;
+}
+
+int my_getopt_long(int argc, char * argv[], const char *shortopts,
+ const struct option *longopts, int *longind)
+{
+ return _my_getopt_internal(argc, argv, shortopts, longopts, longind, 0);
+}
+
+int my_getopt_long_only(int argc, char * argv[], const char *shortopts,
+ const struct option *longopts, int *longind)
+{
+ return _my_getopt_internal(argc, argv, shortopts, longopts, longind, 1);
+}
diff --git a/jpegxr/my_getopt-1.5/my_getopt.h b/jpegxr/my_getopt-1.5/my_getopt.h
new file mode 100644
index 000000000..1d9523d4f
--- /dev/null
+++ b/jpegxr/my_getopt-1.5/my_getopt.h
@@ -0,0 +1,72 @@
+/*
+* my_getopt.h - interface to my re-implementation of getopt.
+* Copyright 1997, 2000, 2001, 2002, 2006, Benjamin Sittler
+*
+* Permission is hereby granted, free of charge, to any person
+* obtaining a copy of this software and associated documentation
+* files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy,
+* modify, merge, publish, distribute, sublicense, and/or sell copies
+* of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef MY_GETOPT_H_INCLUDED
+#define MY_GETOPT_H_INCLUDED
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+ /* reset argument parser to start-up values */
+ extern int my_getopt_reset(void);
+
+ /* UNIX-style short-argument parser */
+ extern int my_getopt(int argc, char * argv[], const char *opts);
+
+ extern int my_optind, my_opterr, my_optopt;
+ extern char *my_optarg;
+
+ struct option{
+ const char *name;
+ int has_arg;
+ int *flag;
+ int val;
+ };
+
+ /* human-readable values for has_arg */
+#undef no_argument
+#define no_argument 0
+#undef required_argument
+#define required_argument 1
+#undef optional_argument
+#define optional_argument 2
+
+ /* GNU-style long-argument parsers */
+ extern int my_getopt_long(int argc, char * argv[], const char *shortopts,
+ const struct option *longopts, int *longind);
+
+ extern int my_getopt_long_only(int argc, char * argv[], const char *shortopts,
+ const struct option *longopts, int *longind);
+
+ extern int _my_getopt_internal(int argc, char * argv[], const char *shortopts,
+ const struct option *longopts, int *longind,
+ int long_only);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MY_GETOPT_H_INCLUDED */
diff --git a/jpegxr/qp.tab.c b/jpegxr/qp.tab.c
new file mode 100644
index 000000000..e87208635
--- /dev/null
+++ b/jpegxr/qp.tab.c
@@ -0,0 +1,1909 @@
+
+/* A Bison parser, made by GNU Bison 2.4.1. */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "2.4.1"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 0
+
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
+/* Using locations. */
+#define YYLSP_NEEDED 0
+
+/* Substitute the variable and function names. */
+#define yyparse qp_parse
+#define yylex qp_lex
+#define yyerror qp_error
+#define yylval qp_lval
+#define yychar qp_char
+#define yydebug qp_debug
+#define yynerrs qp_nerrs
+
+
+/* Copy the first part of user declarations. */
+
+/* Line 189 of yacc.c */
+#line 2 "qp_parse.y"
+
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008.
+**********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: qp_parse.y,v 1.8 2008/03/20 18:10:29 steve Exp $")
+#else
+#ident "$Id: qp_parse.y,v 1.8 2008/03/20 18:10:29 steve Exp $"
+#endif
+
+# include "jpegxr.h"
+# include <stdlib.h>
+# include <assert.h>
+# define YYINCLUDED_STDLIB_H
+
+ extern int qp_lex(void);
+ static void yyerror(const char*txt);
+
+ static int errors = 0;
+
+ /* Parse state variables. */
+
+ /* The image we are getting QP values for */
+ static jxr_image_t cur_image;
+ /* Some characteristics of that image. */
+ static unsigned tile_columns;
+ static unsigned tile_rows;
+
+ /* The array of all the tiles to be calculated. */
+ static struct jxr_tile_qp* tile_qp = 0;
+
+ /* Tile currently in progress. */
+ static unsigned cur_tilex = 0;
+ static unsigned cur_tiley = 0;
+ static struct jxr_tile_qp*cur_tile = 0;
+
+ static unsigned mb_in_tile = 0;
+
+ static unsigned cur_channel = 0;
+
+
+
+/* Line 189 of yacc.c */
+#line 162 "qp.tab.c"
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ K_DC = 258,
+ K_CHANNEL = 259,
+ K_HP = 260,
+ K_INDEPENDENT = 261,
+ K_LP = 262,
+ K_SEPARATE = 263,
+ K_TILE = 264,
+ K_UNIFORM = 265,
+ NUMBER = 266
+ };
+#endif
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+
+/* Line 214 of yacc.c */
+#line 82 "qp_parse.y"
+
+ unsigned number;
+
+ struct {
+ unsigned char*data;
+ unsigned count;
+ } map_list;
+
+ struct sixteen_nums {
+ unsigned char num;
+ unsigned char qp[16];
+ } qp_set;
+
+
+
+/* Line 214 of yacc.c */
+#line 225 "qp.tab.c"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+/* Copy the second part of user declarations. */
+
+
+/* Line 264 of yacc.c */
+#line 237 "qp.tab.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int yyi)
+#else
+static int
+YYID (yyi)
+ int yyi;
+#endif
+{
+ return yyi;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined _STDLIB_H \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss_alloc;
+ YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 6
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 51
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 19
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 14
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 26
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 56
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 266
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 12, 14, 2, 2, 13, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 17, 2, 18, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 15, 2, 16, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const yytype_uint8 yyprhs[] =
+{
+ 0, 0, 3, 5, 8, 10, 11, 23, 25, 27,
+ 29, 32, 34, 35, 42, 47, 52, 55, 57, 62,
+ 67, 72, 76, 78, 80, 81, 84
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int8 yyrhs[] =
+{
+ 20, 0, -1, 21, -1, 21, 22, -1, 22, -1,
+ -1, 9, 12, 11, 13, 11, 14, 23, 15, 24,
+ 25, 16, -1, 10, -1, 8, -1, 6, -1, 25,
+ 26, -1, 26, -1, -1, 4, 11, 27, 15, 28,
+ 16, -1, 7, 17, 32, 18, -1, 5, 17, 32,
+ 18, -1, 28, 29, -1, 29, -1, 3, 15, 11,
+ 16, -1, 7, 15, 30, 16, -1, 5, 15, 30,
+ 16, -1, 30, 31, 11, -1, 11, -1, 13, -1,
+ -1, 32, 11, -1, 11, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
+{
+ 0, 107, 107, 110, 111, 118, 117, 169, 170, 171,
+ 175, 176, 181, 180, 188, 197, 208, 209, 213, 216,
+ 223, 233, 245, 251, 251, 254, 264
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "K_DC", "K_CHANNEL", "K_HP",
+ "K_INDEPENDENT", "K_LP", "K_SEPARATE", "K_TILE", "K_UNIFORM", "NUMBER",
+ "'('", "','", "')'", "'{'", "'}'", "'['", "']'", "$accept", "start",
+ "tile_list", "tile", "$@1", "tile_comp_mode", "tile_body", "tile_item",
+ "$@2", "channel_body", "channel_item", "lphp_qp_list", "optional_comma",
+ "map_list", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 40, 44, 41, 123, 125, 91, 93
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
+{
+ 0, 19, 20, 21, 21, 23, 22, 24, 24, 24,
+ 25, 25, 27, 26, 26, 26, 28, 28, 29, 29,
+ 29, 30, 30, 31, 31, 32, 32
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 1, 2, 1, 0, 11, 1, 1, 1,
+ 2, 1, 0, 6, 4, 4, 2, 1, 4, 4,
+ 4, 3, 1, 1, 0, 2, 1
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
+{
+ 0, 0, 0, 2, 4, 0, 1, 3, 0, 0,
+ 0, 5, 0, 0, 9, 8, 7, 0, 0, 0,
+ 0, 0, 11, 12, 0, 0, 6, 10, 0, 26,
+ 0, 0, 0, 25, 15, 14, 0, 0, 0, 0,
+ 17, 0, 0, 0, 13, 16, 0, 22, 24, 24,
+ 18, 23, 20, 0, 19, 21
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int8 yydefgoto[] =
+{
+ -1, 2, 3, 4, 12, 17, 21, 22, 28, 39,
+ 40, 48, 53, 30
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -12
+static const yytype_int8 yypact[] =
+{
+ 0, -11, 11, 0, -12, 17, -12, -12, 9, 19,
+ 18, -12, 21, 10, -12, -12, -12, 20, 22, 14,
+ 23, 1, -12, -12, 24, 24, -12, -12, 26, -12,
+ -8, -4, 16, -12, -12, -12, 27, 28, 29, -3,
+ -12, 34, 35, 35, -12, -12, 31, -12, -1, 13,
+ -12, -12, -12, 37, -12, -12
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int8 yypgoto[] =
+{
+ -12, -12, -12, 36, -12, -12, -12, 30, -12, -12,
+ -5, -6, -12, 25
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -1
+static const yytype_uint8 yytable[] =
+{
+ 36, 5, 37, 33, 38, 18, 19, 33, 20, 1,
+ 34, 6, 51, 44, 35, 52, 14, 26, 15, 36,
+ 16, 37, 9, 38, 18, 19, 51, 20, 8, 54,
+ 10, 24, 11, 23, 45, 29, 13, 49, 0, 7,
+ 25, 32, 41, 42, 43, 46, 47, 50, 55, 0,
+ 31, 27
+};
+
+static const yytype_int8 yycheck[] =
+{
+ 3, 12, 5, 11, 7, 4, 5, 11, 7, 9,
+ 18, 0, 13, 16, 18, 16, 6, 16, 8, 3,
+ 10, 5, 13, 7, 4, 5, 13, 7, 11, 16,
+ 11, 17, 14, 11, 39, 11, 15, 43, -1, 3,
+ 17, 15, 15, 15, 15, 11, 11, 16, 11, -1,
+ 25, 21
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint8 yystos[] =
+{
+ 0, 9, 20, 21, 22, 12, 0, 22, 11, 13,
+ 11, 14, 23, 15, 6, 8, 10, 24, 4, 5,
+ 7, 25, 26, 11, 17, 17, 16, 26, 27, 11,
+ 32, 32, 15, 11, 18, 18, 3, 5, 7, 28,
+ 29, 15, 15, 15, 16, 29, 11, 11, 30, 30,
+ 16, 13, 16, 31, 16, 11
+};
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+
+#define YYFAIL goto yyerrlab
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (YYID (0))
+
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (!yyvaluep)
+ return;
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+#else
+static void
+yy_stack_print (yybottom, yytop)
+ yytype_int16 *yybottom;
+ yytype_int16 *yytop;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule)
+ YYSTYPE *yyvsp;
+ int yyrule;
+#endif
+{
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ );
+ YYFPRINTF (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyvsp, Rule); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+ const char *yystr;
+#endif
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+#endif
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+ int yyn = yypact[yystate];
+
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
+ else
+ {
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ int yyx;
+
+# if 0
+ /* This is so xgettext sees the translatable formats that are
+ constructed on the fly. */
+ YY_("syntax error, unexpected %s");
+ YY_("syntax error, unexpected %s, expecting %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+ char *yyfmt;
+ char const *yyf;
+ static char const yyunexpected[] = "syntax error, unexpected %s";
+ static char const yyexpecting[] = ", expecting %s";
+ static char const yyor[] = " or %s";
+ char yyformat[sizeof yyunexpected
+ + sizeof yyexpecting - 1
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+ * (sizeof yyor - 1))];
+ char const *yyprefix = yyexpecting;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
+
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
+
+ if (yyresult)
+ {
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ char *yyp = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
+ }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep)
+ const char *yymsg;
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
+{
+ YYUSE (yyvaluep);
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+}
+
+/* Prevent warnings from -Wmissing-prototypes. */
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+/* The lookahead symbol. */
+int yychar;
+
+/* The semantic value of the lookahead symbol. */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far. */
+int yynerrs;
+
+
+
+/*-------------------------.
+| yyparse or yypush_parse. |
+`-------------------------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+
+
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+
+ /* The stacks and their tools:
+ `yyss': related to states.
+ `yyvs': related to semantic values.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
+
+ YYSIZE_T yystacksize;
+
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken;
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ yytoken = 0;
+ yyss = yyssa;
+ yyvs = yyvsa;
+ yystacksize = YYINITDEPTH;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+ yyssp = yyss;
+ yyvsp = yyvs;
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ lookahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to lookahead token. */
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ *++yyvsp = yylval;
+
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 5:
+
+/* Line 1455 of yacc.c */
+#line 118 "qp_parse.y"
+ { cur_tilex = (yyvsp[(3) - (6)].number),
+ cur_tiley = (yyvsp[(5) - (6)].number);
+ assert(cur_tilex < tile_columns);
+ assert(cur_tiley < tile_rows);
+ cur_tile = tile_qp + cur_tiley*tile_columns + cur_tilex;
+ mb_in_tile = jxr_get_TILE_WIDTH(cur_image, cur_tilex) * jxr_get_TILE_HEIGHT(cur_image, cur_tiley);
+ ;}
+ break;
+
+ case 6:
+
+/* Line 1455 of yacc.c */
+#line 126 "qp_parse.y"
+ { /* Check the sanity of the calculated tile. */
+ int idx;
+ switch (cur_tile->component_mode) {
+ case JXR_CM_UNIFORM:
+ break;
+ case JXR_CM_SEPARATE:
+ if (cur_tile->channel[0].num_lp != cur_tile->channel[1].num_lp) {
+ fprintf(stderr, "channel-0 and channel-1 LP counts don't match\n");
+ errors += 1;
+ }
+ if (cur_tile->channel[0].num_hp != cur_tile->channel[1].num_hp) {
+ fprintf(stderr, "channel-0 and channel-1 HP counts don't match\n");
+ errors += 1;
+ }
+ if (jxr_get_IMAGE_CHANNELS(cur_image) == 1) {
+ fprintf(stderr, "Gray (1-channel) tiles must be channel mode UNIFORM\n");
+ errors += 1;
+ }
+ break;
+ case JXR_CM_INDEPENDENT:
+ for (idx = 1 ; idx < jxr_get_IMAGE_CHANNELS(cur_image) ; idx += 1) {
+ if (cur_tile->channel[0].num_lp != cur_tile->channel[idx].num_lp) {
+ fprintf(stderr, "channel-0 and channel-%d LP counts don't match\n", idx);
+ errors += 1;
+ }
+ if (cur_tile->channel[0].num_hp != cur_tile->channel[idx].num_hp) {
+ fprintf(stderr, "channel-0 and channel-%d HP counts don't match\n", idx);
+ errors += 1;
+ }
+ }
+ if (jxr_get_IMAGE_CHANNELS(cur_image) == 1) {
+ fprintf(stderr, "Gray (1-channel) tiles must be channel mode UNIFORM\n");
+ errors += 1;
+ }
+ break;
+ case JXR_CM_Reserved:
+ assert(0);
+ break;
+ }
+ ;}
+ break;
+
+ case 7:
+
+/* Line 1455 of yacc.c */
+#line 169 "qp_parse.y"
+ { cur_tile->component_mode = JXR_CM_UNIFORM; ;}
+ break;
+
+ case 8:
+
+/* Line 1455 of yacc.c */
+#line 170 "qp_parse.y"
+ { cur_tile->component_mode = JXR_CM_SEPARATE; ;}
+ break;
+
+ case 9:
+
+/* Line 1455 of yacc.c */
+#line 171 "qp_parse.y"
+ { cur_tile->component_mode = JXR_CM_INDEPENDENT; ;}
+ break;
+
+ case 12:
+
+/* Line 1455 of yacc.c */
+#line 181 "qp_parse.y"
+ { cur_channel = (yyvsp[(2) - (2)].number);
+ assert(cur_channel < 16);
+ cur_tile->channel[cur_channel].num_lp = 0;
+ cur_tile->channel[cur_channel].num_hp = 0;
+ ;}
+ break;
+
+ case 14:
+
+/* Line 1455 of yacc.c */
+#line 189 "qp_parse.y"
+ { cur_tile->lp_map = (yyvsp[(3) - (4)].map_list).data;
+ if ((yyvsp[(3) - (4)].map_list).count != mb_in_tile) {
+ errors += 1;
+ fprintf(stderr, "parse qp: In tile %u,%u, expected %u lp blocks, got %u.\n",
+ cur_tilex, cur_tiley, mb_in_tile, (yyvsp[(3) - (4)].map_list).count);
+ }
+ ;}
+ break;
+
+ case 15:
+
+/* Line 1455 of yacc.c */
+#line 198 "qp_parse.y"
+ { cur_tile->hp_map = (yyvsp[(3) - (4)].map_list).data;
+ if ((yyvsp[(3) - (4)].map_list).count != mb_in_tile) {
+ errors += 1;
+ fprintf(stderr, "parse qp: In tile %u,%u, expected %u lp blocks, got %u.\n",
+ cur_tilex, cur_tiley, mb_in_tile, (yyvsp[(3) - (4)].map_list).count);
+ }
+ ;}
+ break;
+
+ case 18:
+
+/* Line 1455 of yacc.c */
+#line 214 "qp_parse.y"
+ { cur_tile->channel[cur_channel].dc_qp = (yyvsp[(3) - (4)].number); ;}
+ break;
+
+ case 19:
+
+/* Line 1455 of yacc.c */
+#line 217 "qp_parse.y"
+ { cur_tile->channel[cur_channel].num_lp = (yyvsp[(3) - (4)].qp_set).num;
+ int idx;
+ for (idx = 0 ; idx < (yyvsp[(3) - (4)].qp_set).num ; idx += 1)
+ cur_tile->channel[cur_channel].lp_qp[idx] = (yyvsp[(3) - (4)].qp_set).qp[idx];
+ ;}
+ break;
+
+ case 20:
+
+/* Line 1455 of yacc.c */
+#line 224 "qp_parse.y"
+ { cur_tile->channel[cur_channel].num_hp = (yyvsp[(3) - (4)].qp_set).num;
+ int idx;
+ for (idx = 0 ; idx < (yyvsp[(3) - (4)].qp_set).num ; idx += 1)
+ cur_tile->channel[cur_channel].hp_qp[idx] = (yyvsp[(3) - (4)].qp_set).qp[idx];
+ ;}
+ break;
+
+ case 21:
+
+/* Line 1455 of yacc.c */
+#line 234 "qp_parse.y"
+ { unsigned cnt = (yyvsp[(1) - (3)].qp_set).num;
+ if (cnt >= 16) {
+ fprintf(stderr, "Too many (>16) QP values in QP list.\n");
+ errors += 1;
+ } else {
+ assert(cnt < 16);
+ (yyvsp[(1) - (3)].qp_set).qp[cnt] = (yyvsp[(3) - (3)].number);
+ (yyvsp[(1) - (3)].qp_set).num += 1;
+ }
+ (yyval.qp_set) = (yyvsp[(1) - (3)].qp_set);
+ ;}
+ break;
+
+ case 22:
+
+/* Line 1455 of yacc.c */
+#line 246 "qp_parse.y"
+ { (yyval.qp_set).num = 1;
+ (yyval.qp_set).qp[0] = (yyvsp[(1) - (1)].number);
+ ;}
+ break;
+
+ case 25:
+
+/* Line 1455 of yacc.c */
+#line 255 "qp_parse.y"
+ { if ((yyvsp[(1) - (2)].map_list).count >= mb_in_tile) {
+ fprintf(stderr, "Too many map items for tile!\n");
+ errors += 1;
+ } else {
+ (yyvsp[(1) - (2)].map_list).data[(yyvsp[(1) - (2)].map_list).count++] = (yyvsp[(2) - (2)].number);
+ }
+ (yyval.map_list) = (yyvsp[(1) - (2)].map_list);
+ ;}
+ break;
+
+ case 26:
+
+/* Line 1455 of yacc.c */
+#line 265 "qp_parse.y"
+ { assert(mb_in_tile >= 1);
+ (yyval.map_list).data = (unsigned char*)calloc(mb_in_tile, 1);
+ (yyval.map_list).count = 1;
+ (yyval.map_list).data[0] = (yyvsp[(1) - (1)].number);
+ ;}
+ break;
+
+
+
+/* Line 1455 of yacc.c */
+#line 1660 "qp.tab.c"
+ default: break;
+ }
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (YY_("syntax error"));
+#else
+ {
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ }
+ }
+
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (yymsg);
+ }
+ else
+ {
+ yyerror (YY_("syntax error"));
+ if (yysize != 0)
+ goto yyexhaustedlab;
+ }
+ }
+#endif
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ *++yyvsp = yylval;
+
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#if !defined(yyoverflow) || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEMPTY)
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval);
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
+}
+
+
+
+/* Line 1675 of yacc.c */
+#line 272 "qp_parse.y"
+
+
+extern void qp_restart(FILE*fd);
+
+int qp_parse_file(FILE*fd, jxr_image_t image)
+{
+ cur_image = image;
+ tile_columns = jxr_get_TILE_COLUMNS(image);
+ tile_rows = jxr_get_TILE_ROWS(image);
+
+ tile_qp = (struct jxr_tile_qp *) calloc(tile_columns*tile_rows, sizeof(*tile_qp));
+ assert(tile_qp);
+
+#if defined(DETAILED_DEBUG)
+ printf("qp_parse: tile_columns=%u, tile_rows=%u\n", tile_columns, tile_rows);
+#endif
+
+ qp_restart(fd);
+ yyparse();
+
+#if defined(DETAILED_DEBUG)
+ printf("qp_parse: parse done with %u errors\n", errors);
+#endif
+
+ if (errors) return -1;
+
+ jxr_set_QP_DISTRIBUTED(image, tile_qp);
+ return 0;
+}
+
+
+
+static void yyerror(const char*txt)
+{
+ fprintf(stderr, "parsing QP file: %s\n", txt);
+ errors += 1;
+}
+
diff --git a/jpegxr/qp.tab.h b/jpegxr/qp.tab.h
new file mode 100644
index 000000000..fd17ca14a
--- /dev/null
+++ b/jpegxr/qp.tab.h
@@ -0,0 +1,87 @@
+
+/* A Bison parser, made by GNU Bison 2.4.1. */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ K_DC = 258,
+ K_CHANNEL = 259,
+ K_HP = 260,
+ K_INDEPENDENT = 261,
+ K_LP = 262,
+ K_SEPARATE = 263,
+ K_TILE = 264,
+ K_UNIFORM = 265,
+ NUMBER = 266
+ };
+#endif
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+
+/* Line 1676 of yacc.c */
+#line 82 "qp_parse.y"
+
+ unsigned number;
+
+ struct {
+ unsigned char*data;
+ unsigned count;
+ } map_list;
+
+ struct sixteen_nums {
+ unsigned char num;
+ unsigned char qp[16];
+ } qp_set;
+
+
+
+/* Line 1676 of yacc.c */
+#line 79 "qp.tab.h"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+extern YYSTYPE qp_lval;
+
+
diff --git a/jpegxr/qp_lexor.c b/jpegxr/qp_lexor.c
new file mode 100644
index 000000000..8d9a8af7f
--- /dev/null
+++ b/jpegxr/qp_lexor.c
@@ -0,0 +1,1869 @@
+#line 2 "qp_lexor.c"
+
+#line 4 "qp_lexor.c"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define yy_create_buffer qp__create_buffer
+#define yy_delete_buffer qp__delete_buffer
+#define yy_flex_debug qp__flex_debug
+#define yy_init_buffer qp__init_buffer
+#define yy_flush_buffer qp__flush_buffer
+#define yy_load_buffer_state qp__load_buffer_state
+#define yy_switch_to_buffer qp__switch_to_buffer
+#define yyin qp_in
+#define yyleng qp_leng
+#define yylex qp_lex
+#define yylineno qp_lineno
+#define yyout qp_out
+#define yyrestart qp_restart
+#define yytext qp_text
+#define yywrap qp_wrap
+#define yyalloc qp_alloc
+#define yyrealloc qp_realloc
+#define yyfree qp_free
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif /* defined (__STDC__) */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE qp_restart(qp_in )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int qp_leng;
+
+extern FILE *qp_in, *qp_out;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+ #define YY_LESS_LINENO(n)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up qp_text. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = (yy_hold_char); \
+ YY_RESTORE_YY_MORE_OFFSET \
+ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up qp_text again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr) )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via qp_restart()), so that the user can continue scanning by
+ * just pointing qp_in at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+ : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when qp_text is formed. */
+static char yy_hold_char;
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+int qp_leng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* Flag which is used to allow qp_wrap()'s to do buffer switches
+ * instead of setting up a fresh qp_in. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void qp_restart (FILE *input_file );
+void qp__switch_to_buffer (YY_BUFFER_STATE new_buffer );
+YY_BUFFER_STATE qp__create_buffer (FILE *file,int size );
+void qp__delete_buffer (YY_BUFFER_STATE b );
+void qp__flush_buffer (YY_BUFFER_STATE b );
+void qp_push_buffer_state (YY_BUFFER_STATE new_buffer );
+void qp_pop_buffer_state (void );
+
+static void qp_ensure_buffer_stack (void );
+static void qp__load_buffer_state (void );
+static void qp__init_buffer (YY_BUFFER_STATE b,FILE *file );
+
+#define YY_FLUSH_BUFFER qp__flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE qp__scan_buffer (char *base,yy_size_t size );
+YY_BUFFER_STATE qp__scan_string (yyconst char *yy_str );
+YY_BUFFER_STATE qp__scan_bytes (yyconst char *bytes,int len );
+
+void *qp_alloc (yy_size_t );
+void *qp_realloc (void *,yy_size_t );
+void qp_free (void * );
+
+#define yy_new_buffer qp__create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ qp_ensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ qp__create_buffer(qp_in,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
+ qp_ensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ qp__create_buffer(qp_in,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define qp_wrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+FILE *qp_in = (FILE *) 0, *qp_out = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int qp_lineno;
+
+int qp_lineno = 1;
+
+extern char *qp_text;
+#define yytext_ptr qp_text
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[] );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up qp_text.
+ */
+#define YY_DO_BEFORE_ACTION \
+ (yytext_ptr) = yy_bp; \
+ qp_leng = (size_t) (yy_cp - yy_bp); \
+ (yy_hold_char) = *yy_cp; \
+ *yy_cp = '\0'; \
+ (yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 13
+#define YY_END_OF_BUFFER 14
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static yyconst flex_int16_t yy_accept[55] =
+ { 0,
+ 0, 0, 14, 12, 1, 1, 2, 11, 12, 12,
+ 12, 12, 12, 12, 12, 12, 2, 11, 3, 5,
+ 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 6, 0, 0, 10, 0, 8,
+ 0, 0, 7, 0
+ } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 2, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 1, 1, 4, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 6, 7, 1, 1,
+ 1, 8, 1, 1, 1, 9, 1, 1, 1, 10,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 11, 1, 12, 13,
+
+ 14, 15, 1, 16, 17, 1, 1, 18, 19, 20,
+ 21, 22, 1, 23, 24, 25, 26, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst flex_int32_t yy_meta[27] =
+ { 0,
+ 1, 1, 2, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1
+ } ;
+
+static yyconst flex_int16_t yy_base[56] =
+ { 0,
+ 0, 0, 65, 66, 66, 66, 0, 59, 57, 52,
+ 51, 44, 39, 44, 40, 36, 0, 50, 66, 66,
+ 66, 43, 40, 30, 33, 33, 29, 34, 36, 32,
+ 30, 24, 21, 19, 66, 20, 26, 25, 27, 14,
+ 18, 15, 9, 14, 66, 19, 17, 66, 16, 66,
+ 9, 3, 66, 66, 26
+ } ;
+
+static yyconst flex_int16_t yy_def[56] =
+ { 0,
+ 54, 1, 54, 54, 54, 54, 55, 54, 54, 54,
+ 54, 54, 54, 54, 54, 54, 55, 54, 54, 54,
+ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
+ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
+ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
+ 54, 54, 54, 0, 54
+ } ;
+
+static yyconst flex_int16_t yy_nxt[93] =
+ { 0,
+ 4, 5, 6, 7, 8, 4, 9, 10, 11, 4,
+ 4, 12, 4, 4, 4, 4, 13, 4, 4, 4,
+ 4, 4, 4, 14, 15, 16, 17, 53, 52, 51,
+ 50, 49, 48, 47, 46, 45, 44, 43, 42, 41,
+ 40, 39, 38, 37, 36, 35, 34, 33, 32, 31,
+ 30, 29, 28, 27, 18, 26, 25, 24, 23, 22,
+ 21, 20, 19, 18, 54, 3, 54, 54, 54, 54,
+ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
+ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
+ 54, 54
+
+ } ;
+
+static yyconst flex_int16_t yy_chk[93] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 55, 52, 51, 49,
+ 47, 46, 44, 43, 42, 41, 40, 39, 38, 37,
+ 36, 34, 33, 32, 31, 30, 29, 28, 27, 26,
+ 25, 24, 23, 22, 18, 16, 15, 14, 13, 12,
+ 11, 10, 9, 8, 3, 54, 54, 54, 54, 54,
+ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
+ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
+ 54, 54
+
+ } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+extern int qp__flex_debug;
+int qp__flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *qp_text;
+#line 1 "qp_lexor.lex"
+#line 3 "qp_lexor.lex"
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008.
+**********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: qp_lexor.lex,v 1.6 2008/03/14 16:08:04 steve Exp $")
+#else
+#ident "$Id: qp_lexor.lex,v 1.6 2008/03/14 16:08:04 steve Exp $"
+#endif
+
+# include "qp.tab.h"
+# include "jxr_priv.h"
+
+/* Windows VidualStudio does not have a <unistd.h> header file, */
+/* so we want the nounistd option to prevent it. However, this */
+/* option doesn't seem to work properly, so we instead rely on */
+/* "sed" to remove the include from the */
+/* generated code. */
+/* %option nounistd */
+#line 575 "qp_lexor.c"
+
+#define INITIAL 0
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Accessor methods to globals.
+ These are made visible to non-reentrant scanners for convenience. */
+
+int qp_lex_destroy (void );
+
+int qp_get_debug (void );
+
+void qp_set_debug (int debug_flag );
+
+YY_EXTRA_TYPE qp_get_extra (void );
+
+void qp_set_extra (YY_EXTRA_TYPE user_defined );
+
+FILE *qp_get_in (void );
+
+void qp_set_in (FILE * in_str );
+
+FILE *qp_get_out (void );
+
+void qp_set_out (FILE * out_str );
+
+int qp_get_leng (void );
+
+char *qp_get_text (void );
+
+int qp_get_lineno (void );
+
+void qp_set_lineno (int line_number );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int qp_wrap (void );
+#else
+extern int qp_wrap (void );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( qp_text, qp_leng, 1, qp_out )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+ { \
+ int c = '*'; \
+ size_t n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( qp_in )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( qp_in ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else \
+ { \
+ errno=0; \
+ while ( (result = fread(buf, 1, max_size, qp_in))==0 && ferror(qp_in)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(qp_in); \
+ } \
+ }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int qp_lex (void);
+
+#define YY_DECL int qp_lex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after qp_text and qp_leng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+
+#line 67 "qp_lexor.lex"
+
+
+
+#line 764 "qp_lexor.c"
+
+ if ( !(yy_init) )
+ {
+ (yy_init) = 1;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! (yy_start) )
+ (yy_start) = 1; /* first start state */
+
+ if ( ! qp_in )
+ qp_in = stdin;
+
+ if ( ! qp_out )
+ qp_out = stdout;
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ qp_ensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ qp__create_buffer(qp_in,YY_BUF_SIZE );
+ }
+
+ qp__load_buffer_state( );
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = (yy_c_buf_p);
+
+ /* Support of qp_text. */
+ *yy_cp = (yy_hold_char);
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = (yy_start);
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 55 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_current_state != 54 );
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+
+ YY_DO_BEFORE_ACTION;
+
+do_action: /* This label is used only to access EOF actions. */
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = (yy_hold_char);
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+ goto yy_find_action;
+
+case 1:
+/* rule 1 can match eol */
+YY_RULE_SETUP
+#line 70 "qp_lexor.lex"
+{ /* Skip white space */; }
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 71 "qp_lexor.lex"
+{ /* Skip comments */; }
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 73 "qp_lexor.lex"
+{ return K_DC; }
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 74 "qp_lexor.lex"
+{ return K_LP; }
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 75 "qp_lexor.lex"
+{ return K_HP; }
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 77 "qp_lexor.lex"
+{ return K_CHANNEL; }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 78 "qp_lexor.lex"
+{ return K_INDEPENDENT; }
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 79 "qp_lexor.lex"
+{ return K_SEPARATE; }
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 80 "qp_lexor.lex"
+{ return K_TILE; }
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 81 "qp_lexor.lex"
+{ return K_UNIFORM; }
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 83 "qp_lexor.lex"
+{ qp_lval.number = strtoul(qp_text, 0, 0); return NUMBER; }
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 85 "qp_lexor.lex"
+{ return qp_text[0]; }
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 87 "qp_lexor.lex"
+ECHO;
+ YY_BREAK
+#line 909 "qp_lexor.c"
+case YY_STATE_EOF(INITIAL):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = (yy_hold_char);
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed qp_in at a new source and called
+ * qp_lex(). If so, then we have to assure
+ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = qp_in;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++(yy_c_buf_p);
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ (yy_did_buffer_switch_on_eof) = 0;
+
+ if ( qp_wrap( ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * qp_text, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) =
+ (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ (yy_c_buf_p) =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+} /* end of qp_lex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+ register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ register char *source = (yytext_ptr);
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+ else
+ {
+ int num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+ int yy_c_buf_p_offset =
+ (int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ qp_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+ number_to_move - 1;
+
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ (yy_n_chars), (size_t) num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ if ( (yy_n_chars) == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ qp_restart(qp_in );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ /* Extend the array by 50%, plus the number we really need. */
+ yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) qp_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ }
+
+ (yy_n_chars) += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+ (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+ static yy_state_type yy_get_previous_state (void)
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+
+ yy_current_state = (yy_start);
+
+ for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 55 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
+{
+ register int yy_is_jam;
+ register char *yy_cp = (yy_c_buf_p);
+
+ register YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 55 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 54);
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+ static int yyinput (void)
+#else
+ static int input (void)
+#endif
+
+{
+ int c;
+
+ *(yy_c_buf_p) = (yy_hold_char);
+
+ if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ /* This was really a NUL. */
+ *(yy_c_buf_p) = '\0';
+
+ else
+ { /* need more input */
+ int offset = (yy_c_buf_p) - (yytext_ptr);
+ ++(yy_c_buf_p);
+
+ switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ qp_restart(qp_in );
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( qp_wrap( ) )
+ return EOF;
+
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) = (yytext_ptr) + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */
+ *(yy_c_buf_p) = '\0'; /* preserve qp_text */
+ (yy_hold_char) = *++(yy_c_buf_p);
+
+ return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ *
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+ void qp_restart (FILE * input_file )
+{
+
+ if ( ! YY_CURRENT_BUFFER ){
+ qp_ensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ qp__create_buffer(qp_in,YY_BUF_SIZE );
+ }
+
+ qp__init_buffer(YY_CURRENT_BUFFER,input_file );
+ qp__load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ *
+ */
+ void qp__switch_to_buffer (YY_BUFFER_STATE new_buffer )
+{
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * qp_pop_buffer_state();
+ * qp_push_buffer_state(new_buffer);
+ */
+ qp_ensure_buffer_stack ();
+ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ qp__load_buffer_state( );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (qp_wrap()) processing, but the only time this flag
+ * is looked at is after qp_wrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void qp__load_buffer_state (void)
+{
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ qp_in = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ (yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ *
+ * @return the allocated buffer state.
+ */
+ YY_BUFFER_STATE qp__create_buffer (FILE * file, int size )
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) qp_alloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in qp__create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) qp_alloc(b->yy_buf_size + 2 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in qp__create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ qp__init_buffer(b,file );
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with qp__create_buffer()
+ *
+ */
+ void qp__delete_buffer (YY_BUFFER_STATE b )
+{
+
+ if ( ! b )
+ return;
+
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ qp_free((void *) b->yy_ch_buf );
+
+ qp_free((void *) b );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a qp_restart() or at EOF.
+ */
+ static void qp__init_buffer (YY_BUFFER_STATE b, FILE * file )
+
+{
+ int oerrno = errno;
+
+ qp__flush_buffer(b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+ /* If b is the current buffer, then qp__init_buffer was _probably_
+ * called from qp_restart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+
+ b->yy_is_interactive = 0;
+
+ errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ *
+ */
+ void qp__flush_buffer (YY_BUFFER_STATE b )
+{
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == YY_CURRENT_BUFFER )
+ qp__load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ *
+ */
+void qp_push_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+ if (new_buffer == NULL)
+ return;
+
+ qp_ensure_buffer_stack();
+
+ /* This block is copied from qp__switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ (yy_buffer_stack_top)++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from qp__switch_to_buffer. */
+ qp__load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ *
+ */
+void qp_pop_buffer_state (void)
+{
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ qp__delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if ((yy_buffer_stack_top) > 0)
+ --(yy_buffer_stack_top);
+
+ if (YY_CURRENT_BUFFER) {
+ qp__load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+ }
+}
+
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+static void qp_ensure_buffer_stack (void)
+{
+ int num_to_alloc;
+
+ if (!(yy_buffer_stack)) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1;
+ (yy_buffer_stack) = (struct yy_buffer_state**)qp_alloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+ if ( ! (yy_buffer_stack) )
+ YY_FATAL_ERROR( "out of dynamic memory in qp_ensure_buffer_stack()" );
+
+ memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ (yy_buffer_stack_max) = num_to_alloc;
+ (yy_buffer_stack_top) = 0;
+ return;
+ }
+
+ if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ int grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = (yy_buffer_stack_max) + grow_size;
+ (yy_buffer_stack) = (struct yy_buffer_state**)qp_realloc
+ ((yy_buffer_stack),
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+ if ( ! (yy_buffer_stack) )
+ YY_FATAL_ERROR( "out of dynamic memory in qp_ensure_buffer_stack()" );
+
+ /* zero only the new slots.*/
+ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+ (yy_buffer_stack_max) = num_to_alloc;
+ }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE qp__scan_buffer (char * base, yy_size_t size )
+{
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) qp_alloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in qp__scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ qp__switch_to_buffer(b );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to qp_lex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ *
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ * qp__scan_bytes() instead.
+ */
+YY_BUFFER_STATE qp__scan_string (yyconst char * yystr )
+{
+
+ return qp__scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to qp_lex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE qp__scan_bytes (yyconst char * yybytes, int _yybytes_len )
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = _yybytes_len + 2;
+ buf = (char *) qp_alloc(n );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in qp__scan_bytes()" );
+
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
+
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = qp__scan_buffer(buf,n );
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in qp__scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up qp_text. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ qp_text[qp_leng] = (yy_hold_char); \
+ (yy_c_buf_p) = qp_text + yyless_macro_arg; \
+ (yy_hold_char) = *(yy_c_buf_p); \
+ *(yy_c_buf_p) = '\0'; \
+ qp_leng = yyless_macro_arg; \
+ } \
+ while ( 0 )
+
+/* Accessor methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ *
+ */
+int qp_get_lineno (void)
+{
+
+ return qp_lineno;
+}
+
+/** Get the input stream.
+ *
+ */
+FILE *qp_get_in (void)
+{
+ return qp_in;
+}
+
+/** Get the output stream.
+ *
+ */
+FILE *qp_get_out (void)
+{
+ return qp_out;
+}
+
+/** Get the length of the current token.
+ *
+ */
+int qp_get_leng (void)
+{
+ return qp_leng;
+}
+
+/** Get the current token.
+ *
+ */
+
+char *qp_get_text (void)
+{
+ return qp_text;
+}
+
+/** Set the current line number.
+ * @param line_number
+ *
+ */
+void qp_set_lineno (int line_number )
+{
+
+ qp_lineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ *
+ * @see qp__switch_to_buffer
+ */
+void qp_set_in (FILE * in_str )
+{
+ qp_in = in_str ;
+}
+
+void qp_set_out (FILE * out_str )
+{
+ qp_out = out_str ;
+}
+
+int qp_get_debug (void)
+{
+ return qp__flex_debug;
+}
+
+void qp_set_debug (int bdebug )
+{
+ qp__flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+ /* Initialization is the same as for the non-reentrant scanner.
+ * This function is called from qp_lex_destroy(), so don't allocate here.
+ */
+
+ (yy_buffer_stack) = 0;
+ (yy_buffer_stack_top) = 0;
+ (yy_buffer_stack_max) = 0;
+ (yy_c_buf_p) = (char *) 0;
+ (yy_init) = 0;
+ (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+ qp_in = stdin;
+ qp_out = stdout;
+#else
+ qp_in = (FILE *) 0;
+ qp_out = (FILE *) 0;
+#endif
+
+ /* For future reference: Set errno on error, since we are called by
+ * qp_lex_init()
+ */
+ return 0;
+}
+
+/* qp_lex_destroy is for both reentrant and non-reentrant scanners. */
+int qp_lex_destroy (void)
+{
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ qp__delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ qp_pop_buffer_state();
+ }
+
+ /* Destroy the stack itself. */
+ qp_free((yy_buffer_stack) );
+ (yy_buffer_stack) = NULL;
+
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * qp_lex() is called, initialization will occur. */
+ yy_init_globals( );
+
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *qp_alloc (yy_size_t size )
+{
+ return (void *) malloc( size );
+}
+
+void *qp_realloc (void * ptr, yy_size_t size )
+{
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+}
+
+void qp_free (void * ptr )
+{
+ free( (char *) ptr ); /* see qp_realloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 87 "qp_lexor.lex"
+
+
+
diff --git a/jpegxr/qp_lexor.lex b/jpegxr/qp_lexor.lex
new file mode 100644
index 000000000..3dda90448
--- /dev/null
+++ b/jpegxr/qp_lexor.lex
@@ -0,0 +1,87 @@
+
+%{
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008.
+**********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: qp_lexor.lex,v 1.6 2008/03/14 16:08:04 steve Exp $")
+#else
+#ident "$Id: qp_lexor.lex,v 1.6 2008/03/14 16:08:04 steve Exp $"
+#endif
+
+# include "qp.tab.h"
+# include "jxr_priv.h"
+
+%}
+
+%option noyywrap
+%option batch
+%option never-interactive
+%option nounput
+
+ /* Windows VidualStudio does not have a <unistd.h> header file, */
+ /* so we want the nounistd option to prevent it. However, this */
+ /* option doesn't seem to work properly, so we instead rely on */
+ /* "sed" to remove the include from the */
+ /* generated code. */
+ /* %option nounistd */
+
+%%
+
+
+[ \t\r\n] { /* Skip white space */; }
+"#".* { /* Skip comments */; }
+
+"DC" { return K_DC; }
+"LP" { return K_LP; }
+"HP" { return K_HP; }
+
+"channel" { return K_CHANNEL; }
+"independent" { return K_INDEPENDENT; }
+"separate" { return K_SEPARATE; }
+"tile" { return K_TILE; }
+"uniform" { return K_UNIFORM; }
+
+[0-9]+ { qp_lval.number = strtoul(yytext, 0, 0); return NUMBER; }
+
+. { return yytext[0]; }
+
+%%
diff --git a/jpegxr/qp_parse.y b/jpegxr/qp_parse.y
new file mode 100644
index 000000000..9544290bf
--- /dev/null
+++ b/jpegxr/qp_parse.y
@@ -0,0 +1,308 @@
+
+%{
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008.
+**********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: qp_parse.y,v 1.8 2008/03/20 18:10:29 steve Exp $")
+#else
+#ident "$Id: qp_parse.y,v 1.8 2008/03/20 18:10:29 steve Exp $"
+#endif
+
+# include "jpegxr.h"
+# include <stdlib.h>
+# include <assert.h>
+# define YYINCLUDED_STDLIB_H
+
+ extern int qp_lex(void);
+ static void yyerror(const char*txt);
+
+ static int errors = 0;
+
+ /* Parse state variables. */
+
+ /* The image we are getting QP values for */
+ static jxr_image_t cur_image;
+ /* Some characteristics of that image. */
+ static unsigned tile_columns;
+ static unsigned tile_rows;
+
+ /* The array of all the tiles to be calculated. */
+ static struct jxr_tile_qp* tile_qp = 0;
+
+ /* Tile currently in progress. */
+ static unsigned cur_tilex = 0;
+ static unsigned cur_tiley = 0;
+ static struct jxr_tile_qp*cur_tile = 0;
+
+ static unsigned mb_in_tile = 0;
+
+ static unsigned cur_channel = 0;
+
+%}
+
+%union {
+ unsigned number;
+
+ struct {
+ unsigned char*data;
+ unsigned count;
+ } map_list;
+
+ struct sixteen_nums {
+ unsigned char num;
+ unsigned char qp[16];
+ } qp_set;
+}
+
+
+ /* Keywords */
+%token K_DC K_CHANNEL K_HP K_INDEPENDENT K_LP K_SEPARATE K_TILE K_UNIFORM
+ /* Other tokens */
+%token <number> NUMBER
+
+%type <qp_set> lphp_qp_list
+%type <map_list> map_list
+
+%%
+
+start : tile_list ;
+
+tile_list
+ : tile_list tile
+ | tile
+ ;
+
+ /* Describe the QP for a specific tile in the image, with the tile
+ position given in tile-column/tile-row coordinates. */
+tile
+ : K_TILE '(' NUMBER ',' NUMBER ')'
+ { cur_tilex = $3,
+ cur_tiley = $5;
+ assert(cur_tilex < tile_columns);
+ assert(cur_tiley < tile_rows);
+ cur_tile = tile_qp + cur_tiley*tile_columns + cur_tilex;
+ mb_in_tile = jxr_get_TILE_WIDTH(cur_image, cur_tilex) * jxr_get_TILE_HEIGHT(cur_image, cur_tiley);
+ }
+ '{' tile_comp_mode tile_body '}'
+ { /* Check the sanity of the calculated tile. */
+ int idx;
+ switch (cur_tile->component_mode) {
+ case JXR_CM_UNIFORM:
+ break;
+ case JXR_CM_SEPARATE:
+ if (cur_tile->channel[0].num_lp != cur_tile->channel[1].num_lp) {
+ fprintf(stderr, "channel-0 and channel-1 LP counts don't match\n");
+ errors += 1;
+ }
+ if (cur_tile->channel[0].num_hp != cur_tile->channel[1].num_hp) {
+ fprintf(stderr, "channel-0 and channel-1 HP counts don't match\n");
+ errors += 1;
+ }
+ if (jxr_get_IMAGE_CHANNELS(cur_image) == 1) {
+ fprintf(stderr, "Gray (1-channel) tiles must be channel mode UNIFORM\n");
+ errors += 1;
+ }
+ break;
+ case JXR_CM_INDEPENDENT:
+ for (idx = 1 ; idx < jxr_get_IMAGE_CHANNELS(cur_image) ; idx += 1) {
+ if (cur_tile->channel[0].num_lp != cur_tile->channel[idx].num_lp) {
+ fprintf(stderr, "channel-0 and channel-%d LP counts don't match\n", idx);
+ errors += 1;
+ }
+ if (cur_tile->channel[0].num_hp != cur_tile->channel[idx].num_hp) {
+ fprintf(stderr, "channel-0 and channel-%d HP counts don't match\n", idx);
+ errors += 1;
+ }
+ }
+ if (jxr_get_IMAGE_CHANNELS(cur_image) == 1) {
+ fprintf(stderr, "Gray (1-channel) tiles must be channel mode UNIFORM\n");
+ errors += 1;
+ }
+ break;
+ case JXR_CM_Reserved:
+ assert(0);
+ break;
+ }
+ }
+ ;
+
+tile_comp_mode
+ : K_UNIFORM { cur_tile->component_mode = JXR_CM_UNIFORM; }
+ | K_SEPARATE { cur_tile->component_mode = JXR_CM_SEPARATE; }
+ | K_INDEPENDENT { cur_tile->component_mode = JXR_CM_INDEPENDENT; }
+ ;
+
+tile_body
+ : tile_body tile_item
+ | tile_item
+ ;
+
+tile_item
+ : K_CHANNEL NUMBER
+ { cur_channel = $2;
+ assert(cur_channel < 16);
+ cur_tile->channel[cur_channel].num_lp = 0;
+ cur_tile->channel[cur_channel].num_hp = 0;
+ }
+ '{' channel_body '}'
+
+ | K_LP '[' map_list ']'
+ { cur_tile->lp_map = $3.data;
+ if ($3.count != mb_in_tile) {
+ errors += 1;
+ fprintf(stderr, "parse qp: In tile %u,%u, expected %u lp blocks, got %u.\n",
+ cur_tilex, cur_tiley, mb_in_tile, $3.count);
+ }
+ }
+
+ | K_HP '[' map_list ']'
+ { cur_tile->hp_map = $3.data;
+ if ($3.count != mb_in_tile) {
+ errors += 1;
+ fprintf(stderr, "parse qp: In tile %u,%u, expected %u lp blocks, got %u.\n",
+ cur_tilex, cur_tiley, mb_in_tile, $3.count);
+ }
+ }
+ ;
+
+channel_body
+ : channel_body channel_item
+ | channel_item
+ ;
+
+channel_item
+ : K_DC '{' NUMBER '}'
+ { cur_tile->channel[cur_channel].dc_qp = $3; }
+
+ | K_LP '{' lphp_qp_list '}'
+ { cur_tile->channel[cur_channel].num_lp = $3.num;
+ int idx;
+ for (idx = 0 ; idx < $3.num ; idx += 1)
+ cur_tile->channel[cur_channel].lp_qp[idx] = $3.qp[idx];
+ }
+
+ | K_HP '{' lphp_qp_list '}'
+ { cur_tile->channel[cur_channel].num_hp = $3.num;
+ int idx;
+ for (idx = 0 ; idx < $3.num ; idx += 1)
+ cur_tile->channel[cur_channel].hp_qp[idx] = $3.qp[idx];
+ }
+
+ ;
+
+lphp_qp_list
+ : lphp_qp_list optional_comma NUMBER
+ { unsigned cnt = $1.num;
+ if (cnt >= 16) {
+ fprintf(stderr, "Too many (>16) QP values in QP list.\n");
+ errors += 1;
+ } else {
+ assert(cnt < 16);
+ $1.qp[cnt] = $3;
+ $1.num += 1;
+ }
+ $$ = $1;
+ }
+ | NUMBER
+ { $$.num = 1;
+ $$.qp[0] = $1;
+ }
+ ;
+
+optional_comma: ',' | ;
+
+map_list
+ : map_list NUMBER
+ { if ($1.count >= mb_in_tile) {
+ fprintf(stderr, "Too many map items for tile!\n");
+ errors += 1;
+ } else {
+ $1.data[$1.count++] = $2;
+ }
+ $$ = $1;
+ }
+
+ | NUMBER
+ { assert(mb_in_tile >= 1);
+ $$.data = (unsigned char*)calloc(mb_in_tile, 1);
+ $$.count = 1;
+ $$.data[0] = $1;
+ }
+ ;
+
+%%
+
+extern void qp_restart(FILE*fd);
+
+int qp_parse_file(FILE*fd, jxr_image_t image)
+{
+ cur_image = image;
+ tile_columns = jxr_get_TILE_COLUMNS(image);
+ tile_rows = jxr_get_TILE_ROWS(image);
+
+ tile_qp = (struct jxr_tile_qp *) calloc(tile_columns*tile_rows, sizeof(*tile_qp));
+ assert(tile_qp);
+
+#if defined(DETAILED_DEBUG)
+ printf("qp_parse: tile_columns=%u, tile_rows=%u\n", tile_columns, tile_rows);
+#endif
+
+ qp_restart(fd);
+ yyparse();
+
+#if defined(DETAILED_DEBUG)
+ printf("qp_parse: parse done with %u errors\n", errors);
+#endif
+
+ if (errors) return -1;
+
+ jxr_set_QP_DISTRIBUTED(image, tile_qp);
+ return 0;
+}
+
+
+
+static void yyerror(const char*txt)
+{
+ fprintf(stderr, "parsing QP file: %s\n", txt);
+ errors += 1;
+}
diff --git a/jpegxr/r_parse.c b/jpegxr/r_parse.c
new file mode 100644
index 000000000..2b4df846e
--- /dev/null
+++ b/jpegxr/r_parse.c
@@ -0,0 +1,3378 @@
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+***********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: r_parse.c,v 1.39 2008/03/24 18:06:56 steve Exp $")
+#else
+#ident "$Id: r_parse.c,v 1.39 2008/03/24 18:06:56 steve Exp $"
+#endif
+
+# include "jxr_priv.h"
+# include <stdlib.h>
+# include <memory.h>
+# include <assert.h>
+
+static int r_image_header(jxr_image_t image, struct rbitstream*str);
+static int r_image_plane_header(jxr_image_t image, struct rbitstream*str, int alpha);
+static int r_INDEX_TABLE(jxr_image_t image, struct rbitstream*str);
+static int64_t r_PROFILE_LEVEL_INFO(jxr_image_t image, struct rbitstream*str);
+static int r_TILE(jxr_image_t image, struct rbitstream*str);
+
+static int r_HP_QP(jxr_image_t image, struct rbitstream*str);
+
+static int32_t r_DEC_DC(jxr_image_t image, struct rbitstream*str,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my,
+ int model_bits, int chroma_flag, int is_dc_ch);
+static uint32_t r_DECODE_ABS_LEVEL(jxr_image_t image, struct rbitstream*str,
+ int band, int chroma_flag);
+static int r_DECODE_FIRST_INDEX(jxr_image_t image, struct rbitstream*str,
+ int chroma_flag, int band);
+static int r_DECODE_INDEX(jxr_image_t image, struct rbitstream*str,
+ int location, int chroma_flag, int band, int context);
+static int r_DECODE_RUN(jxr_image_t image, struct rbitstream*str, int max_run);
+static int r_REFINE_LP(struct rbitstream*str, int coeff, int model_bits);
+static int r_REFINE_CBP(struct rbitstream*str, int cbp);
+static void r_PredCBP(jxr_image_t image, int*diff_cbp,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my);
+static int r_DECODE_BLOCK_ADAPTIVE(jxr_image_t image, struct rbitstream*str,
+ unsigned tx, unsigned mx,
+ int cbp_flag, int chroma_flag,
+ int channel, int block, int mbhp_pred_mode,
+ unsigned model_bits);
+static void r_BLOCK_FLEXBITS(jxr_image_t image, struct rbitstream*str,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my,
+ unsigned chan, unsigned bl, unsigned model_bits);
+static int r_calculate_mbhp_mode(jxr_image_t image, int tx, int mx);
+static int get_is_dc_yuv(struct rbitstream*str);
+static int dec_cbp_yuv_lp1(jxr_image_t image, struct rbitstream*str);
+static int dec_abslevel_index(jxr_image_t image, struct rbitstream*str, int vlc_select);
+static int get_num_cbp(struct rbitstream*str, struct adaptive_vlc_s*vlc);
+static int get_num_blkcbp(jxr_image_t image, struct rbitstream*str, struct adaptive_vlc_s*vlc);
+static int get_value_012(struct rbitstream*str);
+static int get_num_ch_blk(struct rbitstream*str);
+
+
+
+int jxr_read_image_bitstream(jxr_image_t image, FILE*fd)
+{
+ int rc;
+ struct rbitstream bits;
+ uint8_t input_profile;
+ uint8_t input_level;
+ int64_t subsequent_bytes;
+
+ _jxr_rbitstream_initialize(&bits, fd);
+
+ /* Image header for the image overall */
+ rc = r_image_header(image, &bits);
+ if (rc < 0) return rc;
+
+ /* Image plane. */
+ rc = r_image_plane_header(image, &bits, 0);
+ if (rc < 0) return rc;
+
+ /* Make image structures that need header details. */
+ _jxr_make_mbstore(image, 0);
+
+ /* If there is an alpa channel, process the image place header
+ for it. */
+ if (ALPHACHANNEL_FLAG(image)) {
+ int ch;
+
+ image->alpha = jxr_create_input();
+ *image->alpha = *image;
+
+ rc = r_image_plane_header(image->alpha, &bits, 1);
+ if (rc < 0) return rc;
+
+ for(ch = 0; ch < image->num_channels; ch ++)
+ memset(&image->alpha->strip[ch], 0, sizeof(image->alpha->strip[ch]));
+
+ _jxr_make_mbstore(image->alpha, 0);
+ image->alpha->primary = 0;
+ }
+
+ rc = r_INDEX_TABLE(image, &bits);
+
+ /* Store command line input values for later comparison */
+ input_profile = image->profile_idc;
+ input_level = image->level_idc;
+
+ /* inferred value as per Appendix B */
+ image->profile_idc = 111;
+ image->level_idc = 255;
+
+ subsequent_bytes = _jxr_rbitstream_intVLW(&bits);
+ DEBUG(" Subsequent bytes with %ld bytes\n", subsequent_bytes);
+ if (subsequent_bytes > 0) {
+ int64_t read_bytes = r_PROFILE_LEVEL_INFO(image,&bits);
+ int64_t additional_bytes = subsequent_bytes - read_bytes;
+ int64_t idx;
+ for (idx = 0 ; idx < additional_bytes ; idx += 1) {
+ _jxr_rbitstream_uint8(&bits); /* RESERVED_A_BYTE */
+ }
+ }
+
+ assert(image->profile_idc <= input_profile);
+ assert(image->level_idc <= input_level);
+
+ rc = jxr_test_PROFILE_IDC(image, 1);
+ rc = jxr_test_LEVEL_IDC(image, 1);
+
+ DEBUG("MARK HERE as the tile base. bitpos=%zu\n", _jxr_rbitstream_bitpos(&bits));
+ _jxr_rbitstream_mark(&bits);
+
+ /* The image data is in a TILE element even if there is no
+ tiling. No tiling just means 1 big tile. */
+ rc = r_TILE(image, &bits);
+
+ DEBUG("Consumed %zu bytes of the bitstream\n", bits.read_count);
+
+#ifdef VERIFY_16BIT
+ if(image->lwf_test == 0)
+ DEBUG("Meet conditions for LONG_WORD_FLAG == 0!");
+ else {
+ DEBUG("Don't meet conditions for LONG_WORD_FLAG == 0!");
+ if (LONG_WORD_FLAG(image) == 0)
+ return JXR_EC_BADFORMAT;
+ }
+#endif
+
+ return rc;
+}
+
+int jxr_test_LONG_WORD_FLAG(jxr_image_t image, int flag)
+{
+#ifdef VERIFY_16BIT
+ if (flag == 0 && image->lwf_test != 0) {
+ DEBUG("Using LONG_WORD_FLAG decoder but did not meet LONG_WORD_FLAG == 0 conditions!");
+ return JXR_EC_BADFORMAT;
+ }
+ else
+#endif
+ return 0;
+
+}
+
+#if defined(DETAILED_DEBUG)
+static const char*bitdepth_names[16] = {
+ "BD1WHITE1", "BD8", "BD16", "BD16S",
+ "BD16F", "RESERVED5", "BD32S", "BD32F",
+ "BD5", "BD10", "BD565", "RESERVED11"
+ "RESERVED12", "RESERVED12", "RESERVED12","BD1BLACK1"
+};
+
+#endif
+
+static int r_image_header(jxr_image_t image, struct rbitstream*str)
+{
+ const char GDI_SIG[] = "WMPHOTO\0";
+ unsigned idx;
+
+ unsigned version_info, version_sub_info;
+ unsigned hei_sum;
+ unsigned wid_sum = 0;
+
+ /* Read and test the GDI_SIGNATURE magic number */
+ for (idx = 0 ; idx < 8 ; idx += 1) {
+ uint8_t byte = _jxr_rbitstream_uint8(str);
+ if (byte != GDI_SIG[idx]) {
+ return JXR_EC_BADMAGIC;
+ }
+ }
+
+ DEBUG("Got magic number.\n");
+ DEBUG("START IMAGE_HEADER (bitpos=%zu)\n", _jxr_rbitstream_bitpos(str));
+
+ /* Get the version info */
+ version_info = _jxr_rbitstream_uint4(str);
+
+ image->disableTileOverlapFlag = _jxr_rbitstream_uint1(str);
+ DEBUG(" disableTileOverlapFlag: %d\n", image->disableTileOverlapFlag);
+
+ version_sub_info = _jxr_rbitstream_uint3(str);
+ DEBUG(" Version: %u.%u\n", version_info, version_sub_info);
+
+ /* Read some of the flags as a group. There are a bunch of
+ small flag values together here, so it is economical to
+ just collect them all at once. */
+ image->header_flags1 = _jxr_rbitstream_uint8(str);
+ image->header_flags2 = _jxr_rbitstream_uint8(str);
+ image->header_flags_fmt = _jxr_rbitstream_uint8(str);
+
+ /* check container conformance */
+ if (image->container_current_separate_alpha == 0)
+ assert(SOURCE_CLR_FMT(image) == image->container_color);
+ assert(((image->header_flags_fmt & 0x0f) == 15 ? 0 : (image->header_flags_fmt & 0x0f)) == image->container_bpc);
+ if (image->container_separate_alpha == 0)
+ assert(image->container_alpha == ALPHACHANNEL_FLAG(image));
+ else
+ assert(ALPHACHANNEL_FLAG(image) == 0);
+
+ DEBUG(" Flags group1=0x%02x\n", image->header_flags1);
+ DEBUG(" Flags group2=0x%02x\n", image->header_flags2);
+ DEBUG(" OUTPUT_CLR_FMT=%d\n", SOURCE_CLR_FMT(image));
+ DEBUG(" OUTPUT_BITDEPTH=%d (%s)\n", SOURCE_BITDEPTH(image), bitdepth_names[SOURCE_BITDEPTH(image)]);
+
+ /* Get the configured image dimensions. */
+ if (SHORT_HEADER_FLAG(image)) {
+ DEBUG(" SHORT_HEADER_FLAG=true\n");
+ image->width1 = _jxr_rbitstream_uint16(str);
+ image->height1 = _jxr_rbitstream_uint16(str);
+ } else {
+ DEBUG(" SHORT_HEADER_FLAG=false\n");
+ image->width1 = _jxr_rbitstream_uint32(str);
+ image->height1 = _jxr_rbitstream_uint32(str);
+ }
+
+ /* check container conformance */
+ assert(image->width1 + 1 == image->container_width);
+ assert(image->height1 + 1 == image->container_height);
+
+ DEBUG(" Image dimensions: %u x %u\n", image->width1+1, image->height1+1);
+
+ assert(image->tile_row_height == 0);
+ assert(image->tile_column_width == 0);
+ assert(image->tile_column_position == 0);
+ if (jxr_get_TILING_FLAG(image)) {
+ image->tile_columns = _jxr_rbitstream_uint12(str) + 1;
+ image->tile_rows = _jxr_rbitstream_uint12(str) + 1;
+ DEBUG(" TILING %u columns, %u rows (bitpos=%zu)\n",
+ image->tile_columns, image->tile_rows,
+ _jxr_rbitstream_bitpos(str));
+
+
+ } else {
+ /* NO TILING means that the entire image is exactly 1
+ tile. Configure the single tile to be the size of the
+ entire image. */
+ image->tile_columns = 1;
+ image->tile_rows = 1;
+ DEBUG(" NO TILING\n");
+ }
+
+ /* Collect the widths of the tile columns. All but the last
+ column width are encoded in the input stream. The last is
+ inferred from the accumulated width of the columns and the
+ total width of the image. If there is no tiling, then there
+ is exactly 1 tile, and this degenerates to the width of the
+ image.
+
+ The heights of tile rows is processed exactly the same way. */
+
+ image->tile_column_width = (unsigned*)calloc(2*image->tile_columns, sizeof(unsigned));
+ image->tile_column_position = image->tile_column_width + image->tile_columns;
+ image->tile_row_height = (unsigned*)calloc(2*image->tile_rows, sizeof(unsigned));
+ image->tile_row_position = image->tile_row_height + image->tile_rows;
+
+ wid_sum = 0;
+ if (SHORT_HEADER_FLAG(image)) {
+ for (idx = 0 ; idx < image->tile_columns-1 ; idx += 1) {
+ image->tile_column_width[idx] = _jxr_rbitstream_uint8(str);
+ image->tile_column_position[idx] = wid_sum;
+ wid_sum += image->tile_column_width[idx];
+ }
+
+ } else {
+ for (idx = 0 ; idx < image->tile_columns-1 ; idx += 1) {
+ image->tile_column_width[idx] = _jxr_rbitstream_uint16(str);
+ image->tile_column_position[idx] = wid_sum;
+ wid_sum += image->tile_column_width[idx];
+ }
+ }
+ /* calculate final tile width after windowing parameters are found */
+
+ hei_sum = 0;
+ if (SHORT_HEADER_FLAG(image)) {
+ for (idx = 0 ; idx < image->tile_rows-1 ; idx += 1) {
+ image->tile_row_height[idx] = _jxr_rbitstream_uint8(str);
+ image->tile_row_position[idx] = hei_sum;
+ hei_sum += image->tile_row_height[idx];
+ }
+
+ } else {
+ for (idx = 0 ; idx < image->tile_rows-1 ; idx += 1) {
+ image->tile_row_height[idx] = _jxr_rbitstream_uint16(str);
+ image->tile_row_position[idx] = hei_sum;
+ hei_sum += image->tile_row_height[idx];
+ }
+ }
+ /* calculate final tile height after windowing parameters are found */
+
+ if (WINDOWING_FLAG(image)) {
+ image->window_extra_top = _jxr_rbitstream_uint6(str);
+ image->window_extra_left = _jxr_rbitstream_uint6(str);
+ image->window_extra_bottom = _jxr_rbitstream_uint6(str);
+ image->window_extra_right = _jxr_rbitstream_uint6(str);
+ } else {
+ image->window_extra_top = 0;
+ image->window_extra_left = 0;
+ if ((image->height1 + 1) % 16 == 0)
+ image->window_extra_bottom = 0;
+ else
+ image->window_extra_bottom = 16 - ((image->height1 + 1) % 16);
+ if ((image->width1 + 1) % 16 == 0)
+ image->window_extra_right = 0;
+ else
+ image->window_extra_right = 16 - ((image->width1 + 1) % 16);
+ DEBUG(" NO WINDOWING\n");
+ }
+ image->extended_width = image->width1 + 1 + image->window_extra_left + image->window_extra_right;
+ image->extended_height = image->height1 + 1 + image->window_extra_top + image->window_extra_bottom;
+
+ image->lwf_test = 0;
+
+ image->tile_column_width[image->tile_columns-1] = (image->extended_width >> 4)-wid_sum;
+ image->tile_column_position[image->tile_columns-1] = wid_sum;
+
+ image->tile_row_height[image->tile_rows-1] = (image->extended_height >> 4)-hei_sum;
+ image->tile_row_position[image->tile_rows-1] = hei_sum;
+
+#if defined(DETAILED_DEBUG)
+ DEBUG(" Tile widths:");
+ for (idx = 0 ; idx < image->tile_columns ; idx += 1)
+ DEBUG(" %u", image->tile_column_width[idx]);
+ DEBUG("\n");
+ DEBUG(" Tile heights:");
+ for (idx = 0 ; idx < image->tile_rows ; idx += 1)
+ DEBUG(" %u", image->tile_row_height[idx]);
+ DEBUG("\n");
+#endif
+
+ /* Perform some checks */
+ assert(image->extended_width % 16 == 0);
+ if ((OVERLAP_INFO(image) >= 2) && (image->use_clr_fmt == 1 || image->use_clr_fmt == 2))
+ {
+ assert(image->extended_width >= 32);
+ if (image->disableTileOverlapFlag) {
+ unsigned int idx = 0;
+ for (idx = 0; idx < image->tile_columns ; idx += 1)
+ assert(image->tile_column_width[idx] > 1);
+ }
+ }
+ assert(image->extended_height % 16 == 0);
+
+ DEBUG("END IMAGE_HEADER (%zu bytes)\n", str->read_count);
+ return 0;
+}
+
+static int r_image_plane_header(jxr_image_t image, struct rbitstream*str, int alpha)
+{
+ size_t save_count = str->read_count;
+ uint16_t num_components;
+
+ DEBUG("START IMAGE_PLANE_HEADER (bitpos=%zu)\n", _jxr_rbitstream_bitpos(str));
+
+ /* NOTE: The "use_clr_fmt" is the encoded color format, and is
+ not necessarily the same as the image color format
+ signaled in the image header. All of our processing of an
+ image plane is handled using the "use_clr_fmt", and only
+ transformed to the image color format on the way out. */
+
+ image->use_clr_fmt = _jxr_rbitstream_uint3(str); /* INTERNAL_CLR_FMT */
+ image->scaled_flag = _jxr_rbitstream_uint1(str); /* NO_SCALED_FLAG */
+ image->bands_present = _jxr_rbitstream_uint4(str); /* BANDS_PRESENT */
+
+ /* for alpha image plane, INTERNAL_CLR_FMT == YONLY */
+ if (alpha)
+ assert(image->use_clr_fmt == 0);
+
+ DEBUG(" INTERNAL_CLR_FMT = %d\n", image->use_clr_fmt);
+ DEBUG(" SCALED_FLAG = %s\n", image->scaled_flag? "true" : "false");
+ DEBUG(" BANDS_PRESENT = %d\n", image->bands_present);
+
+ switch (image->use_clr_fmt) {
+ case 0: /* YONLY */
+ image->num_channels = 1;
+ break;
+ case 1: /* YUV420 */
+ _jxr_rbitstream_uint1(str); /* RESERVED_E_BIT */
+ image->chroma_centering_x = _jxr_rbitstream_uint3(str); /* CHROMA_CENTERING_X */
+ _jxr_rbitstream_uint1(str); /* RESERVED_G_BIT */
+ image->chroma_centering_y = _jxr_rbitstream_uint3(str); /* CHROMA_CENTERING_Y */
+ image->num_channels = 3;
+ break;
+ case 2: /* YUV422 */
+ _jxr_rbitstream_uint1(str); /* RESERVED_E_BIT */
+ image->chroma_centering_x = _jxr_rbitstream_uint3(str); /* CHROMA_CENTERING_X */
+ _jxr_rbitstream_uint4(str); /* RESERVED_H */
+ image->chroma_centering_y = 0;
+ image->num_channels = 3;
+ break;
+ case 3: /* YUV444 */
+ _jxr_rbitstream_uint4(str); /* RESERVED_F */
+ _jxr_rbitstream_uint4(str); /* RESERVED_H */
+ image->num_channels = 3;
+ break;
+ case 4: /* YUVK */
+ image->num_channels = 4;
+ break;
+ case 6: /* NCOMPONENT */
+ num_components = _jxr_rbitstream_uint4(str);
+ if (num_components == 0xf) {
+ image->num_channels = 16 + _jxr_rbitstream_uint12(str);
+ }
+ else {
+ image->num_channels = 1 + num_components;
+ _jxr_rbitstream_uint4(str); /* RESERVED_H */
+ }
+ break;
+ case 5: /* RESERVED */
+ case 7: /* RESERVED */
+ break;
+ }
+
+ /*
+ check container conformance - specific for tag based container
+ this section should be modified when the container is
+ */
+ if (image->container_alpha) {
+ if (image->container_separate_alpha) {
+ if (image->container_current_separate_alpha) {
+ assert(image->num_channels == 1);
+ assert(image->bands_present == image->container_alpha_band_presence || image->container_alpha_band_presence > 3 || image->container_alpha_band_presence < 0);
+ }
+ else {
+ assert(image->num_channels == image->container_nc - 1);
+ assert((image->bands_present == image->container_image_band_presence) || (image->container_image_band_presence > 3) || (image->container_image_band_presence < 0));
+ }
+ }
+ else {
+ if (alpha) {
+ assert(image->num_channels == 1);
+ assert(image->bands_present == image->container_alpha_band_presence || image->container_alpha_band_presence > 3 || image->container_alpha_band_presence < 0);
+ }
+ else {
+ assert(image->num_channels == image->container_nc - 1);
+ assert(image->bands_present == image->container_image_band_presence || image->container_image_band_presence > 3 || (image->container_image_band_presence < 0));
+ }
+ }
+ }
+ else {
+ assert(image->num_channels == image->container_nc);
+ assert(image->bands_present == image->container_image_band_presence || image->container_image_band_presence > 3 || (image->container_image_band_presence < 0));
+ }
+
+
+ switch (SOURCE_BITDEPTH(image)) {
+ case 0: /* BD1WHITE1 */
+ case 1: /* BD8 */
+ case 4: /* BD16F */
+ case 8: /* BD5 */
+ case 9: /* BD10 */
+ case 15: /* BD1BLACK1 */
+ image->shift_bits = 0;
+ break;
+ case 2: /* BD16 */
+ case 3: /* BD16S */
+ case 6: /* BD32S */
+ image->shift_bits = _jxr_rbitstream_uint8(str); /* SHIFT_BITS */
+ DEBUG(" SHIFT_BITS = %u\n", image->shift_bits);
+ break;
+ case 7: /* BD32F */
+ image->len_mantissa = _jxr_rbitstream_uint8(str); /* LEN_MANTISSA */
+ image->exp_bias = _jxr_rbitstream_uint8(str); /* EXP_BIAS */
+ DEBUG(" LEN_MANTISSA = %u\n", image->len_mantissa);
+ DEBUG(" EXP_BIAS = %u\n", image->exp_bias);
+ break;
+ default: /* RESERVED */
+ DEBUG(" XXXX Inexplicable SOURCE_BITDEPTH=%u\n", SOURCE_BITDEPTH(image));
+ break;
+ }
+
+ /* If the stream signals that the DC frames use a uniform
+ quantization parameter, then collect that parameter
+ here. In this case, DC quantization parameters elsewhere in
+ the image are suppressed. Note that per macroblock, there
+ is only 1 DC value, so only 1 DC QP is needed. */
+ image->dc_frame_uniform = _jxr_rbitstream_uint1(str);
+ DEBUG(" DC_FRAME_UNIFORM = %s\n", image->dc_frame_uniform?"true":"false");
+ if (image->dc_frame_uniform) {
+ _jxr_r_DC_QP(image, str);
+ }
+
+ if (image->bands_present != 3 /*DCONLY*/) {
+ _jxr_rbitstream_uint1(str); /* RESERVED_I_BIT */
+
+ image->lp_frame_uniform = _jxr_rbitstream_uint1(str);
+ DEBUG(" LP_FRAME_UNIFORM = %s\n", image->lp_frame_uniform?"true":"false");
+ if (image->lp_frame_uniform) {
+ image->num_lp_qps = 1;
+ _jxr_r_LP_QP(image, str);
+ }
+
+ if (image->bands_present != 2 /*NOHIGHPASS*/) {
+ _jxr_rbitstream_uint1(str); /* RESERVED_J_BIT */
+
+ image->hp_frame_uniform = _jxr_rbitstream_uint1(str);
+ DEBUG(" HP_FRAME_UNIFORM = %s\n", image->hp_frame_uniform?"true":"false");
+ if (image->hp_frame_uniform) {
+ image->num_hp_qps = 1;
+ r_HP_QP(image, str);
+ }
+ }
+
+ }
+
+ _jxr_rbitstream_syncbyte(str);
+ DEBUG("END IMAGE_PLANE_HEADER (%zd bytes, bitpos=%zu)\n",
+ str->read_count - save_count, _jxr_rbitstream_bitpos(str));
+
+ return 0;
+}
+
+static int get_ch_mode(jxr_image_t image, struct rbitstream*str)
+{
+ int ch_mode;
+ if (image->num_channels == 1) {
+ ch_mode = 0; /* UNIFORM */
+ } else {
+ ch_mode = _jxr_rbitstream_uint2(str);
+ }
+ return ch_mode;
+}
+
+int _jxr_r_DC_QP(jxr_image_t image, struct rbitstream*str)
+{
+ unsigned idx;
+
+ int ch_mode = get_ch_mode(image, str);
+ DEBUG(" DC_QP CH_MODE=%d ", ch_mode);
+
+ switch (ch_mode) {
+ case 0: /* UNIFORM */
+ image->dc_quant_ch[0] = _jxr_rbitstream_uint8(str);
+ DEBUG(" DC_QUANT UNIFORM =%u", image->dc_quant_ch[0]);
+ for (idx = 1 ; idx < image->num_channels ; idx += 1)
+ image->dc_quant_ch[idx] = image->dc_quant_ch[0];
+ break;
+ case 1: /* SEPARATE */
+ image->dc_quant_ch[0] = _jxr_rbitstream_uint8(str);
+ image->dc_quant_ch[1] = _jxr_rbitstream_uint8(str);
+ image->dc_quant_ch[2] = image->dc_quant_ch[1];
+ DEBUG(" DC_QUANT SEPARATE Y=%u, Chr=%u", image->dc_quant_ch[0],image->dc_quant_ch[1]);
+ break;
+ case 2: /* INDEPENDENT */
+ assert(image->num_channels <= MAX_CHANNELS);
+ for (idx = 0 ; idx < image->num_channels ; idx += 1) {
+ image->dc_quant_ch[idx] = _jxr_rbitstream_uint8(str);
+ DEBUG(" DC_QUANT INDEPENDENT[%d] = %u", idx, image->dc_quant_ch[idx]);
+ }
+ break;
+ case 3: /* Reserved */
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ DEBUG("\n");
+
+ return 0;
+}
+
+int _jxr_r_LP_QP(jxr_image_t image, struct rbitstream*str)
+{
+ unsigned q;
+
+ for (q = 0 ; q < image->num_lp_qps ; q += 1) {
+ unsigned idx;
+ int ch_mode = get_ch_mode(image, str);
+ DEBUG(" LP_QP[%u] CH_MODE=%d LP_QUANT=", q, ch_mode);
+
+ switch (ch_mode) {
+ case 0: /* UNIFORM */
+ image->lp_quant_ch[0][q] = _jxr_rbitstream_uint8(str);
+ DEBUG("%d", image->lp_quant_ch[0][q]);
+ for (idx = 1 ; idx < image->num_channels ; idx += 1)
+ image->lp_quant_ch[idx][q] = image->lp_quant_ch[0][q];
+ break;
+ case 1: /* SEPARATE */
+ image->lp_quant_ch[0][q] = _jxr_rbitstream_uint8(str);
+ image->lp_quant_ch[1][q] = _jxr_rbitstream_uint8(str);
+ DEBUG("SEPARATE Y=%d Chr=%d", image->lp_quant_ch[0][q], image->lp_quant_ch[1][q]);
+ for (idx = 2 ; idx < image->num_channels ; idx += 1)
+ image->lp_quant_ch[idx][q] = image->lp_quant_ch[1][q];
+ break;
+ case 2: /* INDEPENDENT */
+ DEBUG("INDEPENDENT =");
+ for (idx = 0 ; idx < image->num_channels ; idx += 1) {
+ image->lp_quant_ch[idx][q] = _jxr_rbitstream_uint8(str);
+ DEBUG(" %d", image->lp_quant_ch[idx][q]);
+ }
+ break;
+ case 3: /* Reserved */
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ DEBUG("\n");
+ }
+
+ return 0;
+}
+
+static int r_HP_QP(jxr_image_t image, struct rbitstream*str)
+{
+ unsigned q;
+
+ for (q = 0 ; q < image->num_hp_qps ; q += 1) {
+ unsigned idx;
+ int ch_mode = get_ch_mode(image, str);
+ DEBUG("HP_QP[%u] CH_MODE: %d ", q, ch_mode);
+
+ switch (ch_mode) {
+ case 0: /* UNIFORM */
+ image->HP_QUANT_Y[q] = _jxr_rbitstream_uint8(str);
+ DEBUG("UNIFORM %d", image->hp_quant_ch[0][q]);
+ for (idx = 1 ; idx < image->num_channels ; idx += 1)
+ image->hp_quant_ch[idx][q] = image->hp_quant_ch[0][q];
+ break;
+ case 1: /* SEPARATE */
+ image->HP_QUANT_Y[q] = _jxr_rbitstream_uint8(str);
+ image->hp_quant_ch[1][q] = _jxr_rbitstream_uint8(str);
+ DEBUG("SEPARATE Y=%d Chr=%d", image->hp_quant_ch[0][q], image->hp_quant_ch[1][q]);
+ for (idx = 2 ; idx < image->num_channels ; idx += 1)
+ image->hp_quant_ch[idx][q] = image->hp_quant_ch[1][q];
+ break;
+ case 2: /* INDEPENDENT */
+ DEBUG("INDEPENDENT =");
+ for (idx = 0 ; idx < image->num_channels ; idx += 1) {
+ image->hp_quant_ch[idx][q] = _jxr_rbitstream_uint8(str);
+ DEBUG(" %d", image->hp_quant_ch[idx][q]);
+ }
+ break;
+ case 3: /* Reserved */
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ DEBUG(" bitpos=%zu\n", _jxr_rbitstream_bitpos(str));
+ }
+
+ return 0;
+}
+
+static int r_INDEX_TABLE(jxr_image_t image, struct rbitstream*str)
+{
+ DEBUG("INDEX_TABLE START bitpos=%zu\n", _jxr_rbitstream_bitpos(str));
+ if (INDEXTABLE_PRESENT_FLAG(image)) {
+ int num_index_table_entries;
+ int idx;
+
+ uint8_t s0 = _jxr_rbitstream_uint8(str);
+ uint8_t s1 = _jxr_rbitstream_uint8(str);
+ DEBUG(" STARTCODE = 0x%02x 0x%02x\n", s0, s1);
+ if (s0 != 0x00 || s1 != 0x01)
+ return JXR_EC_ERROR;
+
+ if (FREQUENCY_MODE_CODESTREAM_FLAG(image) == 0 /* SPATIALMODE */) {
+ num_index_table_entries = image->tile_rows * image->tile_columns;
+
+ } else {
+ num_index_table_entries = image->tile_rows * image->tile_columns;
+ switch (image->bands_present) {
+ case 4: /* ISOLATED */
+ num_index_table_entries *= 4;
+ break;
+ default:
+ num_index_table_entries *= 4 - image->bands_present;
+ break;
+ }
+ }
+ image->tile_index_table_length = num_index_table_entries;
+
+ assert(image->tile_index_table == 0);
+ image->tile_index_table = (int64_t*)calloc(num_index_table_entries, sizeof(int64_t));
+ DEBUG(" INDEX_TABLE has %d table entries\n", num_index_table_entries);
+
+ for (idx = 0 ; idx < num_index_table_entries ; idx += 1) {
+ int64_t off = _jxr_rbitstream_intVLW(str);
+ DEBUG(" ... %ld\n", off);
+ image->tile_index_table[idx] = off;
+ }
+ }
+
+ DEBUG("INTEX_TABLE DONE bitpos=%zu\n", _jxr_rbitstream_bitpos(str));
+ return 0;
+}
+
+static int64_t r_PROFILE_LEVEL_INFO(jxr_image_t image, struct rbitstream*str)
+{
+ int64_t num_bytes = 0;
+ uint16_t reserved_l;
+ unsigned last_flag;
+
+ int64_t last;
+ for (last = 0 ; last == 0 ; last = last_flag) {
+ image->profile_idc = _jxr_rbitstream_uint8(str); /* PROFILE_IDC */
+ DEBUG(" Profile signaled in file %ld bytes\n", image->profile_idc);
+ image->level_idc = _jxr_rbitstream_uint8(str); /* LEVEL_IDC */
+ DEBUG(" Level signaled in file %ld bytes\n", image->level_idc);
+ reserved_l = _jxr_rbitstream_uint15(str); /* RESERVED_L */
+ last_flag = _jxr_rbitstream_uint1(str); /* LAST_FLAG */
+ num_bytes += 4;
+ }
+
+ return num_bytes;
+}
+
+static int r_TILE(jxr_image_t image, struct rbitstream*str)
+{
+ int rc = 0;
+ image->tile_quant = (struct jxr_tile_qp *) calloc(image->tile_columns*image->tile_rows, sizeof(*(image->tile_quant)));
+ assert(image->tile_quant);
+
+ if (FREQUENCY_MODE_CODESTREAM_FLAG(image) == 0 /* SPATIALMODE */) {
+
+ unsigned tx, ty, tt=0;
+ for (ty = 0 ; ty < image->tile_rows ; ty += 1) {
+ for (tx = 0 ; tx < image->tile_columns ; tx += 1) {
+ if(INDEXTABLE_PRESENT_FLAG(image))
+ {
+ _jxr_rbitstream_seek(str, image->tile_index_table[tt]);
+ tt++;
+ }
+ rc = _jxr_r_TILE_SPATIAL(image, str, tx, ty);
+ if (rc < 0) goto RET;
+ }
+ }
+ } else { /* FREQUENCYMODE */
+
+ unsigned tx, ty, tt;
+ int num_bands = 0;
+ switch (image->bands_present) {
+ case 0: /* ALL */
+ num_bands = 4;
+ break;
+ case 1: /* NOFLEXBITS */
+ num_bands = 3;
+ break;
+ case 2: /* NOHIGHPASS */
+ num_bands = 2;
+ break;
+ case 3: /* DCONLY */
+ num_bands = 1;
+ break;
+ case 4: /* ISOLATED */
+ break;
+ }
+
+ for (ty = 0, tt=0 ; ty < image->tile_rows ; ty += 1) {
+ for (tx = 0 ; tx < image->tile_columns ; tx += 1) {
+ _jxr_rbitstream_seek(str, image->tile_index_table[tt*num_bands+0]);
+ rc = _jxr_r_TILE_DC(image, str, tx, ty);
+ if (rc < 0) goto RET;
+ tt += 1;
+ }
+ }
+
+ if (num_bands > 1) {
+ for (ty = 0, tt=0 ; ty < image->tile_rows ; ty += 1) {
+ for (tx = 0 ; tx < image->tile_columns ; tx += 1) {
+ _jxr_rbitstream_seek(str, image->tile_index_table[tt*num_bands+1]);
+ rc = _jxr_r_TILE_LP(image, str, tx, ty);
+ if (rc < 0) goto RET;
+ tt += 1;
+ }
+ }
+ }
+
+ if (num_bands > 2) {
+ for (ty = 0, tt=0 ; ty < image->tile_rows ; ty += 1) {
+ for (tx = 0 ; tx < image->tile_columns ; tx += 1) {
+ _jxr_rbitstream_seek(str, image->tile_index_table[tt*num_bands+2]);
+ rc = _jxr_r_TILE_HP(image, str, tx, ty);
+ if (rc < 0) goto RET;
+ tt += 1;
+ }
+ }
+ }
+
+ if (num_bands > 3) {
+ for (ty = 0, tt=0 ; ty < image->tile_rows ; ty += 1) {
+ for (tx = 0 ; tx < image->tile_columns ; tx += 1) {
+ int64_t off = image->tile_index_table[tt*num_bands+3];
+ if (off >= 0) {
+ _jxr_rbitstream_seek(str, off);
+ rc = _jxr_r_TILE_FLEXBITS(image, str, tx, ty);
+ if (rc < 0) goto RET;
+ } else {
+ _jxr_r_TILE_FLEXBITS_ESCAPE(image, tx, ty);
+ }
+ tt += 1;
+ }
+ }
+ }
+
+ _jxr_frequency_mode_render(image);
+ }
+
+RET:
+ free(image->tile_quant);
+ return rc;
+}
+
+void _jxr_r_TILE_HEADER_DC(jxr_image_t image, struct rbitstream*str,
+ int alpha_flag, unsigned tx, unsigned ty)
+{
+ DEBUG(" TILE_HEADER_DC START bitpos=%zu\n", _jxr_rbitstream_bitpos(str));
+ if (image->dc_frame_uniform == 0) {
+ DEBUG(" TILE_HEADER_DC: parse non-uniform DC_QP\n");
+ _jxr_r_DC_QP(image, str);
+ memcpy(image->tile_quant[ty*(image->tile_columns) + tx ].dc_quant_ch, image->dc_quant_ch, MAX_CHANNELS);
+ }
+}
+
+void _jxr_r_TILE_HEADER_LOWPASS(jxr_image_t image, struct rbitstream*str,
+ int alpha_flag,
+ unsigned tx, unsigned ty)
+{
+ DEBUG(" TILE_HEADER_LOWPASS START bitpos=%zu\n", _jxr_rbitstream_bitpos(str));
+ if (image->lp_frame_uniform == 0) {
+ image->lp_use_dc_qp = _jxr_rbitstream_uint1(str);
+ DEBUG(" TILE_HEADER_LP: parse non-uniform LP_QP: USE_DC_QP=%u\n",
+ image->lp_use_dc_qp);
+ if (image->lp_use_dc_qp == 0) {
+ image->num_lp_qps = _jxr_rbitstream_uint4(str) + 1;
+ DEBUG(" TILE_HEADER_LP: NUM_LP_QPS = %d\n", image->num_lp_qps);
+ _jxr_r_LP_QP(image, str);
+ memcpy(image->tile_quant[ty*(image->tile_columns) + tx].lp_quant_ch, image->lp_quant_ch, MAX_CHANNELS*MAX_LP_QPS);
+ }
+ else
+ {
+ /* Use the same quantization index as the dc band (the dc quantization step size could be different for each tile, so store it */
+ int ch;
+ for(ch = 0; ch < image->num_channels; ch++)
+ image->tile_quant[ty*(image->tile_columns) + tx].lp_quant_ch[ch][0] = image->dc_quant_ch[ch];
+ }
+ }
+}
+
+
+void _jxr_r_TILE_HEADER_HIGHPASS(jxr_image_t image, struct rbitstream*str,
+ int alpha_flag,
+ unsigned tx, unsigned ty)
+{
+ if (image->hp_frame_uniform == 0) {
+ image->hp_use_lp_qp = _jxr_rbitstream_uint1(str);
+ DEBUG(" TILE_HEADER_HP: parse non-uniform HP_QP: USE_LP_QP=%u\n",
+ image->hp_use_lp_qp);
+
+ if (image->hp_use_lp_qp == 0) {
+ image->num_hp_qps = _jxr_rbitstream_uint4(str) + 1;
+ DEBUG(" TILE_HEADER_HIGHPASS: NUM_HP_QPS = %d\n", image->num_hp_qps);
+ r_HP_QP(image, str);
+ memcpy(image->tile_quant[ty*(image->tile_columns) + tx].hp_quant_ch, image->lp_quant_ch, MAX_CHANNELS*MAX_HP_QPS);
+ }
+ else
+ {
+ /* Use the same quantization index as the lp band (the lp quantization step size could be different for each tile, so store it */
+ int ch;
+ image->num_hp_qps = image->num_lp_qps;
+ for(ch = 0; ch < image->num_channels; ch++) {
+ memcpy(image->hp_quant_ch[ch], image->lp_quant_ch[ch], MAX_LP_QPS);
+ memcpy(image->tile_quant[ty*(image->tile_columns) + tx].hp_quant_ch[ch], image->lp_quant_ch[ch], MAX_LP_QPS);
+ }
+ }
+ }
+}
+
+unsigned _jxr_DECODE_QP_INDEX(struct rbitstream*str, unsigned index_count)
+{
+ static const int bits_per_qp_index[] = {0,0,1,1,2,2,3,3, 3,3,4,4,4,4,4,4,4};
+
+ int nonzero_flag = _jxr_rbitstream_uint1(str);
+ int bits_count;
+
+ assert(index_count <= 16);
+ if (nonzero_flag == 0)
+ return 0;
+
+ bits_count = bits_per_qp_index[index_count];
+ /* DECODE_QP_INDEX is onny called if the index count is
+ greater then 1. Therefore, the bits_count here must be more
+ then zero. */
+ assert(bits_count > 0);
+
+ return _jxr_rbitstream_uintN(str, bits_count)+1;
+}
+
+/*
+* Decode the single DC component for the macroblock.
+*/
+void _jxr_r_MB_DC(jxr_image_t image, struct rbitstream*str,
+ int alpha_flag,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my)
+{
+ int lap_mean[2];
+ lap_mean[0] = 0;
+ lap_mean[1] = 0;
+
+ DEBUG(" MB_DC tile=[%u %u] mb=[%u %u] bitpos=%zu\n",
+ tx, ty, mx, my, _jxr_rbitstream_bitpos(str));
+
+ if (_jxr_InitContext(image, tx, ty, mx, my)) {
+ DEBUG(" MB_DC: Initialize Context\n");
+ _jxr_InitVLCTable(image, AbsLevelIndDCLum);
+ _jxr_InitVLCTable(image, AbsLevelIndDCChr);
+ _jxr_InitializeModelMB(&image->model_dc, 0/*DC*/);
+ }
+
+ if (image->use_clr_fmt==0 || image->use_clr_fmt==4 || image->use_clr_fmt==6) {
+ /* clr_fmt == YONLY, YUVK or NCOMPONENT */
+ unsigned idx;
+ for (idx = 0 ; idx < image->num_channels ; idx += 1) {
+ int m = (idx == 0)? 0 : 1;
+ int model_bits = image->model_dc.bits[m];
+ unsigned is_dc_ch = _jxr_rbitstream_uint1(str);
+ uint32_t dc_val;
+ DEBUG(" MB_DC: IS_DC_CH=%u, model_bits=%d\n",
+ is_dc_ch, model_bits);
+ if (is_dc_ch) {
+ lap_mean[m] += 1;
+ }
+ dc_val = r_DEC_DC(image, str, tx, ty, mx, my,
+ model_bits, 0/*chroma_flag==FALSE*/,
+ is_dc_ch);
+
+ MACROBLK_CUR_DC(image,idx,tx, mx) = dc_val;
+ DEBUG(" dc_val at t=[%u %u], m=[%u %u] == %d (0x%08x)\n",
+ tx, ty, mx, my, (int32_t)dc_val, dc_val);
+ }
+ } else {
+ int is_dc_yuv = get_is_dc_yuv(str);
+ int model_bits_y = image->model_dc.bits[0];
+ int model_bits_uv = image->model_dc.bits[1];
+ uint32_t dc_val_v;
+ uint32_t dc_val_u;
+ uint32_t dc_val_y;
+
+ assert(image->num_channels == 3);
+ DEBUG(" MB_DC: IS_DC_YUV=0x%x, model_bits[0]=%d, model_bits[1]=%d\n",
+ is_dc_yuv, model_bits_y, model_bits_uv);
+
+ if (is_dc_yuv&4)
+ lap_mean[0] += 1;
+ dc_val_y = r_DEC_DC(image, str, tx, ty, mx, my,
+ model_bits_y, 0/*chroma_flag==FALSE*/,
+ is_dc_yuv&4);
+
+ if (is_dc_yuv&2)
+ lap_mean[1] += 1;
+ dc_val_u = r_DEC_DC(image, str, tx, ty, mx, my,
+ model_bits_uv, 1/*chroma_flag==TRUE*/,
+ is_dc_yuv&2);
+
+ if (is_dc_yuv&1)
+ lap_mean[1] += 1;
+ dc_val_v = r_DEC_DC(image, str, tx, ty, mx, my,
+ model_bits_uv, 1/*chroma_flag==TRUE*/,
+ is_dc_yuv&1);
+
+ MACROBLK_CUR_DC(image,0,tx, mx) = dc_val_y;
+ MACROBLK_CUR_DC(image,1,tx, mx) = dc_val_u;
+ MACROBLK_CUR_DC(image,2,tx, mx) = dc_val_v;
+ DEBUG(" dc_val at t=[%u %u], m=[%u %u] == %d (0x%08x), %d (0x%08x), %d (0x%08x)\n",
+ tx, ty, mx, my, (int)dc_val_y, dc_val_y, (int)dc_val_u, dc_val_u, (int)dc_val_v, dc_val_v);
+ }
+
+ /* */
+ DEBUG(" MB_DC: UpdateModelMB: lap_mean={%u %u}\n", lap_mean[0], lap_mean[1]);
+ _jxr_UpdateModelMB(image, lap_mean, &image->model_dc, 0/*DC*/);
+ if (_jxr_ResetContext(image, tx, mx)) {
+ DEBUG(" MB_DC: Reset Context\n");
+ /* AdaptDC */
+ _jxr_AdaptVLCTable(image, AbsLevelIndDCLum);
+ _jxr_AdaptVLCTable(image, AbsLevelIndDCChr);
+ }
+ DEBUG(" MB_DC DONE tile=[%u %u] mb=[%u %u]\n", tx, ty, mx, my);
+}
+
+/*
+* When the LP value is input from the stream, it is delivered into
+* the target array based on a scan order. The "lopass_scanorder"
+* array maps the list of LP values (actually the position in the
+* list) to the location in the scan. Thus the scan order places the
+* value into the lpinput array.
+*
+* A property of the lpinput is that it is sparse. The adpative scan
+* order tries to adapt the scan order so that the most frequent value
+* is pressed to the beginning of the input stream. It does this by
+* counting the arrival of each value, and bubbling frequent values
+* forward.
+*
+* Note in the code below that the "i" value ranges from 1-16 but the
+* tables are numbered from 0-15. Thus "i-1" is used to index tables.
+*
+* Note that the scanorder is adapted while we go, but the only
+* adjustment is to swap the current position with the previous. Thus,
+* it is not possible to effect the current pass with the adaptation.
+*/
+static void AdaptiveLPScan(jxr_image_t image, int lpinput_n[], int i, int value)
+{
+ int k;
+ assert(i > 0);
+ k = image->lopass_scanorder[i-1];
+ lpinput_n[k] = value;
+ image->lopass_scantotals[i-1] += 1;
+ if (i>1 && image->lopass_scantotals[i-1] > image->lopass_scantotals[i-2]) {
+ SWAP(image->lopass_scantotals[i-1], image->lopass_scantotals[i-2]);
+ SWAP(image->lopass_scanorder[i-1], image->lopass_scanorder[i-2]);
+ }
+}
+
+void _jxr_r_MB_LP(jxr_image_t image, struct rbitstream*str,
+ int alpha_flag,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my)
+{
+ static const int transpose420[4] = {0, 2,
+ 1, 3 };
+ static const int transpose422[8] = {0, 2, 1, 3, 4, 6, 5, 7};
+ int LPInput[8][16];
+ int idx;
+ int model_bits;
+ int lap_mean[2];
+ int ndx;
+ int full_planes;
+ int cbplp;
+
+ for (idx = 0 ; idx < 8 ; idx += 1) {
+ int k;
+ for (k = 0 ; k < 16 ; k += 1)
+ LPInput[idx][k] = 0;
+ }
+
+ lap_mean[0] = 0;
+ lap_mean[1] = 0;
+
+ DEBUG(" MB_LP tile=[%u %u] mb=[%u %u] bitpos=%zu\n",
+ tx, ty, mx, my, _jxr_rbitstream_bitpos(str));
+
+ if (_jxr_InitContext(image, tx, ty, mx, my)) {
+ DEBUG(" Init contexts\n");
+ _jxr_InitializeCountCBPLP(image);
+ _jxr_InitLPVLC(image);
+ _jxr_InitializeAdaptiveScanLP(image);
+ _jxr_InitializeModelMB(&image->model_lp, 1/*LP*/);
+ }
+
+ if (_jxr_ResetTotals(image, mx)) {
+ _jxr_ResetTotalsAdaptiveScanLP(image);
+ }
+
+ full_planes = image->num_channels;
+ if (image->use_clr_fmt==2 || image->use_clr_fmt==1)
+ full_planes = 2;
+
+ /* The CBPLP signals whether any non-zero coefficients are
+ present in the LP band for this macroblock. It is a bitmask
+ with a bit for each channel. So for example, YONLY, which
+ has 1 channel, has a 1-bit cbplp. */
+
+ cbplp = 0;
+ /* if CLR_FMT is YUV420, YUV422 or YUV444... */
+ if (image->use_clr_fmt==1 || image->use_clr_fmt==2 || image->use_clr_fmt==3) {
+ int max = full_planes * 4 - 5;
+
+ DEBUG(" MB_LP: Calculate YUV CBP using CountZeroCBPLP=%d, CountMaxCBPLP=%d bitpos=%zu\n",
+ image->count_zero_CBPLP, image->count_max_CBPLP, _jxr_rbitstream_bitpos(str));
+
+ if (image->count_zero_CBPLP <= 0 || image->count_max_CBPLP < 0) {
+ int cbp_yuv_lp1 = dec_cbp_yuv_lp1(image, str);
+ if (image->count_max_CBPLP < image->count_zero_CBPLP)
+ cbplp = max - cbp_yuv_lp1;
+ else
+ cbplp = cbp_yuv_lp1;
+ } else {
+ uint32_t cbp_yuv_lp2 = _jxr_rbitstream_uintN(str, full_planes);
+ cbplp = cbp_yuv_lp2;
+ }
+ _jxr_UpdateCountCBPLP(image, cbplp, max);
+
+ } else {
+ int idx;
+ cbplp = 0;
+ for (idx = 0 ; idx < image->num_channels ; idx += 1) {
+ int cbp_ch_lp = _jxr_rbitstream_uint1(str);
+ cbplp |= cbp_ch_lp << idx;
+ }
+ }
+
+ DEBUG(" MB_LP: cbplp = 0x%x (full_planes=%u)\n", cbplp, full_planes);
+
+ for (ndx = 0 ; ndx < full_planes ; ndx += 1) {
+ int idx;
+ const int chroma_flag = ndx>0? 1 : 0;
+ int num_nonzero = 0;
+
+ DEBUG(" MB_LP: process full_plane %u, CBPLP for plane=%d, bitpos=%zu\n",
+ ndx, (cbplp>>ndx)&1, _jxr_rbitstream_bitpos(str));
+ if ((cbplp>>ndx) & 1) {
+ /* If the CBPLP bit is set for this plane, then we
+ have parsing to do. Decode the (15) coeffs and
+ arrange them for use in the MB. */
+ int RLCoeffs[32] = {0};
+ int location = 1;
+ for (idx = 0 ; idx < 32 ; idx += 1)
+ RLCoeffs[idx] = 0;
+
+ /* if CLR_FMT is YUV420 or YUV422 */
+ if (image->use_clr_fmt==1/*YUV420*/ && chroma_flag)
+ location = 10;
+ if (image->use_clr_fmt==2/*YUV422*/ && chroma_flag)
+ location = 2;
+
+ num_nonzero = r_DECODE_BLOCK(image, str,
+ chroma_flag, RLCoeffs, 1/*LP*/, location);
+ DEBUG(" : num_nonzero = %d\n", num_nonzero);
+ assert(num_nonzero <= 16);
+
+ if ((image->use_clr_fmt==1 || image->use_clr_fmt==2) && chroma_flag) {
+ static const int remap_arr[] = {4, 1, 2, 3, 5, 6, 7};
+ int temp[14];
+ int idx;
+ int k, i;
+ int count_chr;
+ int remap_off;
+ for (idx = 0 ; idx < 14 ; idx += 1)
+ temp[idx] = 0;
+
+ remap_off = 0;
+ if (image->use_clr_fmt==1/*YUV420*/)
+ remap_off = 1;
+
+ count_chr = 14;
+ if (image->use_clr_fmt==1/*YUV420*/)
+ count_chr = 6;
+
+ i = 0;
+ for (k = 0; k < num_nonzero; k+=1) {
+ i += RLCoeffs[k*2+0];
+ temp[i] = RLCoeffs[k*2+1];
+ i += 1;
+ }
+ for (k = 0; k < count_chr; k+=1) {
+ int remap = remap_arr[(k>>1) + remap_off];
+ int plane = (k&1) + 1;
+ if (image->use_clr_fmt==1)
+ remap = transpose420[remap];
+ if (image->use_clr_fmt==2)
+ remap = transpose422[remap];
+ LPInput[plane][remap] = temp[k];
+ }
+#if defined(DEBUG)
+ {
+ int k;
+ DEBUG(" RLCoeffs[ndx=%d] ==", ndx);
+ for (k = 0 ; k<(num_nonzero*2); k+=2) {
+ DEBUG(" %d/0x%x", RLCoeffs[k+0], RLCoeffs[k+1]);
+ }
+ DEBUG("\n");
+ DEBUG(" temp ==");
+ for (k = 0 ; k<14; k+=1) {
+ DEBUG(" 0x%x", temp[k]);
+ }
+ DEBUG("\n");
+ }
+#endif
+ } else {
+ /* "i" is the current position in the LP
+ array. It is adjusted based in the run
+ each time around. This implines that the
+ run value is the number of 0 elements in
+ the LP array between non-zero values. */
+ int k, i = 1;
+ for (k = 0; k < num_nonzero; k+=1) {
+ i += RLCoeffs[k*2];
+ AdaptiveLPScan(image, LPInput[ndx], i, RLCoeffs[k*2+1]);
+ i += 1;
+ }
+ }
+ }
+
+#if defined(DEBUG)
+ if (image->use_clr_fmt == 2/*YUV422*/) {
+ int k;
+ DEBUG(" lp val[ndx=%d] before refine ==", ndx);
+ for (k = 1 ; k<8; k+=1) {
+ DEBUG(" 0x%x/0x%x", LPInput[1][k], LPInput[2][k]);
+ }
+ DEBUG("\n");
+
+ } else if (image->use_clr_fmt == 1/*YUV420*/) {
+ int k;
+ DEBUG(" lp val[ndx=%d] before refine ==", ndx);
+ for (k = 1 ; k<4; k+=1) {
+ DEBUG(" 0x%x/0x%x", LPInput[1][k], LPInput[2][k]);
+ }
+ DEBUG("\n");
+
+ } else {
+ int k;
+ DEBUG(" lp val[ndx=%d] before refine ==", ndx);
+ for (k = 1 ; k<16; k+=1) {
+ DEBUG(" 0x%x", LPInput[ndx][k]);
+ }
+ DEBUG("\n");
+ DEBUG(" adapted scan order ==");
+ for (k = 0 ; k<15; k+=1) {
+ DEBUG(" %2d", image->lopass_scanorder[k]);
+ }
+ DEBUG("\n");
+ DEBUG(" adapted scan totals ==");
+ for (k = 0 ; k<15; k+=1) {
+ DEBUG(" %2d", image->lopass_scantotals[k]);
+ }
+ DEBUG("\n");
+ }
+#endif
+
+ model_bits = image->model_lp.bits[chroma_flag];
+ lap_mean[chroma_flag] += num_nonzero;
+ DEBUG(" MB_LP: start refine, model_bits=%d, bitpos=%zu\n",
+ model_bits, _jxr_rbitstream_bitpos(str));
+ if (model_bits) {
+ static const int transpose444[16] = { 0, 4, 8,12,
+ 1, 5, 9,13,
+ 2, 6,10,14,
+ 3, 7,11,15 };
+ if (chroma_flag == 0) {
+ int k;
+ for (k=1 ;k<16; k+=1) {
+ int k_ptr = transpose444[k];
+ LPInput[ndx][k_ptr] = r_REFINE_LP(str, LPInput[ndx][k_ptr], model_bits);
+ }
+ } else {
+ int k;
+ switch (image->use_clr_fmt) {
+ case 1: /* YUV420 */
+ for (k=1 ; k<4; k+=1) {
+ int k_ptr = transpose420[k];
+ LPInput[1][k_ptr] = r_REFINE_LP(str, LPInput[1][k_ptr], model_bits);
+ LPInput[2][k_ptr] = r_REFINE_LP(str, LPInput[2][k_ptr], model_bits);
+ }
+ break;
+ case 2: /* YUV422 */
+ for (k=1 ; k<8; k+=1) {
+ int k_ptr = transpose422[k];
+ DEBUG(" MP_LP: Refine LP_Input[1/2][%d] = 0x%x/0x%x bitpos=%zu\n",
+ k_ptr, LPInput[1][k_ptr], LPInput[2][k_ptr],
+ _jxr_rbitstream_bitpos(str));
+ LPInput[1][k_ptr] = r_REFINE_LP(str, LPInput[1][k_ptr], model_bits);
+ LPInput[2][k_ptr] = r_REFINE_LP(str, LPInput[2][k_ptr], model_bits);
+ }
+ break;
+ default: /* All others */
+ for (k=1 ;k<16; k+=1) {
+ int k_ptr = transpose444[k];
+ LPInput[ndx][k_ptr] = r_REFINE_LP(str, LPInput[ndx][k_ptr], model_bits);
+ }
+ break;
+ }
+ }
+ }
+
+ /* Stash the calculated LP values into the current
+ MACROBLK strip */
+ if (chroma_flag == 0) {
+ /* All luma planes are simply copied into the macroblk. */
+ int k;
+ DEBUG(" lp val ==");
+ for (k = 1 ; k<16; k+=1) {
+ DEBUG(" 0x%x", LPInput[ndx][k]);
+ MACROBLK_CUR_LP(image, ndx, tx, mx, k-1) = LPInput[ndx][k];
+ }
+ DEBUG("\n");
+ } else {
+ int k;
+ DEBUG(" lp val (ch=%d) ==", ndx);
+ switch (image->use_clr_fmt) {
+ case 1:/* YUV420 */
+ /* The chroma for YUV420 is interleaved. */
+ for (k = 1 ; k < 4 ; k+=1) {
+ DEBUG(" 0x%x/0x%x", LPInput[1][k], LPInput[2][k]);
+ MACROBLK_CUR_LP(image, 1, tx, mx, k-1) = LPInput[1][k];
+ MACROBLK_CUR_LP(image, 2, tx, mx, k-1) = LPInput[2][k];
+ }
+ break;
+ case 2:/* YUV422 */
+ /* The chroma for YUV422 is interleaved. */
+ for (k = 1 ; k < 8 ; k+=1) {
+ DEBUG(" 0x%x/0x%x", LPInput[1][k], LPInput[2][k]);
+ MACROBLK_CUR_LP(image, 1, tx, mx, k-1) = LPInput[1][k];
+ MACROBLK_CUR_LP(image, 2, tx, mx, k-1) = LPInput[2][k];
+ }
+ break;
+ default:
+ for (k = 1 ; k < 16 ; k += 1) {
+ DEBUG(" 0x%x", LPInput[ndx][k]);
+ MACROBLK_CUR_LP(image, ndx, tx, mx, k-1) = LPInput[ndx][k];
+ }
+ break;
+ }
+ DEBUG("\n");
+ }
+ }
+
+ DEBUG(" MB_LP: UpdateModelMB lap_mean={%d, %d}\n", lap_mean[0], lap_mean[1]);
+ _jxr_UpdateModelMB(image, lap_mean, &image->model_lp, 1/*band=LP*/);
+ if (_jxr_ResetContext(image, tx, mx)) {
+ DEBUG(" AdaptLP at the end of mx=%d (my=%d, ndx=%u)\n", mx, my, ndx);
+ _jxr_AdaptLP(image);
+ }
+
+ DEBUG(" MB_LP DONE tile=[%u %u] mb=[%u %u]\n", tx, ty, mx, my);
+}
+
+/*
+* This decides the MBCBP for the macroblock. This value is then used
+* by the MB_HP to know how to decide the HP values for the macroblock.
+*/
+int _jxr_r_MB_CBP(jxr_image_t image, struct rbitstream*str, int alpha_flag,
+ unsigned tx, unsigned ty, unsigned mx, unsigned my)
+{
+ static const int flc_table[] = {0, 2, 1, 2, 2, 0};
+ static const int off_table[] = {0, 4, 2, 8, 12, 1};
+ static const int out_table[] = {
+ 0, 15, 3, 12,
+ 1, 2, 4, 8,
+ 5, 6, 9, 10,
+ 7, 11, 13, 14 };
+
+ int diff_cbp[MAX_CHANNELS];
+ int idx;
+ int chan;
+ int channels;
+
+ for (idx = 0 ; idx < MAX_CHANNELS ; idx += 1)
+ diff_cbp[idx] = 0;
+
+ DEBUG(" MB_CBP tile=[%u %u] mb=[%u %u] bitpos=%zu\n",
+ tx, ty, mx, my, _jxr_rbitstream_bitpos(str));
+
+ if (_jxr_InitContext(image, tx, ty, mx, my)) {
+ DEBUG(" MB_CBP: InitContext\n");
+ /* This happens only at the top left edge of the tile. */
+ _jxr_InitCBPVLC(image);
+ }
+
+ /* "Channels" is not quite the same as "planes". For the
+ purposes of CBP parsing, a color image has 1 channel. */
+ channels = 1;
+ if (image->use_clr_fmt==4/*YUVK*/ || image->use_clr_fmt==6/*NCOMPONENT*/)
+ channels = image->num_channels;
+
+ /* This "for" loop decides not the code block pattern itself,
+ but the encoded difference values. These are then added to
+ the predicted values that are calculated later to make the
+ actual MBCBP values. */
+ for (chan = 0 ; chan < channels ; chan += 1) {
+ struct adaptive_vlc_s*vlc = image->vlc_table + DecNumCBP;
+ int num_cbp = get_num_cbp(str, vlc);
+ int blk;
+ static const int Num_CBP_Delta[5] = {0, -1, 0, 1, 1};
+ int cbp;
+
+ DEBUG(" MB_CBP: Decode CBP for channel %d bitpos=%zu\n", chan, _jxr_rbitstream_bitpos(str));
+
+ assert(vlc->deltatable == 0 && num_cbp < 5);
+ vlc->discriminant += Num_CBP_Delta[num_cbp];
+
+ DEBUG(" MB_CBP: Got num_cbp=%d, start REFINE_CBP at bitpos=%zu\n",
+ num_cbp, _jxr_rbitstream_bitpos(str));
+
+ cbp = r_REFINE_CBP(str, num_cbp);
+
+ DEBUG(" MB_CBP: Refined CBP=0x%x (num=%d)\n", cbp, num_cbp);
+
+ /* The cbp is a "block present" bit hask for a group of
+ 4 blocks. This is used to inform the loop below that
+ then tries to fill discern the 4 bits for the range
+ enabled by this first level cbp. For example, if
+ cbp=0x5, then the 16 diff_cbp values are 0x0?0? where
+ the ? nibbles are yet to be resolved by the loop
+ below. */
+
+ for (blk = 0 ; blk < 4 ; blk += 1) {
+ int code;
+ int val;
+ int blkcbp;
+ int num_blkcbp;
+
+ if ( (cbp & (1<<blk)) == 0 )
+ continue;
+
+ vlc = image->vlc_table + DecNumBlkCBP;
+ DEBUG(" MB_CBP: block=%d Use DecNumBlkCBP table=%d, discriminant=%d, bitpos=%zu\n",
+ blk, vlc->table, vlc->discriminant, _jxr_rbitstream_bitpos(str));
+
+ num_blkcbp = get_num_blkcbp(image, str, vlc);
+
+ assert(vlc->deltatable == 0);
+
+ if (image->use_clr_fmt==0 || image->use_clr_fmt==4 || image->use_clr_fmt==6) {
+ static const int Num_BLKCBP_Delta5[5] = {0, -1, 0, 1, 1};
+ assert(num_blkcbp < 5);
+ vlc->discriminant += Num_BLKCBP_Delta5[num_blkcbp];
+ } else {
+ static const int Num_BLKCBP_Delta9[9] = {2, 2, 1, 1, -1, -2, -2, -2, -3};
+ assert(num_blkcbp < 9);
+ vlc->discriminant += Num_BLKCBP_Delta9[num_blkcbp];
+ }
+
+ DEBUG(" MB_CBP: NUM_BLKCBP=%d, discriminant becomes=%d, \n",
+ num_blkcbp, vlc->discriminant);
+
+ val = num_blkcbp + 1;
+
+ blkcbp = 0;
+
+ /* Should only be true if this is chroma data. */
+ if (val >= 6) {
+ int chr_cbp = get_value_012(str);
+ blkcbp = 0x10 * (chr_cbp+1);
+ if (val >= 9) {
+ int val_inc = get_value_012(str);
+ val += val_inc;
+ }
+ DEBUG(" MB_CBP: iVal=%d, CHR_CBP=%x\n", val, chr_cbp);
+ val -= 6;
+ }
+ assert(val < 6);
+
+ code = off_table[val];
+ if (flc_table[val]) {
+ code += _jxr_rbitstream_uintN(str, flc_table[val]);
+ }
+
+ assert(code < 16);
+ blkcbp += out_table[code];
+
+ DEBUG(" MB_CBP: NUM_BLKCBP=%d, iCode=%d\n", num_blkcbp, code);
+ DEBUG(" MB_CBP: blkcbp=0x%x for chunk blk=%d\n", blkcbp, blk);
+
+ /* blkcbp is done. Now calculate the
+ diff_cbp. How this is done (and how many
+ there are) depend on the color format. */
+
+ switch (image->use_clr_fmt) {
+ case 3: /*YUV444*/
+ diff_cbp[0] |= (blkcbp&0xf) << (blk * 4);
+ if (blkcbp & 0x10) {
+ int num_ch_blk = get_num_ch_blk(str);
+ int cbp_chr = r_REFINE_CBP(str, num_ch_blk+1);
+ DEBUG(" MB_CBP: Refined CBP_U=0x%x (num=%d)\n", cbp_chr, num_ch_blk);
+ diff_cbp[1] |= cbp_chr << (blk*4);
+ }
+ if (blkcbp & 0x20) {
+ int num_ch_blk = get_num_ch_blk(str);
+ int cbp_chr = r_REFINE_CBP(str, num_ch_blk+1);
+ DEBUG(" MB_CBP: Refined CBP_V=0x%x (num=%d)\n", cbp_chr, num_ch_blk);
+ diff_cbp[2] |= cbp_chr << (blk*4);
+ }
+ break;
+
+ case 2: /*YUV422*/
+ diff_cbp[0] |= (blkcbp&0xf) << (blk*4);
+ if (blkcbp & 0x10) {
+ const int shift[4] = {0, 1, 4, 5};
+ int cbp_ch_blk = get_value_012(str);
+ int cbp_chr = shift[cbp_ch_blk+1];
+ diff_cbp[1] |= cbp_chr << shift[blk];
+ DEBUG(" MB_CBP: Refined CBP_U=0x%x (cbp_ch_blk=%d, blk=%d)\n",
+ diff_cbp[1], cbp_ch_blk, blk);
+ }
+ if (blkcbp & 0x20) {
+ const int shift[4] = {0, 1, 4, 5};
+ int cbp_ch_blk = get_value_012(str);
+ int cbp_chr = shift[cbp_ch_blk+1];
+ diff_cbp[2] |= cbp_chr << shift[blk];
+ DEBUG(" MB_CBP: Refined CBP_V=0x%x (cbp_ch_blk=%d, blk=%d)\n",
+ diff_cbp[2], cbp_ch_blk, blk);
+ }
+ break;
+
+ case 1: /*YUV420*/
+ diff_cbp[0] |= (blkcbp & 0xf) << (blk*4);
+ diff_cbp[1] |= ((blkcbp >> 4) & 1) << blk;
+ diff_cbp[2] += ((blkcbp >> 5) & 1) << blk;
+ break;
+
+ default:
+ diff_cbp[chan] |= blkcbp << (blk*4);
+ break;
+ }
+ }
+ DEBUG(" MB_CBP: chan=%d, num_cbp=%d, cbp=0x%1x\n", chan, num_cbp, cbp);
+ }
+
+#if defined(DETAILED_DEBUG)
+ for (chan = 0 ; chan < image->num_channels ; chan += 1) {
+ DEBUG(" MB_CBP: diff_cbp[%d]=0x%04x\n", chan, diff_cbp[chan]);
+ }
+#endif
+
+ r_PredCBP(image, diff_cbp, tx, ty, mx, my);
+
+ DEBUG(" MB_CBP done tile=[%u %u] mb=[%u %u]\n", tx, ty, mx, my);
+ return 0;
+}
+
+static int r_REFINE_CBP(struct rbitstream*str, int num)
+{
+ switch (num) {
+ case 1:
+ return 1 << _jxr_rbitstream_uint2(str);
+
+ case 2:
+ /*
+ * table value
+ * 00 3
+ * 01 5
+ * 100 6
+ * 101 9
+ * 110 10
+ * 111 12
+ */
+ if (_jxr_rbitstream_uint1(str) == 0) {
+ if (_jxr_rbitstream_uint1(str) == 0)
+ return 3;
+ else
+ return 5;
+ } else { /* 1xx */
+ if (_jxr_rbitstream_uint1(str) == 0) { /* 10x */
+ if (_jxr_rbitstream_uint1(str) == 0)
+ return 6;
+ else
+ return 9;
+ } else { /* 11x */
+ if (_jxr_rbitstream_uint1(str) == 0)
+ return 10;
+ else
+ return 12;
+ }
+ }
+
+ case 3:
+ return 0x0f ^ (1 << _jxr_rbitstream_uint2(str));
+
+ case 4:
+ return 0x0f;
+
+ default:
+ return 0x00;
+ }
+}
+
+
+int _jxr_r_MB_HP(jxr_image_t image, struct rbitstream*str,
+ int alpha_flag,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my)
+{
+ int use_num_channels;
+ int idx;
+ int lap_mean[2];
+ int flex_flag;
+ int mbhp_pred_mode;
+
+ DEBUG(" MB_HP tile=[%u %u] mb=[%u %u] bitpos=%zu\n",
+ tx, ty, mx, my, _jxr_rbitstream_bitpos(str));
+
+ if (_jxr_InitContext(image, tx, ty, mx, my)) {
+ DEBUG(" MB_HP: InitContext\n");
+ /* This happens only at the top left edge of the tile. */
+ _jxr_InitHPVLC(image);
+ _jxr_InitializeAdaptiveScanHP(image);
+ _jxr_InitializeModelMB(&image->model_hp, 2/*band=HP*/);
+ }
+
+ if (_jxr_ResetTotals(image, mx)) {
+ _jxr_ResetTotalsAdaptiveScanHP(image);
+ }
+
+ /* FLEXBITS are embedded in the HP data if there are FLEXBITS
+ present in the bitstream AND we are in SPATIAL (not
+ FREQUENCY) mode. */
+ flex_flag = 1;
+ if (image->bands_present == 1) /* NOFLEXBITS */
+ flex_flag = 0;
+ if (FREQUENCY_MODE_CODESTREAM_FLAG(image) != 0) /* FREQUENCY_MODE */
+ flex_flag = 0;
+
+ lap_mean[0] = 0;
+ lap_mean[1] = 0;
+
+ /* Calculate the MB HP prediction mode. This uses only local
+ information, namely the LP values. */
+ mbhp_pred_mode = r_calculate_mbhp_mode(image, tx, mx);
+ assert(mbhp_pred_mode < 4);
+
+ for (idx = 0 ; idx < image->num_channels; idx += 1) {
+ int chroma_flag = idx>0? 1 : 0;
+ int nblocks = 4;
+ unsigned model_bits;
+ int cbp;
+ int block;
+
+ if (chroma_flag && image->use_clr_fmt==1/*YUV420*/)
+ nblocks = 1;
+ else if (chroma_flag && image->use_clr_fmt==2/*YUV422*/)
+ nblocks = 2;
+
+ model_bits = image->model_hp.bits[chroma_flag];
+ cbp = MACROBLK_CUR_HPCBP(image, idx, tx, mx);
+
+ DEBUG(" MB_HP channel=%d, cbp=0x%x, model_bits=%u MBHPMode=%d\n",
+ idx, cbp, model_bits, mbhp_pred_mode);
+ for (block=0 ; block<(nblocks*4) ; block += 1, cbp >>= 1) {
+ int bpos = block;
+ int num_nonzero;
+ /* Only remap the Y plane of YUV42X data. */
+ if (nblocks == 4)
+ bpos = _jxr_hp_scan_map[block];
+ num_nonzero = r_DECODE_BLOCK_ADAPTIVE(image, str, tx, mx,
+ cbp&1, chroma_flag,
+ idx, bpos, mbhp_pred_mode,
+ model_bits);
+ if (num_nonzero < 0) {
+ DEBUG("ERROR: r_DECODE_BLOCK_ADAPTIVE returned rc=%d\n", num_nonzero);
+ return JXR_EC_ERROR;
+ }
+ if (flex_flag)
+ r_BLOCK_FLEXBITS(image, str, tx, ty, mx, my,
+ idx, bpos, model_bits);
+ lap_mean[chroma_flag] += num_nonzero;
+ }
+
+ }
+
+ use_num_channels = image->num_channels;
+ if (image->use_clr_fmt == 1/*YUV420*/ || image->use_clr_fmt == 2/*YUV422*/)
+ use_num_channels = 1;
+
+ /* Propagate HP predictions only in SPATIAL MODE. If this is
+ FREQUENCY mode, and there is a FLEXBITS pass later, then do
+ *not* do the predictions, leaving them to the FLEXBITS tile. */
+ if (FREQUENCY_MODE_CODESTREAM_FLAG(image) == 0 || image->bands_present == 1) {
+ DEBUG(" MB_HP: propagate hp predictions within MB_HP function\n");
+ for (idx = 0 ; idx < use_num_channels ; idx += 1)
+ _jxr_propagate_hp_predictions(image, idx, tx, mx, mbhp_pred_mode);
+ }
+
+ DEBUG(" MP_HP: lap_mean={%u, %u}, model_hp.bits={%u %u}, model_hp.state={%d %d}\n",
+ lap_mean[0], lap_mean[1],
+ image->model_hp.bits[0], image->model_hp.bits[1],
+ image->model_hp.state[0], image->model_hp.state[1]);
+
+ MACROBLK_CUR(image,0,tx,mx).mbhp_pred_mode = mbhp_pred_mode;
+ MACROBLK_CUR(image,0,tx,mx).hp_model_bits[0] = image->model_hp.bits[0];
+ MACROBLK_CUR(image,0,tx,mx).hp_model_bits[1] = image->model_hp.bits[1];
+
+ _jxr_UpdateModelMB(image, lap_mean, &image->model_hp, 2/*band=HP*/);
+ if (_jxr_ResetContext(image, tx, mx)) {
+ DEBUG(" MB_HP: Run AdaptHP\n");
+ _jxr_AdaptHP(image);
+ }
+
+ DEBUG(" MP_HP: Updated: lap_mean={%u, %u}, model_hp.bits={%u %u}, model_hp.state={%d %d}\n",
+ lap_mean[0], lap_mean[1],
+ image->model_hp.bits[0], image->model_hp.bits[1],
+ image->model_hp.state[0], image->model_hp.state[1]);
+
+ DEBUG(" MB_HP DONE tile=[%u %u] mb=[%u %u]\n", tx, ty, mx, my);
+ return 0;
+}
+
+int _jxr_r_MB_FLEXBITS(jxr_image_t image, struct rbitstream*str,
+ int alpha_flag,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my)
+{
+ int idx;
+ for (idx = 0 ; idx < image->num_channels ; idx += 1) {
+ int chroma_flag = idx>0? 1 : 0;
+ int nblocks = 4;
+ unsigned model_bits;
+ int block;
+ if (chroma_flag && image->use_clr_fmt==1/*YUV420*/)
+ nblocks = 1;
+ else if (chroma_flag && image->use_clr_fmt==2/*YUV422*/)
+ nblocks = 2;
+
+ model_bits = MACROBLK_CUR(image,0,tx,mx).hp_model_bits[chroma_flag];
+
+ for (block=0 ; block<(nblocks*4) ; block += 1) {
+ int bpos = block;
+ /* Only remap the Y plane of YUV42X data. */
+ if (nblocks == 4)
+ bpos = _jxr_hp_scan_map[block];
+
+ r_BLOCK_FLEXBITS(image, str, tx, ty, mx, my,
+ idx, bpos, model_bits);
+ }
+ }
+
+ return 0;
+}
+
+/*
+* Decode a single DC component value from the input stream.
+*/
+static int32_t r_DEC_DC(jxr_image_t image, struct rbitstream*str,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my,
+ int model_bits, int chroma_flag, int is_dc_ch)
+{
+ int32_t dc_val = 0;
+
+ if (is_dc_ch) {
+ dc_val = r_DECODE_ABS_LEVEL(image, str, 0/*DC*/, chroma_flag) -1;
+ DEBUG(" DEC_DC: DECODE_ABS_LEVEL = %u (0x%08x)\n", dc_val, dc_val);
+ }
+
+ /* If there are model_bits, then read them literally from the
+ bitstream and use them as the LSB bits for the DC value. */
+ if (model_bits > 0) {
+ int idx;
+ DEBUG(" DEC_DC: Collect %u model_bits\n", model_bits);
+ for (idx = 0 ; idx < model_bits ; idx += 1) {
+ dc_val <<= 1;
+ dc_val |= _jxr_rbitstream_uint1(str);
+ }
+ }
+
+ /* If the dc_val is non-zero, it may have a sign so decode the
+ sign bit and apply it. */
+ if (dc_val != 0) {
+ int sign_flag = _jxr_rbitstream_uint1(str);
+ DEBUG(" DEC_DC: sign_flag=%s\n", sign_flag? "true":"false");
+ if (sign_flag)
+ dc_val = - dc_val;
+ }
+
+ DEBUG(" DEC_DC: DC value is %d (0x%08x)\n", dc_val, dc_val);
+ return dc_val;
+}
+
+/*
+* This function decodes one sample from one of the bands. The code is
+* the same for any of the bands. The band (and chroma_flag) is only
+* used to select the vlc_table.
+*
+* Note that the chroma_flag is only interpreted as the "chroma_flag"
+* when the band is DC. Otherwise, the chroma_flag argument is taken
+* as the "context" argument described in the specification.
+*/
+static uint32_t r_DECODE_ABS_LEVEL(jxr_image_t image, struct rbitstream*str,
+ int band, int chroma_flag)
+{
+ int vlc_select = _jxr_vlc_select(band, chroma_flag);
+
+ const int remap[] = {2, 3, 4, 6, 10, 14};
+ const int fixed_len[] = {0, 0, 1, 2, 2, 2};
+ uint32_t level;
+
+ int abslevel_index = dec_abslevel_index(image, str, vlc_select);
+ DEBUG(" Use vlc_select = %s (table=%d) to decode level index, bitpos=%zu\n",
+ _jxr_vlc_index_name(vlc_select), image->vlc_table[vlc_select].table,
+ _jxr_rbitstream_bitpos(str));
+ DEBUG(" ABSLEVEL_INDEX = %d\n", abslevel_index);
+
+ image->vlc_table[vlc_select].discriminant += _jxr_abslevel_index_delta[abslevel_index];
+
+ if (abslevel_index < 6) {
+ int fixed = fixed_len[abslevel_index];
+ uint32_t level_ref = 0;
+
+ level = remap[abslevel_index];
+ if (fixed > 0) {
+ int idx;
+ assert(fixed <= 32);
+ for (idx = 0 ; idx < fixed ; idx += 1) {
+ level_ref <<= 1;
+ level_ref |= _jxr_rbitstream_uint1(str);
+ }
+ level += level_ref;
+ }
+ DEBUG(" ABS_LEVEL = 0x%x (fixed = %d, level_ref = %d)\n",
+ level, fixed, level_ref);
+ } else {
+ int fixed = 4 + _jxr_rbitstream_uint4(str);
+ uint32_t level_ref;
+ int idx;
+
+ if (fixed == 19) {
+ fixed += _jxr_rbitstream_uint2(str);
+ if (fixed == 22) {
+ fixed += _jxr_rbitstream_uint3(str);
+ }
+ }
+
+ assert(fixed <= 32);
+
+ level_ref = 0;
+ for (idx = 0 ; idx < fixed ; idx += 1) {
+ level_ref <<= 1;
+ level_ref |= _jxr_rbitstream_uint1(str);
+ }
+ level = 2 + (1 << fixed) + level_ref;
+ DEBUG(" ABS_LEVEL = 0x%x (fixed = %d, level_ref = %d)\n",
+ level, fixed, level_ref);
+ }
+
+ return level;
+}
+
+/*
+* The DECODE_BLOCK decodes the block as run/coefficient pairs. The
+* run is the distance to the next coefficient, and is followed by the
+* coefficient itself. The skipped values are implicitly zeros. A
+* later process takes these pairs including adaptation of their position.
+*/
+int r_DECODE_BLOCK(jxr_image_t image, struct rbitstream*str,
+ int chroma_flag, int coeff[32], int band, int location)
+{
+ int num_nz = 1;
+
+ /* The index is a bit field that encodes three values:
+ * index[0] : 1 means the run to the next coeff is == 0
+ * index[1] : 1 means the next coefficient is >1
+ * index[3:2]: 0 This is the last coefficient
+ * 1 the next non-zero coefficient immediately follows
+ * 2 there are zero coefficients before the next.
+ */
+ int index = r_DECODE_FIRST_INDEX(image, str, chroma_flag, band);
+ int sr = index & 1;
+ int srn = index >> 2;
+ int context = sr & srn;
+ int sign_flag;
+
+ DEBUG(" DECODE_BLOCK chroma_flag=%d, band=%d, location=%d bitpos=%zu\n",
+ chroma_flag, band, location, _jxr_rbitstream_bitpos(str));
+ DEBUG(" first index=0x%x\n", index);
+
+
+ /* Decode the first coefficient. Note that the chroma_flag
+ argument to DECODE_ABS_LEVEL really is supposed to be the
+ context. It is "chroma" for DC values (band==0) and context
+ for LP and HP values. This DECODE_BLOCK is only called for
+ LP and HP blocks. */
+ sign_flag = _jxr_rbitstream_uint1(str);
+ if (index&2)
+ coeff[1] = r_DECODE_ABS_LEVEL(image, str, band, context);
+ else
+ coeff[1] = 1;
+
+ if (sign_flag)
+ coeff[1] = -coeff[1];
+
+ /* Decode the run to the first coefficient. */
+ if (index&1) {
+ coeff[0] = 0;
+ } else {
+ assert( location < 15 );
+ coeff[0] = r_DECODE_RUN(image, str, 15-location);
+ }
+
+ DEBUG(" coeff[0] = %d (run)\n", coeff[0]);
+ DEBUG(" coeff[1] = 0x%x (coeff)\n", coeff[1]);
+
+ location += coeff[0] + 1;
+
+ while (srn != 0) { /* While more coefficients are expected... */
+ sr = srn & 1;
+
+ /* Decode run to the next coefficient. */
+ if (srn & 1) {
+ coeff[num_nz*2] = 0;
+ } else {
+ coeff[num_nz*2] = r_DECODE_RUN(image, str, 15-location);
+ }
+
+ DEBUG(" coeff[%d*2+0] = %d (run)\n", num_nz, coeff[num_nz*2]);
+
+ location += coeff[num_nz*2] + 1;
+
+ /* The index is a bit field that encodes two values:
+ * index[0] : 1 means the run to the next coeff is == 0
+ * index[2:1]: 0 This is the last coefficient
+ * 1 the next non-zero coefficient immediately follows
+ * 2 there are zero coefficients before the next.
+ * The location can clue the DECODE_INDEX that certain
+ * constraints on the possible index values may exist,
+ * and certain restricted tables are used.
+ */
+ index = r_DECODE_INDEX(image, str, location, chroma_flag, band, context);
+ DEBUG(" next index=0x%x\n", index);
+
+ srn = index >> 1;
+ context &= srn;
+
+ /* Decode the next coefficient. */
+ sign_flag = _jxr_rbitstream_uint1(str);
+ if (index & 1)
+ coeff[num_nz*2+1] = r_DECODE_ABS_LEVEL(image, str,
+ band, context);
+ else
+ coeff[num_nz*2+1] = 1;
+
+ if (sign_flag)
+ coeff[num_nz*2+1] = -coeff[num_nz*2+1];
+
+ DEBUG(" coeff[%d*2+1] = 0x%x (coeff)\n", num_nz, coeff[num_nz*2+1]);
+ num_nz += 1;
+ }
+
+ DEBUG(" DECODE_BLOCK done, num_nz=%d\n", num_nz);
+ return num_nz;
+}
+
+static int r_DECODE_FIRST_INDEX(jxr_image_t image, struct rbitstream*str,
+ int chroma_flag, int band)
+{
+ /* VALUE TABLE0
+ * 0 0000 1..
+ * 1 0000 01.
+ * 2 0000 000
+ * 3 0000 001
+ * 4 0010 0..
+ * 5 010. ...
+ * 6 0010 1..
+ * 7 1... ...
+ * 8 0011 0..
+ * 9 0001 ...
+ * 10 0011 1..
+ * 11 011. ...
+ * (Table 59: Note that the first bit is handled as a special
+ * case, so the array only needs to account for the last 6 bits.)
+ */
+ static const unsigned char c0b[64] = {
+ 6, 6, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
+ };
+ static const signed char c0v[64] = {
+ 2, 3, 1, 1, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9,
+ 4, 4, 4, 4, 6, 6, 6, 6, 8, 8, 8, 8, 10,10,10,10,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 11,11,11,11, 11,11,11,11, 11,11,11,11, 11,11,11,11
+ };
+ /* VALUE TABLE1
+ * 0 0010 ..
+ * 1 0001 0.
+ * 2 0000 00
+ * 3 0000 01
+ * 4 0011 ..
+ * 5 010. ..
+ * 6 0001 1.
+ * 7 11.. ..
+ * 8 011. ..
+ * 9 100. ..
+ * 10 0000 1.
+ * 11 101. ..
+ */
+ static const unsigned char c1b[64] = {
+ 6, 6, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
+ };
+ static const signed char c1v[64] = {
+ 2, 3,10,10, 1, 1, 6, 6, 0, 0, 0, 0, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 8, 8, 8, 8, 8, 8, 8, 8,
+ 9, 9, 9, 9, 9, 9, 9, 9, 11,11,11,11, 11,11,11,11,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+ };
+
+ /* VALUE TABLE2
+ * 0 11.. ...
+ * 1 001. ...
+ * 2 0000 000
+ * 3 0000 001
+ * 4 0000 1..
+ * 5 010. ...
+ * 6 0000 010
+ * 7 011. ...
+ * 8 100. ...
+ * 9 101. ...
+ * 10 0000 011
+ * 11 0001 ...
+ */
+ static const unsigned char c2b[128] = {
+ 7, 7, 7, 7, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
+ };
+ static const signed char c2v[128] = {
+ 2, 3, 6,10, 4, 4, 4, 4, 11,11,11,11, 11,11,11,11,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ /* VALUE TABLE3
+ * 0 001. ...
+ * 1 11.. ...
+ * 2 0000 000
+ * 3 0000 1..
+ * 4 0001 0..
+ * 5 010. ...
+ * 6 0000 001
+ * 7 011. ...
+ * 8 0001 1..
+ * 9 100. ...
+ * 10 0000 01.
+ * 11 101. ...
+ */
+ static const unsigned char c3b[128] = {
+ 7, 7, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
+ };
+ static const signed char c3v[128] = {
+ 2, 6,10,10, 3, 3, 3, 3, 4, 4, 4, 4, 8, 8, 8, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 11,11,11,11, 11,11,11,11, 11,11,11,11, 11,11,11,11,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ };
+
+ /* VALUE TABLE4
+ * 0 010. ....
+ * 1 1... ....
+ * 2 0000 001.
+ * 3 0001 ....
+ * 4 0000 010.
+ * 5 011. ....
+ * 6 0000 0000
+ * 7 0010 ....
+ * 8 0000 011.
+ * 9 0011 ....
+ * 10 0000 0001
+ * 11 0000 1...
+ */
+ static const unsigned char c4b[128] = {
+ 7, 7, 6, 6, 6, 6, 6, 6, 4, 4, 4, 4, 4, 4, 4, 4,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
+ };
+ static const signed char c4v[128] = {
+ 6,10, 2, 2, 4, 4, 8, 8, 11,11,11,11, 11,11,11,11,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
+ };
+
+ typedef int deltatable_t[12];
+ const deltatable_t FirstIndexDelta[4] = {
+ { 1, 1, 1, 1, 1, 0, 0,-1, 2, 1, 0, 0 },
+ { 2, 2,-1,-1,-1, 0,-2,-1, 0, 0,-2,-1 },
+ {-1, 1, 0, 2, 0, 0, 0, 0,-2, 0, 1, 1 },
+ { 0, 1, 0, 1,-2, 0,-1,-1,-2,-1,-2,-2 }
+ };
+
+ int delta_table;
+ int delta2table;
+ int vlc_table;
+ int first_index;
+
+ abs_level_vlc_index_t vlc_select = (abs_level_vlc_index_t)0;
+
+ switch (band) {
+ case 1: /* LP */
+ if (chroma_flag)
+ vlc_select = DecFirstIndLPChr;
+ else
+ vlc_select = DecFirstIndLPLum;
+ break;
+ case 2: /* HP */
+ if (chroma_flag)
+ vlc_select = DecFirstIndHPChr;
+ else
+ vlc_select = DecFirstIndHPLum;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ vlc_table = image->vlc_table[vlc_select].table;
+ first_index = 0;
+
+ switch (vlc_table) {
+ case 0:
+ if (_jxr_rbitstream_uint1(str)) {
+ first_index = 7;
+ } else {
+ first_index = _jxr_rbitstream_intE(str, 6, c0b, c0v);
+ }
+ break;
+
+ case 1:
+ first_index = _jxr_rbitstream_intE(str, 6, c1b, c1v);
+ break;
+
+ case 2:
+ first_index = _jxr_rbitstream_intE(str, 7, c2b, c2v);
+ break;
+
+ case 3:
+ first_index = _jxr_rbitstream_intE(str, 7, c3b, c3v);
+ break;
+
+ case 4:
+ if (_jxr_rbitstream_uint1(str)) {
+ first_index = 1;
+ } else {
+ first_index = _jxr_rbitstream_intE(str, 7, c4b, c4v);
+ }
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ delta_table = image->vlc_table[vlc_select].deltatable;
+ delta2table = image->vlc_table[vlc_select].delta2table;
+
+ assert(delta_table < 4);
+ assert(delta2table < 4);
+ assert(first_index < 12);
+ image->vlc_table[vlc_select].discriminant += FirstIndexDelta[delta_table][first_index];
+ image->vlc_table[vlc_select].discriminant2 += FirstIndexDelta[delta2table][first_index];
+ DEBUG(" DECODE_FIRST_INDEX: vlc_select = %s, vlc_table = %d, deltatable/2 = %d/%d, discriminant/2 = %d/%d, first_index=%d\n",
+ _jxr_vlc_index_name(vlc_select), vlc_table,
+ delta_table, delta2table,
+ image->vlc_table[vlc_select].discriminant,
+ image->vlc_table[vlc_select].discriminant2, first_index);
+
+ return first_index;
+}
+
+static int r_DECODE_INDEX(jxr_image_t image, struct rbitstream*str,
+ int location, int chroma_flag, int band, int context)
+{
+ int vlc_select = 0;
+ int vlc_delta;
+ int vlc_delta2;
+ int vlc_table;
+ int index;
+
+ typedef int deltatable_t[6];
+ const deltatable_t Index1Delta[3] = {
+ {-1, 1, 1, 1, 0, 1 },
+ {-2, 0, 0, 2, 0, 0 },
+ {-1,-1, 0, 1,-2, 0 }
+ };
+
+
+ switch (band) {
+ case 1: /* LP */
+ if (chroma_flag)
+ vlc_select = context? DecIndLPChr1 : DecIndLPChr0;
+ else
+ vlc_select = context? DecIndLPLum1 : DecIndLPLum0;
+ break;
+ case 2: /* HP */
+ if (chroma_flag)
+ vlc_select = context? DecIndHPChr1 : DecIndHPChr0;
+ else
+ vlc_select = context? DecIndHPLum1 : DecIndHPLum0;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ index = 0;
+
+ /* If location > 15, then there can't possibly be coefficients
+ after the next, so the encoding will only encode the low
+ bit, that hints the run is zero or not. */
+ if (location > 15) {
+ index = _jxr_rbitstream_uint1(str);
+ DEBUG(" DECODE_INDEX: location=%d, index=%d\n", location, index);
+ return index;
+ }
+
+ /* If location == 15, then this is probably the last
+ coefficient, but there may be more. We do know that there
+ are no zero coefficients before the next (if there is one).
+ Use a fixed table to decode the index with reduced alphabet. */
+ if (location == 15) {
+ /* Table 61
+ * INDEX2 table
+ * 0 0
+ * 2 10
+ * 1 110
+ * 3 111
+ */
+ if (_jxr_rbitstream_uint1(str) == 0)
+ index = 0; /* 0 */
+ else if (_jxr_rbitstream_uint1(str) == 0)
+ index = 2; /* 10 */
+ else if (_jxr_rbitstream_uint1(str) == 0)
+ index = 1; /* 110 */
+ else
+ index = 3; /* 111 */
+ DEBUG(" DECODE_INDEX: location=%d, index=%d\n", location, index);
+ return index;
+ }
+
+ /* For more general cases, use adaptive table selections to
+ decode the full set of index possibilities. */
+ vlc_table = image->vlc_table[vlc_select].table;
+ DEBUG(" DECODE_INDEX: vlc_select = %s, vlc_table = %d chroma_flag=%d\n",
+ _jxr_vlc_index_name(vlc_select), vlc_table, chroma_flag);
+
+ /* Table 60 is implemented in this switch. */
+ switch (vlc_table) {
+ case 0:
+ /* INDEX1 table0
+ * 0 1
+ * 1 00000
+ * 2 001
+ * 3 00001
+ * 4 01
+ * 5 0001
+ */
+ if (_jxr_rbitstream_uint1(str) == 1)
+ index = 0; /* 1 */
+ else if (_jxr_rbitstream_uint1(str) == 1)
+ index = 4; /* 01 */
+ else if (_jxr_rbitstream_uint1(str) == 1)
+ index = 2; /* 001 */
+ else if (_jxr_rbitstream_uint1(str) == 1)
+ index = 5; /* 0001 */
+ else if (_jxr_rbitstream_uint1(str) == 1)
+ index = 3; /* 00001 */
+ else
+ index = 1; /* 00000 */
+ break;
+
+ case 1:
+ /* INDEX1 table1
+ * 0 01
+ * 1 0000
+ * 2 10
+ * 3 0001
+ * 4 11
+ * 5 001
+ */
+ switch (_jxr_rbitstream_uint2(str)) {
+ case 1: /* 01 */
+ index = 0;
+ break;
+ case 2: /* 10 */
+ index = 2;
+ break;
+ case 3: /* 11 */
+ index = 4;
+ break;
+ case 0: /* 00... */
+ if (_jxr_rbitstream_uint1(str) == 1)
+ index = 5; /* 001 */
+ else if (_jxr_rbitstream_uint1(str) == 1)
+ index = 3; /* 0001 */
+ else
+ index = 1; /* 0000 */
+ break;
+ }
+ break;
+
+ case 2:
+ /* INDEX1 table2
+ * 0 0000
+ * 1 0001
+ * 2 01
+ * 3 10
+ * 4 11
+ * 5 001
+ */
+ switch (_jxr_rbitstream_uint2(str)) {
+ case 1: /* 01 */
+ index = 2;
+ break;
+ case 2: /* 10 */
+ index = 3;
+ break;
+ case 3: /* 11 */
+ index = 4;
+ break;
+ case 0: /* 00... */
+ if (_jxr_rbitstream_uint1(str))
+ index = 5; /* 001 */
+ else if (_jxr_rbitstream_uint1(str))
+ index = 1; /* 0001 */
+ else
+ index = 0; /* 0000 */
+ break;
+ }
+ break;
+
+ case 3:
+ /* INDEX1 table3
+ * 0 00000
+ * 1 00001
+ * 2 01
+ * 3 1
+ * 4 0001
+ * 5 001
+ */
+ if (_jxr_rbitstream_uint1(str))
+ index = 3; /* 1 */
+ else if (_jxr_rbitstream_uint1(str))
+ index = 2; /* 01 */
+ else if (_jxr_rbitstream_uint1(str))
+ index = 5; /* 001 */
+ else if (_jxr_rbitstream_uint1(str))
+ index = 4; /* 0001 */
+ else if (_jxr_rbitstream_uint1(str))
+ index = 1; /* 00001 */
+ else
+ index = 0; /* 00000 */
+ break;
+
+ default:
+ assert(0);
+ }
+
+ vlc_delta = image->vlc_table[vlc_select].deltatable;
+ vlc_delta2 = image->vlc_table[vlc_select].delta2table;
+
+ image->vlc_table[vlc_select].discriminant += Index1Delta[vlc_delta][index];
+ image->vlc_table[vlc_select].discriminant2+= Index1Delta[vlc_delta2][index];
+
+ DEBUG(" DECODE_INDEX: vlc_select = %s, deltatable/2 = %d/%d, discriminant/2 becomes %d/%d\n",
+ _jxr_vlc_index_name(vlc_select), vlc_delta, vlc_delta2,
+ image->vlc_table[vlc_select].discriminant,
+ image->vlc_table[vlc_select].discriminant2);
+
+ return index;
+}
+
+static int r_DECODE_RUN(jxr_image_t image, struct rbitstream*str, int max_run)
+{
+ int run;
+
+ if (max_run < 5) {
+ DEBUG(" DECODE_RUN max_run=%d (<5) bitpos=%zu\n",
+ max_run, _jxr_rbitstream_bitpos(str));
+ switch (max_run) {
+ case 1:
+ run = 1;
+ break;
+ case 2:
+ if (_jxr_rbitstream_uint1(str))
+ run = 1;
+ else
+ run = 2;
+ break;
+ case 3:
+ if (_jxr_rbitstream_uint1(str))
+ run = 1;
+ else if (_jxr_rbitstream_uint1(str))
+ run = 2;
+ else
+ run = 3;
+ break;
+ case 4:
+ if (_jxr_rbitstream_uint1(str))
+ run = 1;
+ else if (_jxr_rbitstream_uint1(str))
+ run = 2;
+ else if (_jxr_rbitstream_uint1(str))
+ run = 3;
+ else
+ run = 4;
+ break;
+ }
+
+ } else {
+ static const int RunBin[15] = {-1,-1,-1,-1, 2,2,2, 1,1,1,1, 0,0,0,0 };
+ static const int RunFixedLen[15] = {0,0,1,1,3, 0,0,1,1,2, 0,0,0,0,1 };
+ static const int Remap[15] = {1,2,3,5,7, 1,2,3,5,7, 1,2,3,4,5 };
+ int run_index = 0;
+ int fixed;
+ int index;
+
+ if (_jxr_rbitstream_uint1(str))
+ run_index = 0; /* 1 */
+ else if (_jxr_rbitstream_uint1(str))
+ run_index = 1; /* 01 */
+ else if (_jxr_rbitstream_uint1(str))
+ run_index = 2; /* 001 */
+ else if (_jxr_rbitstream_uint1(str))
+ run_index = 4; /* 0001 */
+ else
+ run_index = 3; /* 0000 */
+
+ DEBUG(" DECODE_RUN max_run=%d, RUN_INDEX=%d\n", max_run, run_index);
+
+ assert(max_run < 15);
+ index = run_index + 5*RunBin[max_run];
+ DEBUG(" DECODE_RUN index=%d\n", index);
+
+ assert(run_index < 15);
+ fixed = RunFixedLen[index];
+ DEBUG(" DECODE_RUN fixed=%d (bitpos=%zu)\n",
+ fixed, _jxr_rbitstream_bitpos(str));
+
+ assert(run_index < 15);
+ run = Remap[index];
+ if (fixed) {
+ run += _jxr_rbitstream_uintN(str, fixed);
+ }
+ }
+
+ DEBUG(" DECODE_RUN max_run=%d, run=%d\n", max_run, run);
+
+ return run;
+}
+
+
+static int r_REFINE_LP(struct rbitstream*str, int coeff, int model_bits)
+{
+ int coeff_refinement = _jxr_rbitstream_uintN(str, model_bits);
+
+ if (coeff > 0) {
+ coeff <<= model_bits;
+ coeff += coeff_refinement;
+ } else if (coeff < 0) {
+ coeff <<= model_bits;
+ coeff -= coeff_refinement;
+ } else {
+ coeff = coeff_refinement;
+ if (coeff) {
+ int sign_flag = _jxr_rbitstream_uint1(str);
+ if (sign_flag)
+ coeff = -coeff;
+ }
+ }
+
+ return coeff;
+}
+
+static void r_PredCBP(jxr_image_t image, int*diff_cbp,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my)
+{
+ int idx;
+
+ if (_jxr_InitContext(image, tx, ty, mx, my)) {
+ _jxr_InitializeCBPModel(image);
+ }
+
+ assert(my == image->cur_my);
+ switch (image->use_clr_fmt) {
+ case 1: /*YUV420*/
+ MACROBLK_CUR_HPCBP(image, 0, tx, mx)
+ = _jxr_PredCBP444(image, diff_cbp, 0, tx, mx, my);
+ MACROBLK_CUR_HPCBP(image, 1, tx, mx)
+ = _jxr_PredCBP420(image, diff_cbp, 1, tx, mx, my);
+ MACROBLK_CUR_HPCBP(image, 2, tx, mx)
+ = _jxr_PredCBP420(image, diff_cbp, 2, tx, mx, my);
+ DEBUG(" PredCBP: Predicted HPCBP[ch=0]: 0x%04x (YUV420)\n",
+ MACROBLK_CUR_HPCBP(image, 0, tx, mx));
+ DEBUG(" PredCBP: Predicted HPCBP[ch=1]: 0x%04x (YUV420)\n",
+ MACROBLK_CUR_HPCBP(image, 1, tx, mx));
+ DEBUG(" PredCBP: Predicted HPCBP[ch=2]: 0x%04x (YUV420)\n",
+ MACROBLK_CUR_HPCBP(image, 2, tx, mx));
+ break;
+ case 2: /*YUV422*/
+ MACROBLK_CUR_HPCBP(image, 0, tx, mx)
+ = _jxr_PredCBP444(image, diff_cbp, 0, tx, mx, my);
+ MACROBLK_CUR_HPCBP(image, 1, tx, mx)
+ = _jxr_PredCBP422(image, diff_cbp, 1, tx, mx, my);
+ MACROBLK_CUR_HPCBP(image, 2, tx, mx)
+ = _jxr_PredCBP422(image, diff_cbp, 2, tx, mx, my);
+ DEBUG(" PredCBP: Predicted HPCBP[ch=0]: 0x%04x (YUV422)\n",
+ MACROBLK_CUR_HPCBP(image, 0, tx, mx));
+ DEBUG(" PredCBP: Predicted HPCBP[ch=1]: 0x%04x (YUV422)\n",
+ MACROBLK_CUR_HPCBP(image, 1, tx, mx));
+ DEBUG(" PredCBP: Predicted HPCBP[ch=2]: 0x%04x (YUV422)\n",
+ MACROBLK_CUR_HPCBP(image, 2, tx, mx));
+ break;
+ default:
+ for (idx = 0; idx<image->num_channels; idx += 1) {
+ MACROBLK_CUR_HPCBP(image, idx, tx, mx)
+ = _jxr_PredCBP444(image, diff_cbp, idx, tx, mx, my);
+ DEBUG(" PredCBP: Predicted HPCBP[ch=%d]: 0x%04x\n",
+ idx, MACROBLK_CUR_HPCBP(image, idx, tx, mx));
+ }
+ break;
+ }
+}
+
+static void AdaptiveHPScan(jxr_image_t image, int hpinput_n[],
+ int i, int value, int MBHPMode)
+{
+ assert(i > 0);
+
+ if (MBHPMode == 1) {
+ int k = image->hipass_ver_scanorder[i-1];
+ image->hipass_ver_scantotals[i-1] += 1;
+ assert(k < 16);
+ hpinput_n[k] = value;
+
+ if ((i>1) && (image->hipass_ver_scantotals[i-1] > image->hipass_ver_scantotals[i-2])) {
+ SWAP(image->hipass_ver_scantotals[i-1], image->hipass_ver_scantotals[i-2]);
+ SWAP(image->hipass_ver_scanorder[i-1], image->hipass_ver_scanorder[i-2]);
+ }
+ } else {
+ int k = image->hipass_hor_scanorder[i-1];
+ image->hipass_hor_scantotals[i-1] += 1;
+ assert(k < 16);
+ hpinput_n[k] = value;
+
+ if ((i>1) && (image->hipass_hor_scantotals[i-1] > image->hipass_hor_scantotals[i-2])) {
+ SWAP(image->hipass_hor_scantotals[i-1], image->hipass_hor_scantotals[i-2]);
+ SWAP(image->hipass_hor_scanorder[i-1], image->hipass_hor_scanorder[i-2]);
+ }
+ }
+}
+
+/*
+* For each block within the macroblk, there are 15 HP values and the
+* DECODE_BLOCK_ADAPTIVE function is called to collect those values.
+*/
+static int r_DECODE_BLOCK_ADAPTIVE(jxr_image_t image, struct rbitstream*str,
+ unsigned tx, unsigned mx,
+ int cbp_flag, int chroma_flag,
+ int channel, int block, int mbhp_pred_mode,
+ unsigned model_bits)
+{
+ int RLCoeffs[32] = {0};
+
+ int num_nonzero = 0;
+ if (cbp_flag) {
+ int idx, k;
+ int hpinput[16];
+ for (k = 0 ; k < 16 ; k += 1)
+ hpinput[k] = 0;
+
+ num_nonzero = r_DECODE_BLOCK(image, str, chroma_flag, RLCoeffs, 2/*HP*/, 1);
+
+ for (idx = 0, k = 1 ; idx < num_nonzero ; idx += 1) {
+ assert(idx < 16);
+ k += RLCoeffs[idx*2];
+ if (k >= 16) {
+ DEBUG("ERROR: r_DECODE_BLOCK returned bogus RLCoeffs table. ch=%d, tx=%u, mx=%u, k=%d\n",
+ channel, tx, mx, k);
+ for (idx = 0 ; idx < num_nonzero ; idx += 1) {
+ DEBUG(" : RLCoeffs[%d] = %d\n", idx*2, RLCoeffs[idx*2]);
+ DEBUG(" : RLCoeffs[%d] = 0x%x\n", idx*2+1, RLCoeffs[idx*2+1]);
+ }
+ return JXR_EC_ERROR;
+ }
+ assert(k < 16);
+ AdaptiveHPScan(image, hpinput, k, RLCoeffs[idx*2+1], mbhp_pred_mode);
+ k += 1;
+ }
+#if defined(DETAILED_DEBUG)
+ {
+ DEBUG(" HP val[tx=%u, mx=%d, block=%d] ==", tx, mx, block);
+ for (k = 1 ; k<16; k+=1) {
+ DEBUG(" 0x%x", hpinput[k]);
+ }
+ DEBUG("\n");
+ DEBUG(" adapted hor scan order (MBHPMode=%d) ==", mbhp_pred_mode);
+ for (k = 0 ; k<15; k+=1) {
+ DEBUG(" %2d", image->hipass_hor_scanorder[k]);
+ }
+ DEBUG("\n");
+ DEBUG(" adapted hor scan totals ==");
+ for (k = 0 ; k<15; k+=1) {
+ DEBUG(" %2d", image->hipass_hor_scantotals[k]);
+ }
+ DEBUG("\n");
+ DEBUG(" adapted ver scan order (MBHPMode=%d) ==", mbhp_pred_mode);
+ for (k = 0 ; k<15; k+=1) {
+ DEBUG(" %2d", image->hipass_ver_scanorder[k]);
+ }
+ DEBUG("\n");
+ DEBUG(" adapted ver scan totals ==");
+ for (k = 0 ; k<15; k+=1) {
+ DEBUG(" %2d", image->hipass_ver_scantotals[k]);
+ }
+ DEBUG("\n");
+ }
+#endif
+ if (SKIP_HP_DATA(image)) {
+ for (idx = 1; idx < 16; idx += 1)
+ MACROBLK_CUR_HP(image, channel, tx, mx, block, idx-1) = 0;
+ } else {
+ for (idx = 1; idx < 16; idx += 1)
+ MACROBLK_CUR_HP(image, channel, tx, mx, block, idx-1) = hpinput[idx] << model_bits;
+ }
+ }
+
+ return num_nonzero;
+}
+
+
+
+static void r_DECODE_FLEX(jxr_image_t image, struct rbitstream*str,
+ unsigned tx, unsigned mx,
+ int ch, unsigned block, unsigned k,
+ unsigned flexbits)
+{
+ /* NOTE: The model_bits shift was already applied, when the HP
+ value was first parsed. */
+ int coeff = MACROBLK_CUR_HP(image, ch, tx, mx, block, k);
+
+ int flex_ref = _jxr_rbitstream_uintN(str, flexbits);
+ DEBUG(" DECODE_FLEX: coeff=0x%08x, flex_ref=0x%08x\n", coeff, flex_ref);
+ if (coeff > 0) {
+ coeff += flex_ref << image->trim_flexbits;
+ } else if (coeff < 0) {
+ coeff -= flex_ref << image->trim_flexbits;
+ } else {
+ if (flex_ref != 0 && _jxr_rbitstream_uint1(str))
+ coeff = (-flex_ref) << image->trim_flexbits;
+ else
+ coeff = (+flex_ref) << image->trim_flexbits;
+ }
+
+ if (! SKIP_FLEX_DATA(image))
+ MACROBLK_CUR_HP(image, ch, tx, mx, block, k) = coeff;
+}
+
+static void r_BLOCK_FLEXBITS(jxr_image_t image, struct rbitstream*str,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my,
+ unsigned ch, unsigned bl, unsigned model_bits)
+{
+ const int transpose444 [16] = {0, 4, 8,12,
+ 1, 5, 9,13,
+ 2, 6,10,14,
+ 3, 7,11,15 };
+ unsigned flexbits_left = model_bits;
+ if (image->trim_flexbits > flexbits_left)
+ flexbits_left = 0;
+ else
+ flexbits_left -= image->trim_flexbits;
+
+ DEBUG(" BLOCK_FLEXBITS: flexbits_left=%u (model=%u, trim=%u) block=%u bitpos=%zu\n",
+ flexbits_left, model_bits, image->trim_flexbits, bl, _jxr_rbitstream_bitpos(str));
+ if (flexbits_left > 0) {
+ int idx;
+ for (idx = 1; idx < 16; idx += 1) {
+ int idx_trans = transpose444[idx];
+ r_DECODE_FLEX(image, str, tx, mx, ch, bl, idx_trans-1, flexbits_left);
+ }
+ }
+ DEBUG(" BLOCK_FLEXBITS done\n");
+}
+
+static int r_calculate_mbhp_mode(jxr_image_t image, int tx, int mx)
+{
+ long strength_hor = 0;
+ long strength_ver = 0;
+ const long orientation_weight = 4;
+
+ /* Add up the LP magnitudes along the top edge */
+ strength_hor += abs(MACROBLK_CUR_LP(image, 0, tx, mx, 0));
+ strength_hor += abs(MACROBLK_CUR_LP(image, 0, tx, mx, 1));
+ strength_hor += abs(MACROBLK_CUR_LP(image, 0, tx, mx, 2));
+
+ /* Add up the LP magnitudes along the left edge */
+ strength_ver += abs(MACROBLK_CUR_LP(image, 0, tx, mx, 3));
+ strength_ver += abs(MACROBLK_CUR_LP(image, 0, tx, mx, 7));
+ strength_ver += abs(MACROBLK_CUR_LP(image, 0, tx, mx, 11));
+
+ switch (image->use_clr_fmt) {
+ case 0: /*YONLY*/
+ case 6: /*NCOMPONENT*/
+ break;
+ case 3: /*YUV444*/
+ case 4: /*YUVK */
+ strength_hor += abs(MACROBLK_CUR_LP(image, 1, tx, mx, 0));
+ strength_hor += abs(MACROBLK_CUR_LP(image, 2, tx, mx, 0));
+ strength_ver += abs(MACROBLK_CUR_LP(image, 1, tx, mx, 3));
+ strength_ver += abs(MACROBLK_CUR_LP(image, 2, tx, mx, 3));
+ break;
+ case 2: /*YUV422*/
+ strength_hor += abs(MACROBLK_CUR_LP(image, 1, tx, mx, 0));
+ strength_hor += abs(MACROBLK_CUR_LP(image, 2, tx, mx, 0));
+ strength_ver += abs(MACROBLK_CUR_LP(image, 1, tx, mx, 1));
+ strength_ver += abs(MACROBLK_CUR_LP(image, 2, tx, mx, 1));
+ strength_hor += abs(MACROBLK_CUR_LP(image, 1, tx, mx, 4));
+ strength_hor += abs(MACROBLK_CUR_LP(image, 2, tx, mx, 4));
+ strength_ver += abs(MACROBLK_CUR_LP(image, 1, tx, mx, 5));
+ strength_ver += abs(MACROBLK_CUR_LP(image, 2, tx, mx, 5));
+ break;
+ case 1: /*YUV420*/
+ strength_hor += abs(MACROBLK_CUR_LP(image, 1, tx, mx, 0));
+ strength_hor += abs(MACROBLK_CUR_LP(image, 2, tx, mx, 0));
+ strength_ver += abs(MACROBLK_CUR_LP(image, 1, tx, mx, 1));
+ strength_ver += abs(MACROBLK_CUR_LP(image, 2, tx, mx, 1));
+ break;
+ default:
+ assert(0);
+ }
+
+ if (strength_hor * orientation_weight < strength_ver)
+ return 0; /* predict from left */
+ if (strength_ver * orientation_weight < strength_hor)
+ return 1; /* predict from top */
+
+ /* There is no strong weight from top or left, so do not
+ bother with prediction. */
+ return 2;
+}
+
+
+/*
+* This function does HP coefficient propagation within a completed
+* macroblock.
+*/
+void _jxr_propagate_hp_predictions(jxr_image_t image, int ch, unsigned tx, unsigned mx,
+ int mbhp_pred_mode)
+{
+ if (mbhp_pred_mode == 0) { /* Prediction left to right */
+ int idx;
+ for (idx = 1 ; idx < 16 ; idx += 1) {
+ if (idx%4 == 0)
+ continue;
+ CHECK3(image->lwf_test, MACROBLK_CUR_HP(image,ch,tx,mx,idx, 3), MACROBLK_CUR_HP(image,ch,tx,mx,idx, 7), MACROBLK_CUR_HP(image,ch,tx,mx,idx, 11));
+ MACROBLK_CUR_HP(image,ch,tx,mx,idx, 3) += MACROBLK_CUR_HP(image,ch,tx,mx,idx-1, 3);
+ MACROBLK_CUR_HP(image,ch,tx,mx,idx, 7) += MACROBLK_CUR_HP(image,ch,tx,mx,idx-1, 7);
+ MACROBLK_CUR_HP(image,ch,tx,mx,idx,11) += MACROBLK_CUR_HP(image,ch,tx,mx,idx-1,11);
+
+#if defined(DETAILED_DEBUG)
+ {
+ int k;
+ DEBUG(" HP val predicted(l)[ch=%d, tx=%u, mx=%d, block=%d] ==", ch, tx, mx, idx);
+ for (k = 1 ; k<16; k+=1) {
+ DEBUG(" 0x%x", MACROBLK_CUR_HP(image,ch,tx,mx,idx,k-1));
+ }
+ DEBUG("\n");
+ }
+#endif
+ }
+ } else if (mbhp_pred_mode == 1) { /* Prediction top to bottom. */
+ int idx;
+ for (idx = 4 ; idx < 16 ; idx += 1) {
+ CHECK3(image->lwf_test, MACROBLK_CUR_HP(image,ch,tx,mx,idx, 0), MACROBLK_CUR_HP(image,ch,tx,mx,idx, 1), MACROBLK_CUR_HP(image,ch,tx,mx,idx, 2));
+ MACROBLK_CUR_HP(image,ch,tx,mx,idx,0) += MACROBLK_CUR_HP(image,ch,tx,mx, idx-4,0);
+ MACROBLK_CUR_HP(image,ch,tx,mx,idx,1) += MACROBLK_CUR_HP(image,ch,tx,mx, idx-4,1);
+ MACROBLK_CUR_HP(image,ch,tx,mx,idx,2) += MACROBLK_CUR_HP(image,ch,tx,mx, idx-4,2);
+#if defined(DETAILED_DEBUG)
+ {
+ int k;
+ DEBUG(" HP val predicted(t)[ch=%d, tx=%u, mx=%d, block=%d] ==", ch, tx, mx, idx);
+ for (k = 1 ; k<16; k+=1) {
+ DEBUG(" 0x%x", MACROBLK_CUR_HP(image,ch,tx,mx,idx,k-1));
+ }
+ DEBUG("\n");
+ }
+#endif
+ }
+ }
+
+ switch (image->use_clr_fmt) {
+ case 1:/*YUV420*/
+ assert(ch == 0);
+ if (mbhp_pred_mode == 0) {
+ int idx;
+ for (idx = 1 ; idx <= 3 ; idx += 2) {
+ CHECK3(image->lwf_test, MACROBLK_CUR_HP(image,1,tx,mx,idx, 3), MACROBLK_CUR_HP(image,1,tx,mx,idx, 7), MACROBLK_CUR_HP(image,1,tx,mx,idx, 11));
+ CHECK3(image->lwf_test, MACROBLK_CUR_HP(image,2,tx,mx,idx, 3), MACROBLK_CUR_HP(image,2,tx,mx,idx, 7), MACROBLK_CUR_HP(image,2,tx,mx,idx, 11));
+ MACROBLK_CUR_HP(image,1,tx,mx,idx,3) += MACROBLK_CUR_HP(image,1,tx,mx,idx-1,3);
+ MACROBLK_CUR_HP(image,2,tx,mx,idx,3) += MACROBLK_CUR_HP(image,2,tx,mx,idx-1,3);
+ MACROBLK_CUR_HP(image,1,tx,mx,idx,7) += MACROBLK_CUR_HP(image,1,tx,mx,idx-1,7);
+ MACROBLK_CUR_HP(image,2,tx,mx,idx,7) += MACROBLK_CUR_HP(image,2,tx,mx,idx-1,7);
+ MACROBLK_CUR_HP(image,1,tx,mx,idx,11)+= MACROBLK_CUR_HP(image,1,tx,mx,idx-1,11);
+ MACROBLK_CUR_HP(image,2,tx,mx,idx,11)+= MACROBLK_CUR_HP(image,2,tx,mx,idx-1,11);
+#if defined(DETAILED_DEBUG)
+ int k;
+ DEBUG(" HP val predicted(l)[ch=1, tx=%u, mx=%d, block=%d] ==", tx, mx, idx);
+ for (k = 1 ; k<16; k+=1) {
+ DEBUG(" 0x%x", MACROBLK_CUR_HP(image,1,tx,mx,idx,k-1));
+ }
+ DEBUG("\n");
+ DEBUG(" HP val predicted(l)[ch=2, tx=%u, mx=%d, block=%d] ==", tx, mx, idx);
+ for (k = 1 ; k<16; k+=1) {
+ DEBUG(" 0x%x", MACROBLK_CUR_HP(image,2,tx,mx,idx,k-1));
+ }
+ DEBUG("\n");
+#endif
+ }
+ } else if (mbhp_pred_mode == 1) {
+ int idx;
+ for (idx = 2; idx <= 3 ; idx += 1) {
+ CHECK3(image->lwf_test, MACROBLK_CUR_HP(image,1,tx,mx,idx, 0), MACROBLK_CUR_HP(image,1,tx,mx,idx, 1), MACROBLK_CUR_HP(image,1,tx,mx,idx, 2));
+ CHECK3(image->lwf_test, MACROBLK_CUR_HP(image,2,tx,mx,idx, 0), MACROBLK_CUR_HP(image,2,tx,mx,idx, 1), MACROBLK_CUR_HP(image,2,tx,mx,idx, 2));
+ MACROBLK_CUR_HP(image,1,tx,mx,idx,0) += MACROBLK_CUR_HP(image,1,tx,mx,idx-2,0);
+ MACROBLK_CUR_HP(image,2,tx,mx,idx,0) += MACROBLK_CUR_HP(image,2,tx,mx,idx-2,0);
+ MACROBLK_CUR_HP(image,1,tx,mx,idx,1) += MACROBLK_CUR_HP(image,1,tx,mx,idx-2,1);
+ MACROBLK_CUR_HP(image,2,tx,mx,idx,1) += MACROBLK_CUR_HP(image,2,tx,mx,idx-2,1);
+ MACROBLK_CUR_HP(image,1,tx,mx,idx,2) += MACROBLK_CUR_HP(image,1,tx,mx,idx-2,2);
+ MACROBLK_CUR_HP(image,2,tx,mx,idx,2) += MACROBLK_CUR_HP(image,2,tx,mx,idx-2,2);
+#if defined(DETAILED_DEBUG)
+ int k;
+ DEBUG(" HP val predicted(t)[ch=1, tx=%u, mx=%d, block=%d] ==", tx, mx, idx);
+ for (k = 1 ; k<16; k+=1) {
+ DEBUG(" 0x%x", MACROBLK_CUR_HP(image,1,tx,mx,idx,k-1));
+ }
+ DEBUG("\n");
+ DEBUG(" HP val predicted(t)[ch=2, tx=%u, mx=%d, block=%d] ==", tx, mx, idx);
+ for (k = 1 ; k<16; k+=1) {
+ DEBUG(" 0x%x", MACROBLK_CUR_HP(image,2,tx,mx,idx,k-1));
+ }
+ DEBUG("\n");
+#endif
+ }
+ }
+ break;
+
+ case 2:/*YUV422*/
+ assert(ch == 0);
+ if (mbhp_pred_mode == 0) {
+ int idx;
+ for (idx = 1 ; idx <= 7 ; idx += 2) {
+ CHECK3(image->lwf_test, MACROBLK_CUR_HP(image,1,tx,mx,idx, 3), MACROBLK_CUR_HP(image,1,tx,mx,idx, 7), MACROBLK_CUR_HP(image,1,tx,mx,idx, 11));
+ CHECK3(image->lwf_test, MACROBLK_CUR_HP(image,2,tx,mx,idx, 3), MACROBLK_CUR_HP(image,2,tx,mx,idx, 7), MACROBLK_CUR_HP(image,2,tx,mx,idx, 11));
+ MACROBLK_CUR_HP(image,1,tx,mx,idx,3) += MACROBLK_CUR_HP(image,1,tx,mx,idx-1,3);
+ MACROBLK_CUR_HP(image,2,tx,mx,idx,3) += MACROBLK_CUR_HP(image,2,tx,mx,idx-1,3);
+ MACROBLK_CUR_HP(image,1,tx,mx,idx,7) += MACROBLK_CUR_HP(image,1,tx,mx,idx-1,7);
+ MACROBLK_CUR_HP(image,2,tx,mx,idx,7) += MACROBLK_CUR_HP(image,2,tx,mx,idx-1,7);
+ MACROBLK_CUR_HP(image,1,tx,mx,idx,11)+= MACROBLK_CUR_HP(image,1,tx,mx,idx-1,11);
+ MACROBLK_CUR_HP(image,2,tx,mx,idx,11)+= MACROBLK_CUR_HP(image,2,tx,mx,idx-1,11);
+#if defined(DETAILED_DEBUG)
+ int k;
+ DEBUG(" HP val predicted(l)[ch=1, tx=%u, mx=%d, block=%d] ==", tx, mx, idx);
+ for (k = 1 ; k<16; k+=1) {
+ DEBUG(" 0x%x", MACROBLK_CUR_HP(image,1,tx,mx,idx,k-1));
+ }
+ DEBUG("\n");
+ DEBUG(" HP val predicted(l)[ch=2, tx=%u, mx=%d, block=%d] ==", tx, mx, idx);
+ for (k = 1 ; k<16; k+=1) {
+ DEBUG(" 0x%x", MACROBLK_CUR_HP(image,2,tx,mx,idx,k-1));
+ }
+ DEBUG("\n");
+#endif
+ }
+ } else if (mbhp_pred_mode == 1) {
+ int idx;
+ for (idx = 2; idx <= 7 ; idx += 1) {
+ CHECK3(image->lwf_test, MACROBLK_CUR_HP(image,1,tx,mx,idx, 0), MACROBLK_CUR_HP(image,1,tx,mx,idx, 1), MACROBLK_CUR_HP(image,1,tx,mx,idx, 2));
+ CHECK3(image->lwf_test, MACROBLK_CUR_HP(image,2,tx,mx,idx, 0), MACROBLK_CUR_HP(image,2,tx,mx,idx, 1), MACROBLK_CUR_HP(image,2,tx,mx,idx, 2));
+ MACROBLK_CUR_HP(image,1,tx,mx,idx,0) += MACROBLK_CUR_HP(image,1,tx,mx,idx-2,0);
+ MACROBLK_CUR_HP(image,2,tx,mx,idx,0) += MACROBLK_CUR_HP(image,2,tx,mx,idx-2,0);
+ MACROBLK_CUR_HP(image,1,tx,mx,idx,1) += MACROBLK_CUR_HP(image,1,tx,mx,idx-2,1);
+ MACROBLK_CUR_HP(image,2,tx,mx,idx,1) += MACROBLK_CUR_HP(image,2,tx,mx,idx-2,1);
+ MACROBLK_CUR_HP(image,1,tx,mx,idx,2) += MACROBLK_CUR_HP(image,1,tx,mx,idx-2,2);
+ MACROBLK_CUR_HP(image,2,tx,mx,idx,2) += MACROBLK_CUR_HP(image,2,tx,mx,idx-2,2);
+#if defined(DETAILED_DEBUG)
+ int k;
+ DEBUG(" HP val predicted(t)[ch=1, tx=%u, mx=%d, block=%d] ==", tx, mx, idx);
+ for (k = 1 ; k<16; k+=1) {
+ DEBUG(" 0x%x", MACROBLK_CUR_HP(image,1,tx,mx,idx,k-1));
+ }
+ DEBUG("\n");
+ DEBUG(" HP val predicted(t)[ch=2, tx=%u, mx=%d, block=%d] ==", tx, mx, idx);
+ for (k = 1 ; k<16; k+=1) {
+ DEBUG(" 0x%x", MACROBLK_CUR_HP(image,2,tx,mx,idx,k-1));
+ }
+ DEBUG("\n");
+#endif
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+/*
+* Code IS_DC_YUV
+* 10 0
+* 001 1
+* 00001 2
+* 0001 3
+* 11 4
+* 010 5
+* 00000 6
+* 011 7
+*/
+static int get_is_dc_yuv(struct rbitstream*str)
+{
+ if (_jxr_rbitstream_uint1(str) == 1) { /* 1... */
+ if (_jxr_rbitstream_uint1(str) == 1) /* 11 */
+ return 4;
+ else /* 10 */
+ return 0;
+ }
+ else {
+ switch (_jxr_rbitstream_uint2(str)) { /* 1... */
+ case 0: /* 000... */
+ if (_jxr_rbitstream_uint1(str) == 1) /* 0001 */
+ return 3;
+ else if (_jxr_rbitstream_uint1(str) == 1) /* 00001 */
+ return 2;
+ else /* 00000 */
+ return 6;
+ case 1: /* 001 */
+ return 1;
+
+ case 2: /* 010 */
+ return 5;
+
+ case 3: /* 011 */
+ return 7;
+ }
+ }
+
+ assert(0); /* Should not get here. */
+ return -1;
+}
+
+/*
+* table0 table1 value
+* 1 1 0
+* 01 000 1
+* 001 001 2
+* 0000 010 3
+* 0001 011 4
+*/
+static int get_num_cbp(struct rbitstream*str, struct adaptive_vlc_s*vlc)
+{
+ assert(vlc->table < 2);
+
+ if (_jxr_rbitstream_uint1(str) == 1)
+ return 0;
+
+ if (vlc->table == 0) {
+ if (_jxr_rbitstream_uint1(str) == 1)
+ return 1;
+ if (_jxr_rbitstream_uint1(str) == 1)
+ return 2;
+ if (_jxr_rbitstream_uint1(str) == 1)
+ return 4;
+ else
+ return 3;
+ } else {
+ uint8_t tmp = _jxr_rbitstream_uint2(str);
+ return tmp + 1;
+ }
+}
+
+static int get_num_blkcbp(jxr_image_t image, struct rbitstream*str,
+struct adaptive_vlc_s*vlc)
+{
+ switch (image->use_clr_fmt) {
+ case 0: /*YONLY*/
+ case 4: /*YUVK*/
+ case 6: /*NCOMPONENT*/
+ /*
+ * table0 table1 value
+ * 1 1 0
+ * 01 000 1
+ * 001 001 2
+ * 0000 010 3
+ * 0001 011 4
+ *
+ * NOTE that this is exactly the same table as for
+ * NUM_CBP above.
+ */
+ return get_num_cbp(str, vlc);
+
+ default:
+ /*
+ * table0 table1 value
+ * 010 1 0
+ * 00000 001 1
+ * 0010 010 2
+ * 00001 0001 3
+ * 00010 000001 4
+ * 1 011 5
+ * 011 00001 6
+ * 00011 0000000 7
+ * 0011 0000001 8
+ */
+ if (vlc->table == 0) {
+ static const unsigned char codeb[32] = {
+ 5, 5, 5, 5, 4, 4, 4, 4,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 1, 1, 1, 1, 1, 1, 1, 1, /* 1xxxx */
+ 1, 1, 1, 1, 1, 1, 1, 1
+ };
+ static const signed char codev[32] = {
+ 1, 3, 4, 7, 2, 2, 8, 8,
+ 0, 0, 0, 0, 6, 6, 6, 6,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5
+ };
+ return _jxr_rbitstream_intE(str, 5, codeb, codev);
+ } else {
+ static const unsigned char codeb[64] = {
+ 6, 6, 5, 5, 4, 4, 4, 4,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1
+ };
+ static const signed char codev[64] = {
+ 7, 4, 6, 6, 3, 3, 3, 3,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ int tmp = _jxr_rbitstream_intE(str, 6, codeb, codev);
+ if (tmp == 7) tmp += _jxr_rbitstream_uint1(str);
+ return tmp;
+ }
+ }
+}
+
+
+
+/*
+* value table0 table1
+* 0 01 1
+* 1 10 01
+* 2 11 001
+* 3 001 0001
+* 4 0001 00001
+* 5 00000 000000
+* 6 00001 000001
+*/
+static const unsigned char abslevel_code0b[64] = {
+ 5, 5, 5, 5, 4, 4, 4, 4, /* 00000x, 00001x, 0001xx */
+ 3, 3, 3, 3, 3, 3, 3, 3, /* 001xxx */
+ 2, 2, 2, 2, 2, 2, 2, 2, /* 01xxxx */
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, /* 10xxxx */
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, /* 11xxxx */
+ 2, 2, 2, 2, 2, 2, 2, 2
+};
+static const signed char abslevel_code0v[64] = {
+ 5, 5, 6, 6, 4, 4, 4, 4,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2
+};
+
+static const unsigned char abslevel_code1b[64] = {
+ 6, 6, 5, 5, 4, 4, 4, 4, /* 000000, 000001, 00001x, 0001xx */
+ 3, 3, 3, 3, 3, 3, 3, 3, /* 001xxx */
+ 2, 2, 2, 2, 2, 2, 2, 2, /* 01xxxx */
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, /* 1xxxxx */
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1
+};
+static const signed char abslevel_code1v[64] = {
+ 5, 6, 4, 4, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static int dec_abslevel_index(jxr_image_t image, struct rbitstream*str, int vlc_select)
+{
+ const unsigned char*codeb = image->vlc_table[vlc_select].table? abslevel_code1b :abslevel_code0b;
+ const signed char*codev = image->vlc_table[vlc_select].table? abslevel_code1v : abslevel_code0v;
+
+ return _jxr_rbitstream_intE(str, 6, codeb, codev);
+}
+
+static int dec_cbp_yuv_lp1(jxr_image_t image, struct rbitstream*str)
+{
+ static const unsigned char codeb[16] = {
+ 1, 1, 1, 1,
+ 1, 1, 1, 1,
+ 3, 3, 4, 4,
+ 4, 4, 4, 4 };
+ static const signed char codev[16] = {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 1, 1, 2, 3,
+ 4, 5, 6, 7 };
+
+ switch (image->use_clr_fmt) {
+ case 3: /* YUV444 */
+ return _jxr_rbitstream_intE(str, 4, codeb, codev);
+ case 1: /* YUV420 */
+ case 2: /* YUV422 */
+ if (_jxr_rbitstream_uint1(str) == 0) {
+ return 0;
+
+ } else if (_jxr_rbitstream_uint1(str) == 0) {
+ return 1;
+
+ } else if (_jxr_rbitstream_uint1(str) == 0) {
+ return 2;
+
+ } else {
+ return 3;
+ }
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+/*
+* Bits Value
+* 1 0
+* 01 1
+* 00 2
+*/
+static int get_value_012(struct rbitstream*str)
+{
+ if (_jxr_rbitstream_uint1(str) == 1)
+ return 0;
+ else if ( _jxr_rbitstream_uint1(str) == 1)
+ return 1;
+ else
+ return 2;
+}
+
+/*
+* Bits Value
+* 1 0
+* 01 1
+* 000 2
+* 001 3
+*/
+static int get_num_ch_blk(struct rbitstream*str)
+{
+ if (_jxr_rbitstream_uint1(str) == 1)
+ return 0;
+ if (_jxr_rbitstream_uint1(str) == 1)
+ return 1;
+ if (_jxr_rbitstream_uint1(str) == 1)
+ return 3;
+ else
+ return 2;
+}
+
+/*
+* $Log: r_parse.c,v $
+* Revision 1.41 2009/05/29 12:00:00 microsoft
+* Reference Software v1.6 updates.
+*
+* Revision 1.40 2009/04/13 12:00:00 microsoft
+* Reference Software v1.5 updates.
+*
+* Revision 1.39 2008/03/24 18:06:56 steve
+* Imrpove DEBUG messages around quantization.
+*
+* Revision 1.38 2008/03/21 18:30:21 steve
+* Get HP Prediction right for YUVK (CMYK)
+*
+* Revision 1.37 2008/03/20 22:39:41 steve
+* Fix various debug prints of QP data.
+*
+* Revision 1.36 2008/03/17 21:48:55 steve
+* CMYK decode support
+*
+* Revision 1.35 2008/03/13 21:23:27 steve
+* Add pipeline step for YUV420.
+*
+* Revision 1.34 2008/03/13 00:07:22 steve
+* Encode HP of YUV422
+*
+* Revision 1.33 2008/03/06 22:47:39 steve
+* Clean up parsing/encoding of QP counts
+*
+* Revision 1.32 2008/03/06 02:05:48 steve
+* Distributed quantization
+*
+* Revision 1.31 2008/03/05 04:04:30 steve
+* Clarify constraints on USE_DC_QP in image plane header.
+*
+* Revision 1.30 2008/03/05 00:31:17 steve
+* Handle UNIFORM/IMAGEPLANE_UNIFORM compression.
+*
+* Revision 1.29 2008/02/28 18:50:31 steve
+* Portability fixes.
+*
+* Revision 1.28 2008/02/26 23:52:44 steve
+* Remove ident for MS compilers.
+*
+* Revision 1.27 2008/02/23 01:55:51 steve
+* CBP REFINE is more complex when CHR is involved.
+*
+* Revision 1.26 2008/02/22 23:01:33 steve
+* Compress macroblock HP CBP packets.
+*
+* Revision 1.25 2008/01/01 01:07:26 steve
+* Add missing HP prediction.
+*
+* Revision 1.24 2007/12/30 00:16:00 steve
+* Add encoding of HP values.
+*
+* Revision 1.23 2007/12/13 18:01:09 steve
+* Stubs for HP encoding.
+*
+* Revision 1.22 2007/12/12 00:37:33 steve
+* Cleanup some debug messages.
+*
+* Revision 1.21 2007/12/06 23:12:41 steve
+* Stubs for LP encode operations.
+*
+* Revision 1.20 2007/12/06 17:54:09 steve
+* UpdateModelMB dump details.
+*
+* Revision 1.19 2007/11/26 01:47:15 steve
+* Add copyright notices per MS request.
+*
+* Revision 1.18 2007/11/21 00:34:30 steve
+* Rework spatial mode tile macroblock shuffling.
+*
+* Revision 1.17 2007/11/20 00:05:47 steve
+* Complex handling of mbhp_pred_mode in frequency dmoe.
+*
+* Revision 1.16 2007/11/19 18:22:34 steve
+* Skip ESCaped FLEXBITS tiles.
+*
+* Revision 1.15 2007/11/16 20:03:57 steve
+* Store MB Quant, not qp_index.
+*
+* Revision 1.14 2007/11/16 17:33:24 steve
+* Do HP prediction after FLEXBITS frequency tiles.
+*
+* Revision 1.13 2007/11/16 00:29:05 steve
+* Support FREQUENCY mode HP and FLEXBITS
+*
+* Revision 1.12 2007/11/14 23:56:17 steve
+* Fix TILE ordering, using seeks, for FREQUENCY mode.
+*
+* Revision 1.11 2007/11/14 00:17:26 steve
+* Fix parsing of QP indices.
+*
+* Revision 1.10 2007/11/13 03:27:23 steve
+* Add Frequency mode LP support.
+*
+* Revision 1.9 2007/11/12 23:21:55 steve
+* Infrastructure for frequency mode ordering.
+*
+* Revision 1.8 2007/11/08 19:38:38 steve
+* Get stub DCONLY compression to work.
+*
+* Revision 1.7 2007/11/01 21:09:40 steve
+* Multiple rows of tiles.
+*
+* Revision 1.6 2007/10/30 21:32:46 steve
+* Support for multiple tile columns.
+*
+* Revision 1.5 2007/09/08 01:01:43 steve
+* YUV444 color parses properly.
+*
+* Revision 1.4 2007/07/30 23:09:57 steve
+* Interleave FLEXBITS within HP block.
+*
+* Revision 1.3 2007/07/24 20:56:28 steve
+* Fix HP prediction and model bits calculations.
+*
+* Revision 1.2 2007/06/07 18:53:06 steve
+* Parse HP coeffs that are all 0.
+*
+* Revision 1.1 2007/06/06 17:19:12 steve
+* Introduce to CVS.
+*
+*/
+
diff --git a/jpegxr/r_strip.c b/jpegxr/r_strip.c
new file mode 100644
index 000000000..856c41ea8
--- /dev/null
+++ b/jpegxr/r_strip.c
@@ -0,0 +1,2774 @@
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+***********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: r_strip.c,v 1.51 2008/03/24 18:06:56 steve Exp $")
+#else
+#ident "$Id: r_strip.c,v 1.51 2008/03/24 18:06:56 steve Exp $"
+#endif
+
+# include "jxr_priv.h"
+# include <limits.h>
+# include <assert.h>
+# include <math.h>
+# include <memory.h>
+
+static void dclphp_shuffle(int*data, int dclp_count);
+static void unblock_shuffle444(int*data);
+static void unblock_shuffle422(int*data);
+static void unblock_shuffle420(int*data);
+
+static void dequantize_up_dclp(jxr_image_t image, int use_my, int ch)
+{
+ int tx, ty = 0;
+ int dc_quant = 0;
+ unsigned int strip;
+ unsigned int i;
+
+ int lp_coeff_count = 16;
+ if (ch > 0) {
+ if (image->use_clr_fmt == 2/*YUV422*/)
+ lp_coeff_count = 8;
+ else if (image->use_clr_fmt == 1/*YUV420*/)
+ lp_coeff_count = 4;
+ }
+
+ strip = use_my -1;
+ for(i=0; i < image->tile_rows; i++)
+ {
+ /* Figure out what ty is */
+ if(strip >= image->tile_row_position[i] && strip <image->tile_row_position[i] + image->tile_row_height[i])
+ {
+ ty = i;
+ break;
+ }
+ }
+
+ /* The current "cur" is now made up into DC coefficients, so
+ we no longer need the strip_up levels. Dequantize them,
+ inverse tranform then and deliver them to output. */
+ for (tx = 0 ; tx < (int) image->tile_columns ; tx += 1) {
+ int mx;
+ if(image->dc_frame_uniform)
+ dc_quant = image->dc_quant_ch[ch];
+ else
+ dc_quant = image->tile_quant[ty *(image->tile_columns) + tx].dc_quant_ch[ch];
+ dc_quant = _jxr_quant_map(image, dc_quant, ch==0? 1 : 0/* iShift for YONLY */);
+
+ for (mx = 0 ; mx < (int) image->tile_column_width[tx] ; mx += 1) {
+ int lp_quant_idx = MACROBLK_UP1_LP_QUANT(image,ch,tx,mx);
+ int k;
+ int lp_quant_use;
+
+ int lp_quant_raw = 0;
+ if(image->lp_frame_uniform)
+ lp_quant_raw = image->lp_quant_ch[ch][lp_quant_idx];
+ else
+ lp_quant_raw = image->tile_quant[ty *(image->tile_columns) + tx].lp_quant_ch[ch][lp_quant_idx];
+
+ lp_quant_use = _jxr_quant_map(image, lp_quant_raw, ch==0? 1 : 0/* iShift for YONLY */);
+ MACROBLK_UP_DC(image,ch,tx,mx) *= dc_quant;
+ CHECK1(image->lwf_test, MACROBLK_CUR_DC(image,ch,tx,mx));
+
+ DEBUG(" Dequantize strip=%d tx=%d MBx=%d ch=%d with lp_quant=%d lp_quant_use=%d\n",
+ use_my-1, tx, mx, ch, lp_quant_raw, lp_quant_use);
+ for (k = 1 ; k < lp_coeff_count ; k += 1)
+ {
+ MACROBLK_UP_LP(image,ch,tx,mx,k-1) *= lp_quant_use;
+ CHECK1(image->lwf_test, MACROBLK_UP_LP(image,ch,tx,mx,k-1));
+ }
+ }
+ }
+
+#if defined(DETAILED_DEBUG)
+ for (tx = 0 ; tx < (int) image->tile_columns ; tx += 1) {
+ int mx;
+ for (mx = 0 ; mx < (int) image->tile_column_width[tx] ; mx += 1) {
+ int jdx;
+ DEBUG(" DC/LP (strip=%3d, tx=%d mbx=%4d, ch=%d) Dequant:", use_my-1, tx, mx, ch);
+ DEBUG(" 0x%08x", MACROBLK_UP_DC(image,ch,tx,mx));
+ for (jdx = 0; jdx < lp_coeff_count-1 ; jdx += 1) {
+ DEBUG(" 0x%08x", MACROBLK_UP_LP(image,ch,tx,mx,jdx));
+ if ((jdx+1)%4 == 3 && jdx != (lp_coeff_count-2))
+ DEBUG("\n%*s:", 48, "");
+ }
+ DEBUG("\n");
+ }
+ }
+#endif
+}
+
+
+static void IPCT_level1_up1(jxr_image_t image, int use_my, int ch)
+{
+ int idx;
+
+ dequantize_up_dclp(image, use_my, ch);
+
+ DEBUG(" DC-LP IPCT transforms (first level) for strip %d channel %d\n", use_my-1, ch);
+
+ /* Reverse transform the DC/LP to 16 DC values. */
+
+ for (idx = 0 ; idx < (int) EXTENDED_WIDTH_BLOCKS(image); idx += 1) {
+ DEBUG(" DC-LP IPCT transforms for mb[%d %d]\n", idx, use_my-1);
+
+ if (ch > 0 && image->use_clr_fmt == 1/*YUV420*/) {
+
+ _jxr_2x2IPCT(image->strip[ch].up1[idx].data+0);
+ _jxr_InvPermute2pt(image->strip[ch].up1[idx].data+1,
+ image->strip[ch].up1[idx].data+2);
+
+ /* Scale up the chroma channel */
+ if (image->scaled_flag) {
+ int jdx;
+ for (jdx = 0 ; jdx < 4 ; jdx += 1)
+ image->strip[ch].up1[idx].data[jdx] *= 2;
+ }
+
+#if defined(DETAILED_DEBUG)
+ DEBUG(" DC/LP (strip=%3d, mbx=%4d, ch=%d) IPCT:", use_my-1, idx, ch);
+ DEBUG(" 0x%08x", MACROBLK_UP_DC(image,ch,0,idx));
+ DEBUG(" 0x%08x", MACROBLK_UP_LP(image,ch,0,idx,0));
+ DEBUG(" 0x%08x", MACROBLK_UP_LP(image,ch,0,idx,1));
+ DEBUG(" 0x%08x", MACROBLK_UP_LP(image,ch,0,idx,2));
+ DEBUG("\n");
+#endif
+ } else if (ch > 0 && image->use_clr_fmt == 2/*YUV422*/) {
+#if defined(DETAILED_DEBUG)
+ int jdx;
+ DEBUG(" DC/LP scaled_flag=%d\n", image->scaled_flag);
+ DEBUG(" DC/LP (strip=%3d, mbx=%4d, ch=%d) Pre-IPCT:", use_my-1, idx, ch);
+ DEBUG(" 0x%08x", MACROBLK_UP_DC(image,ch,0,idx));
+ for (jdx = 0; jdx < 7 ; jdx += 1) {
+ DEBUG(" 0x%08x", MACROBLK_UP_LP(image,ch,0,idx,jdx));
+ if ((jdx+1)%4 == 3 && jdx != 6)
+ DEBUG("\n%*s:", 44, "");
+ }
+ DEBUG("\n");
+#endif
+
+ _jxr_2ptT(image->strip[ch].up1[idx].data+0,
+ image->strip[ch].up1[idx].data+4);
+ _jxr_2x2IPCT(image->strip[ch].up1[idx].data+0);
+ _jxr_2x2IPCT(image->strip[ch].up1[idx].data+4);
+
+ _jxr_InvPermute2pt(image->strip[ch].up1[idx].data+1,
+ image->strip[ch].up1[idx].data+2);
+ _jxr_InvPermute2pt(image->strip[ch].up1[idx].data+5,
+ image->strip[ch].up1[idx].data+6);
+
+#if defined(DETAILED_DEBUG)
+ DEBUG(" DC/LP scaled_flag=%d\n", image->scaled_flag);
+ DEBUG(" DC/LP (strip=%3d, mbx=%4d, ch=%d) scaled:", use_my-1, idx, ch);
+ DEBUG(" 0x%08x", MACROBLK_UP_DC(image,ch,0,idx));
+ for (jdx = 0; jdx < 7 ; jdx += 1) {
+ DEBUG(" 0x%08x", MACROBLK_UP_LP(image,ch,0,idx,jdx));
+ if ((jdx+1)%4 == 3 && jdx != 6)
+ DEBUG("\n%*s:", 42, "");
+ }
+ DEBUG("\n");
+#endif
+ /* Scale up the chroma channel */
+ if (image->scaled_flag) {
+ int jdx;
+ for (jdx = 0 ; jdx < 8 ; jdx += 1)
+ image->strip[ch].up1[idx].data[jdx] *= 2;
+ }
+
+#if defined(DETAILED_DEBUG)
+ DEBUG(" DC/LP scaled_flag=%d\n", image->scaled_flag);
+ DEBUG(" DC/LP (strip=%3d, mbx=%4d, ch=%d) IPCT:", use_my-1, idx, ch);
+ DEBUG(" 0x%08x", MACROBLK_UP_DC(image,ch,0,idx));
+ for (jdx = 0; jdx < 7 ; jdx += 1) {
+ DEBUG(" 0x%08x", MACROBLK_UP_LP(image,ch,0,idx,jdx));
+ if ((jdx+1)%4 == 3 && jdx != 6)
+ DEBUG("\n%*s:", 40, "");
+ }
+ DEBUG("\n");
+#endif
+ } else {
+
+ /* Channel 0 of everything, and Channel-N of full
+ resolution colors, are processed here. */
+ _jxr_4x4IPCT(image->strip[ch].up1[idx].data);
+
+ /* Scale up the chroma channel */
+ if (ch > 0 && image->scaled_flag) {
+ int jdx;
+ for (jdx = 0 ; jdx < 16 ; jdx += 1)
+ image->strip[ch].up1[idx].data[jdx] *= 2;
+ }
+
+#if defined(DETAILED_DEBUG)
+ int jdx;
+ DEBUG(" DC/LP (strip=%3d, mbx=%4d, ch=%d) IPCT:", use_my-1, idx, ch);
+ DEBUG(" 0x%08x", MACROBLK_UP_DC(image,ch,0,idx));
+ for (jdx = 0; jdx < 15 ; jdx += 1) {
+ DEBUG(" 0x%08x", MACROBLK_UP_LP(image,ch,0,idx,jdx));
+ if ((jdx+1)%4 == 3 && jdx != 14)
+ DEBUG("\n%*s:", 40, "");
+ }
+ DEBUG("\n");
+#endif
+ }
+
+ }
+
+}
+
+static void IPCT_level2_up2(jxr_image_t image, int use_my, int ch)
+{
+ int idx;
+
+ for (idx = 0 ; idx < (int) EXTENDED_WIDTH_BLOCKS(image); idx += 1) {
+ int jdx;
+ /* Reshuffle the DCLP with the HP data to get
+ DC-LP stretches in the data stream. */
+ int dclp_count = 16;
+ int hp_quant_raw;
+ int hp_quant;
+
+ if (ch>0 && image->use_clr_fmt == 2/*YUV422*/)
+ dclp_count = 8;
+ else if (ch>0 && image->use_clr_fmt == 1/*YUV420*/)
+ dclp_count = 4;
+
+ dclphp_shuffle(image->strip[ch].up2[idx].data, dclp_count);
+
+ DEBUG(" DC-LP-HP IPCT transforms for (second level) strip %d MBx=%d ch=%d\n",
+ use_my-2, idx, ch);
+
+ hp_quant_raw = MACROBLK_UP2_HP_QUANT(image,ch,0,idx);
+ hp_quant = _jxr_quant_map(image, hp_quant_raw, 1);
+
+ /* IPCT transform to absorb HP band data. */
+ for (jdx = 0 ; jdx < 16*dclp_count ; jdx += 16) {
+ int k;
+#if defined(DETAILED_DEBUG)
+ {
+ int pix;
+ DEBUG(" DC-LP-HP (strip=%3d, mbx=%4d ch=%d, block=%2d) pre-IPCT:",
+ use_my-2, idx, ch, jdx/16);
+ for (pix = 0; pix < 16 ; pix += 1) {
+ DEBUG(" 0x%08x", image->strip[ch].up2[idx].data[jdx+pix]);
+ if (pix%4 == 3 && pix != 15)
+ DEBUG("\n%*s:", 56, "");
+ }
+ DEBUG("\n");
+ }
+#endif
+ DEBUG(" Dequantize strip=%d MBx=%d ch=%d block=%d with hp_quant=%d (raw=%d)\n",
+ use_my-2, idx, ch, jdx/16, hp_quant, hp_quant_raw);
+ for (k = 1 ; k < 16 ; k += 1)
+ {
+ image->strip[ch].up2[idx].data[jdx+k] *= hp_quant;
+ CHECK1(image->lwf_test, image->strip[ch].up2[idx].data[jdx+k]);
+ }
+
+ _jxr_4x4IPCT(image->strip[ch].up2[idx].data+jdx);
+#if defined(DETAILED_DEBUG)
+ {
+ int pix;
+ DEBUG(" DC-LP-HP (strip=%3d, mbx=%4d ch=%d block=%2d) IPCT:",
+ use_my-2, idx, ch, jdx/16);
+ for (pix = 0; pix < 16 ; pix += 1) {
+ DEBUG(" 0x%08x", image->strip[ch].up2[idx].data[jdx+pix]);
+ if (pix%4 == 3 && pix != 15)
+ DEBUG("\n%*s:", 51, "");
+ }
+ DEBUG("\n");
+ }
+#endif
+ }
+
+ }
+}
+
+#define TOP_Y(y) ( y == image->tile_row_position[ty])
+#define BOTTOM_Y(y) ( y == image->tile_row_position[ty] + image->tile_row_height[ty] - 1)
+#define LEFT_X(idx) ( idx == 0)
+#define RIGHT_X(idx) ( idx == image->tile_column_width[tx] -1 )
+
+
+static void overlap_level1_up2_444(jxr_image_t image, int use_my, int ch)
+{
+ int tx = 0; /* XXXX */
+ int top_my = use_my - 2;
+ int idx;
+
+ int ty = 0;
+ /* 16 Coeffs per MB */
+ assert(ch == 0 || (image->use_clr_fmt != 2/*YUV422*/ && image->use_clr_fmt !=1/* YUV420*/));
+ assert(use_my >= 2);
+ /* Figure out which tile row the current strip of macroblocks belongs to. */
+ while(top_my > image->tile_row_position[ty]+image->tile_row_height[ty] - 1)
+ ty++;
+
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ /* Top edge */
+ if(top_my == 0 || (image->disableTileOverlapFlag && TOP_Y(top_my) ))
+ {
+ /* If this is the very first strip of blocks, then process the
+ first two scan lines with the smaller 4Overlap filter. */
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ /* Top edge across */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag) || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+ int*tp0 = MACROBLK_UP2(image,ch,tx,idx+0).data;
+ int*tp1 = MACROBLK_UP2(image,ch,tx,idx-1).data; /* Macroblock to the right */
+
+ _jxr_4OverlapFilter(tp1+2, tp1+3, tp0+0, tp0+1);
+ _jxr_4OverlapFilter(tp1+6, tp1+7, tp0+4, tp0+5);
+ }
+ }
+ /* Top left corner */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP2(image,ch,tx,0).data;
+ _jxr_4OverlapFilter(tp0+0, tp0+1, tp0+4, tp0+5);
+ }
+ /* Top right corner */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP2(image,ch,tx,image->tile_column_width[tx]-1).data;
+ _jxr_4OverlapFilter(tp0+2, tp0+3, tp0+6, tp0+7);
+ }
+ }
+
+ /* Bottom edge */
+ if ((top_my+1) == (int) EXTENDED_HEIGHT_BLOCKS(image) || (image->disableTileOverlapFlag && BOTTOM_Y(top_my))) {
+
+ /* This is the last row, so there is no UP below
+ TOP. finish up with 4Overlap filters. */
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ /* Bottom edge across */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag)
+ || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+
+ int*tp0 = MACROBLK_UP2(image,ch,tx,idx+0).data;
+ int*tp1 = MACROBLK_UP2(image,ch,tx,idx-1).data;
+ _jxr_4OverlapFilter(tp1+10, tp1+11, tp0+8, tp0+9);
+ _jxr_4OverlapFilter(tp1+14, tp1+15, tp0+12, tp0+13);
+ }
+ }
+
+ /* Bottom left corner */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP2(image,ch,tx,0).data;
+ _jxr_4OverlapFilter(tp0+8, tp0+9, tp0+12, tp0+13);
+ }
+ /* Bottom right corner */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP2(image,ch,tx,image->tile_column_width[tx]-1).data;
+ _jxr_4OverlapFilter(tp0+10, tp0+11, tp0+14, tp0+15);
+ }
+ }
+
+ for (idx = 0 ; idx < image->tile_column_width[tx] ; idx += 1) {
+ if ((top_my+1) < (int) EXTENDED_HEIGHT_BLOCKS(image)) {
+
+ if ((tx == 0 && idx==0 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && LEFT_X(idx) && !BOTTOM_Y(top_my))) {
+ int*tp0 = MACROBLK_UP2(image,ch,tx,0).data;
+ int*up0 = MACROBLK_UP1(image,ch,tx,0).data;
+
+ /* Left edge Across Vertical MBs */
+ _jxr_4OverlapFilter(tp0+8, tp0+12, up0+0, up0+4);
+ _jxr_4OverlapFilter(tp0+9, tp0+13, up0+1, up0+5);
+ }
+
+ if (((image->tile_column_position[tx] + idx < EXTENDED_WIDTH_BLOCKS(image)-1) && !image->disableTileOverlapFlag ) ||
+ ( image->disableTileOverlapFlag && !RIGHT_X(idx) && !BOTTOM_Y(top_my) )
+ ) {
+ /* This assumes that the DCLP coefficients are the first
+ 16 values in the array, and ordered properly. */
+ int*tp0 = MACROBLK_UP2(image,ch,tx,idx+0).data;
+ int*tp1 = MACROBLK_UP2(image,ch,tx,idx+1).data;
+ int*up0 = MACROBLK_UP1(image,ch,tx,idx+0).data;
+ int*up1 = MACROBLK_UP1(image,ch,tx,idx+1).data;
+
+ /* MB below, right, right-below */
+ _jxr_4x4OverlapFilter(tp0+10, tp0+11, tp1+ 8, tp1+ 9,
+ tp0+14, tp0+15, tp1+12, tp1+13,
+ up0+ 2, up0+ 3, up1+ 0, up1+ 1,
+ up0+ 6, up0+ 7, up1+ 4, up1+ 5);
+ }
+ if((image->tile_column_position[tx] + idx == (int) EXTENDED_WIDTH_BLOCKS(image)-1 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && RIGHT_X(idx) && !BOTTOM_Y(top_my)))
+ {
+ int*tp0 = MACROBLK_UP2(image,ch,tx,image->tile_column_width[tx]-1).data;
+ int*up0 = MACROBLK_UP1(image,ch,tx,image->tile_column_width[tx]-1).data;
+
+ /* Right edge Across Vertical MBs */
+ _jxr_4OverlapFilter(tp0+10, tp0+14, up0+2, up0+6);
+ _jxr_4OverlapFilter(tp0+11, tp0+15, up0+3, up0+7);
+ }
+ }
+ }
+ }
+}
+
+/*
+*/
+
+static void overlap_level1_up2_422(jxr_image_t image, int use_my, int ch)
+{
+ int tx = 0; /* XXXX */
+ int top_my = use_my - 2;
+ int idx;
+
+ int ty = 0;
+ assert(ch > 0 && image->use_clr_fmt == 2/*YUV422*/);
+ assert(use_my >= 2);
+ /* Figure out which tile row the current strip of macroblocks belongs to. */
+ while(top_my > image->tile_row_position[ty]+image->tile_row_height[ty] - 1)
+ ty++;
+
+
+ /* Top edge */
+ if(top_my == 0 || (image->disableTileOverlapFlag && TOP_Y(top_my)))
+ {
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ /* Top Left Corner Difference */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP2(image,ch,tx,0).data;
+ tp0[0] = tp0[0] -tp0[1];
+ CHECK1(image->lwf_test, tp0[0]);
+ }
+ /* Top Right Corner Difference */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *tp0 = MACROBLK_UP2(image,ch,tx,image->tile_column_width[tx]-1).data;
+ tp0[1] = tp0[1] - tp0[0];
+ CHECK1(image->lwf_test, tp0[1]);
+ }
+ }
+ }
+
+
+ /* Bottom edge */
+ if ((top_my+1) == (int) EXTENDED_HEIGHT_BLOCKS(image) || (image->disableTileOverlapFlag && BOTTOM_Y(top_my)))
+ {
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ /* Bottom Left Corner Difference */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP2(image,ch,tx,0).data;
+ tp0[6] = tp0[6] -tp0[7];
+ CHECK1(image->lwf_test, tp0[6]);
+ }
+ /* Bottom Right Corner Difference */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *tp0 = MACROBLK_UP2(image,ch,tx,image->tile_column_width[tx]-1).data;
+ tp0[7] = tp0[7] - tp0[6];
+ CHECK1(image->lwf_test, tp0[7]);
+ }
+ }
+ }
+
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ /* Left edge */
+ if (tx == 0 || image->disableTileOverlapFlag)
+ {
+ /* Interior left edge */
+ int*tp0 = MACROBLK_UP2(image,ch,tx,0).data;
+ _jxr_2OverlapFilter(tp0+2, tp0+4);
+ }
+
+ /* Right edge */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP2(image,ch,tx,image->tile_column_width[tx]-1).data;
+ /* Interior Right edge */
+ _jxr_2OverlapFilter(tp0+3, tp0+5);
+ }
+
+
+ /* Top edge */
+ if(top_my == 0 || (image->disableTileOverlapFlag && TOP_Y(top_my) ))
+ {
+ /* If this is the very first strip of blocks, then process the
+ first two scan lines with the smaller 4Overlap filter. */
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ /* Top edge across */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag) || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+ int*tp0 = MACROBLK_UP2(image,ch,tx,idx+0).data;
+ int*tp1 = MACROBLK_UP2(image,ch,tx,idx-1).data; /* The macroblock to the right */
+
+ _jxr_2OverlapFilter(tp1+1, tp0+0);
+ }
+ }
+ }
+
+ /* Bottom edge */
+ if ((top_my+1) == (int) EXTENDED_HEIGHT_BLOCKS(image) || (image->disableTileOverlapFlag && BOTTOM_Y(top_my))) {
+
+ /* This is the last row, so there is no UP below
+ TOP. finish up with 4Overlap filters. */
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ /* Bottom edge across */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag)
+ || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+ int*tp0 = MACROBLK_UP2(image,ch,tx,idx+0).data;
+ int*tp1 = MACROBLK_UP2(image,ch,tx,idx - 1).data;
+ _jxr_2OverlapFilter(tp1+7, tp0+6);
+ }
+ }
+ }
+
+ for (idx = 0 ; idx < image->tile_column_width[tx] ; idx += 1) {
+ if(top_my< EXTENDED_HEIGHT_BLOCKS(image) -1)
+ {
+ if ((tx == 0 && idx==0 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && LEFT_X(idx) && !BOTTOM_Y(top_my))) {
+ /* Across vertical blocks, left edge */
+ int*tp0 = MACROBLK_UP2(image,ch,tx,0).data;
+ int*up0 = MACROBLK_UP1(image,ch,tx,0).data;
+
+ /* Left edge across vertical MBs */
+ _jxr_2OverlapFilter(tp0+6, up0+0);
+ }
+
+ if((image->tile_column_position[tx] + idx == (int) EXTENDED_WIDTH_BLOCKS(image)-1 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && RIGHT_X(idx) && !BOTTOM_Y(top_my)))
+ {
+ int*tp0 = MACROBLK_UP2(image,ch,tx,image->tile_column_width[tx]-1).data;
+ int*up0 = MACROBLK_UP1(image,ch,tx,image->tile_column_width[tx]-1).data;
+
+ /* Right edge across MBs */
+ _jxr_2OverlapFilter(tp0+7, up0+1);
+ }
+
+ if (((image->tile_column_position[tx] + idx < EXTENDED_WIDTH_BLOCKS(image)-1) && !image->disableTileOverlapFlag ) ||
+ ( image->disableTileOverlapFlag && !RIGHT_X(idx) && !BOTTOM_Y(top_my) )
+ )
+ {
+ /* This assumes that the DCLP coefficients are the first
+ 16 values in the array, and ordered properly. */
+ int*tp0 = MACROBLK_UP2(image,ch,tx,idx+0).data;
+ int*tp1 = MACROBLK_UP2(image,ch,tx,idx+1).data;
+ int*up0 = MACROBLK_UP1(image,ch,tx,idx+0).data;
+ int*up1 = MACROBLK_UP1(image,ch,tx,idx+1).data;
+
+ /* MB below, right, right-below */
+ _jxr_2x2OverlapFilter(tp0+7, tp1+6, up0+1, up1+0);
+ }
+ }
+
+ if (((image->tile_column_position[tx] + idx < EXTENDED_WIDTH_BLOCKS(image)-1) && !image->disableTileOverlapFlag ) ||
+ ( image->disableTileOverlapFlag && !RIGHT_X(idx) )
+ )
+ {
+ /* This assumes that the DCLP coefficients are the first
+ 16 values in the array, and ordered properly. */
+ int*tp0 = MACROBLK_UP2(image,ch,tx,idx+0).data;
+ int*tp1 = MACROBLK_UP2(image,ch,tx,idx+1).data;
+
+ /* MB to the right */
+ _jxr_2x2OverlapFilter(tp0+3, tp1+2, tp0+5, tp1+4);
+ }
+ }
+ }
+
+ /* Top edge */
+ if(top_my == 0 || (image->disableTileOverlapFlag && TOP_Y(top_my)))
+ {
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ /* Top Left Corner Addition */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP2(image,ch,tx,0).data;
+ tp0[0] = tp0[0] + tp0[1];
+ CHECK1(image->lwf_test, tp0[0]);
+ }
+ /* Top Right Corner Addition */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *tp0 = MACROBLK_UP2(image,ch,tx,image->tile_column_width[tx]-1).data;
+ tp0[1] = tp0[1] + tp0[0];
+ CHECK1(image->lwf_test, tp0[1]);
+ }
+ }
+ }
+
+ /* Bottom edge */
+ if ((top_my+1) == (int) EXTENDED_HEIGHT_BLOCKS(image) || (image->disableTileOverlapFlag && BOTTOM_Y(top_my)))
+ {
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ /* Bottom Left Corner Addition */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP2(image,ch,tx,0).data;
+ tp0[6] = tp0[6] + tp0[7];
+ CHECK1(image->lwf_test, tp0[6]);
+ }
+ /* Bottom Right Corner Addition */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *tp0 = MACROBLK_UP2(image,ch,tx,image->tile_column_width[tx]-1).data;
+ tp0[7] = tp0[7] + tp0[6];
+ CHECK1(image->lwf_test, tp0[7]);
+ }
+ }
+ }
+}
+
+static void overlap_level1_up2_420(jxr_image_t image, int use_my, int ch)
+{
+ int tx = 0; /* XXXX */
+ int top_my = use_my - 2;
+
+ int idx;
+ int ty = 0;
+ /* 4 coeffs*/
+ assert(ch > 0 && image->use_clr_fmt == 1/*YUV420*/);
+ assert(use_my >= 2);
+ /* Figure out which tile row the current strip of macroblocks belongs to. */
+ while(top_my > image->tile_row_position[ty]+image->tile_row_height[ty] - 1)
+ ty++;
+
+ if(top_my == 0 || (image->disableTileOverlapFlag && TOP_Y(top_my)))
+ {
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ /* Top Left Corner Difference*/
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP2(image,ch,tx,0).data;
+ tp0[0] = tp0[0] -tp0[1];
+ CHECK1(image->lwf_test, tp0[0]);
+ }
+ /* Top Right Corner Difference*/
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *tp0 = MACROBLK_UP2(image,ch,tx,image->tile_column_width[tx]-1).data;
+ tp0[1] = tp0[1] - tp0[0];
+ CHECK1(image->lwf_test, tp0[1]);
+ }
+ }
+ }
+
+ /* Bottom edge */
+ if ((top_my+1) == (int) EXTENDED_HEIGHT_BLOCKS(image) || (image->disableTileOverlapFlag && BOTTOM_Y(top_my)))
+ {
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ /* Bottom Left Corner Difference*/
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP2(image,ch,tx,0).data;
+ tp0[2] = tp0[2] -tp0[3];
+ CHECK1(image->lwf_test, tp0[2]);
+ }
+ /* Bottom Right Corner Difference*/
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *tp0 = MACROBLK_UP2(image,ch,tx,image->tile_column_width[tx]-1).data;
+ tp0[3] = tp0[3] - tp0[2];
+ CHECK1(image->lwf_test, tp0[3]);
+ }
+ }
+ }
+
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ /* Top edge */
+ if(top_my == 0 || (image->disableTileOverlapFlag && TOP_Y(top_my)))
+ {
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ /* Top edge across */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag) || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+ int*tp0 = MACROBLK_UP2(image,ch,tx,idx+0).data;
+ int*tp1 = MACROBLK_UP2(image,ch,tx,idx-1).data;
+ _jxr_2OverlapFilter(tp1+1, tp0+0);
+ }
+ }
+ }
+
+ /* Bottom edge */
+ if ((top_my+1) == (int) EXTENDED_HEIGHT_BLOCKS(image) || (image->disableTileOverlapFlag && BOTTOM_Y(top_my))) {
+
+ /* This is the last row, so there is no UP below
+ TOP. finish up with 4Overlap filters. */
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ /* Bottom edge across */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag)
+ || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+ int*tp0 = MACROBLK_UP2(image,ch,tx,idx+0).data;
+ int*tp1 = MACROBLK_UP2(image,ch,tx,idx-1).data;
+ _jxr_2OverlapFilter(tp1+3, tp0+2);
+ }
+ }
+ }
+ else
+ {
+ for (idx = 0 ; idx < image->tile_column_width[tx] ; idx += 1) {
+
+ if ((tx == 0 && idx==0 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && LEFT_X(idx) && !BOTTOM_Y(top_my))) {
+ /* Left edge across vertical MBs */
+ int*tp0 = MACROBLK_UP2(image,ch,tx,0).data;
+ int*up0 = MACROBLK_UP1(image,ch,tx,0).data;
+
+ _jxr_2OverlapFilter(tp0+2, up0+0);
+ }
+
+ if((image->tile_column_position[tx] + idx == (int) EXTENDED_WIDTH_BLOCKS(image)-1 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && RIGHT_X(idx) && !BOTTOM_Y(top_my)))
+ {
+ /* Right edge across vertical MBs */
+ int*tp0 = MACROBLK_UP2(image,ch,tx,image->tile_column_width[tx]-1).data;
+ int*up0 = MACROBLK_UP1(image,ch,tx,image->tile_column_width[tx]-1).data;
+
+ _jxr_2OverlapFilter(tp0+3, up0+1);
+ }
+
+ if (((image->tile_column_position[tx] + idx < EXTENDED_WIDTH_BLOCKS(image)-1) && !image->disableTileOverlapFlag ) ||
+ ( image->disableTileOverlapFlag && !RIGHT_X(idx) && !BOTTOM_Y(top_my) )
+ )
+ {
+ /* This assumes that the DCLP coefficients are the first
+ 16 values in the array, and ordered properly. */
+ /* MB below, right, right-below */
+ int*tp0 = MACROBLK_UP2(image,ch,tx,idx+0).data;
+ int*tp1 = MACROBLK_UP2(image,ch,tx,idx+1).data;
+ int*up0 = MACROBLK_UP1(image,ch,tx,idx+0).data;
+ int*up1 = MACROBLK_UP1(image,ch,tx,idx+1).data;
+
+ _jxr_2x2OverlapFilter(tp0+3, tp1+2,
+ up0+1, up1+0);
+ }
+ }
+ }
+ }
+
+ /* Top edge */
+ if(top_my == 0 || (image->disableTileOverlapFlag && TOP_Y(top_my)))
+ {
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ /* Top Left Corner Addition */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP2(image,ch,tx,0).data;
+ tp0[0] = tp0[0] + tp0[1];
+ CHECK1(image->lwf_test, tp0[0]);
+ }
+ /* Top Right Corner Addition */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *tp0 = MACROBLK_UP2(image,ch,tx,image->tile_column_width[tx]-1).data;
+ tp0[1] = tp0[1] + tp0[0];
+ CHECK1(image->lwf_test, tp0[1]);
+ }
+ }
+ }
+
+
+ /* Bottom edge */
+ if ((top_my+1) == (int) EXTENDED_HEIGHT_BLOCKS(image) || (image->disableTileOverlapFlag && BOTTOM_Y(top_my)))
+ {
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ /* Bottom Left Corner Addition*/
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP2(image,ch,tx,0).data;
+ tp0[2] = tp0[2] + tp0[3];
+ CHECK1(image->lwf_test, tp0[2]);
+ }
+ /* Bottom Right Corner Addition*/
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *tp0 = MACROBLK_UP2(image,ch,tx,image->tile_column_width[tx]-1).data;
+ tp0[3] = tp0[3] + tp0[2];
+ CHECK1(image->lwf_test, tp0[3]);
+ }
+ }
+ }
+}
+
+
+static void overlap_level1_up2(jxr_image_t image, int use_my, int ch)
+{
+ if (ch == 0) {
+ overlap_level1_up2_444(image, use_my, ch);
+
+ }
+ else {
+ switch (image->use_clr_fmt) {
+ case 1: /*YUV420*/
+ overlap_level1_up2_420(image, use_my, ch);
+ break;
+ case 2: /*YUV422*/
+ overlap_level1_up2_422(image, use_my, ch);
+ break;
+ default:
+ overlap_level1_up2_444(image, use_my, ch);
+ break;
+ }
+ }
+}
+
+static int*R2B(int*data, int x, int y)
+{
+ int bx = x/4;
+ int by = y/4;
+ int bl = by*4 + bx;
+ return data + bl*16 + 4*(y%4) + x%4;
+}
+
+static int*R2B42(int*data, int x, int y)
+{
+ int bx = x/4;
+ int by = y/4;
+ int bl = by*2 + bx;
+ return data + bl*16 + 4*(y%4) + x%4;
+}
+
+static void overlap_level2_up3_444(jxr_image_t image, int use_my, int ch)
+{
+ int tx = 0; /* XXXX */
+ int top_my = use_my - 3;
+ int idx;
+ int ty = 0;
+
+ assert(ch == 0 || (image->use_clr_fmt != 2/*YUV422*/ && image->use_clr_fmt !=1/* YUV420*/));
+ assert(use_my >= 3);
+ DEBUG("Overlap Level2 for row %d\n", top_my);
+
+ /* Figure out which tile row the current strip of macroblocks belongs to. */
+ while(top_my > image->tile_row_position[ty]+image->tile_row_height[ty] - 1)
+ ty++;
+
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ int jdx;
+ /* Left edge */
+ if (tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*dp = MACROBLK_UP3(image,ch,tx,0).data;
+ for (jdx = 2 ; jdx < 14 ; jdx += 4) {
+ _jxr_4OverlapFilter(R2B(dp,0,jdx+0),R2B(dp,0,jdx+1),R2B(dp,0,jdx+2),R2B(dp,0,jdx+3));
+ _jxr_4OverlapFilter(R2B(dp,1,jdx+0),R2B(dp,1,jdx+1),R2B(dp,1,jdx+2),R2B(dp,1,jdx+3));
+ }
+ }
+
+ /* Right edge */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag){
+ int*dp = MACROBLK_UP3(image,ch,tx,image->tile_column_width[tx]-1).data;
+ for (jdx = 2 ; jdx < 14 ; jdx += 4) {
+ _jxr_4OverlapFilter(R2B(dp,14,jdx+0),R2B(dp,14,jdx+1),R2B(dp,14,jdx+2),R2B(dp,14,jdx+3));
+ _jxr_4OverlapFilter(R2B(dp,15,jdx+0),R2B(dp,15,jdx+1),R2B(dp,15,jdx+2),R2B(dp,15,jdx+3));
+ }
+ }
+
+ /* Top edge */
+ if(top_my == 0 || (image->disableTileOverlapFlag && TOP_Y(top_my) ))
+ {
+ /* If this is the very first strip of blocks, then process the
+ first two scan lines with the smaller 4Overlap filter. */
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ int*dp = MACROBLK_UP3(image,ch,tx,idx).data;
+ _jxr_4OverlapFilter(R2B(dp, 2,0),R2B(dp, 3,0),R2B(dp, 4,0),R2B(dp, 5,0));
+ _jxr_4OverlapFilter(R2B(dp, 6,0),R2B(dp, 7,0),R2B(dp, 8,0),R2B(dp, 9,0));
+ _jxr_4OverlapFilter(R2B(dp,10,0),R2B(dp,11,0),R2B(dp,12,0),R2B(dp,13,0));
+
+ _jxr_4OverlapFilter(R2B(dp, 2,1),R2B(dp, 3,1),R2B(dp, 4,1),R2B(dp, 5,1));
+ _jxr_4OverlapFilter(R2B(dp, 6,1),R2B(dp, 7,1),R2B(dp, 8,1),R2B(dp, 9,1));
+ _jxr_4OverlapFilter(R2B(dp,10,1),R2B(dp,11,1),R2B(dp,12,1),R2B(dp,13,1));
+
+ /* Top edge across */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag) || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+ int*pp = MACROBLK_UP3(image,ch,tx,idx-1).data;
+ _jxr_4OverlapFilter(R2B(pp,14,0),R2B(pp,15,0),R2B(dp,0,0),R2B(dp,1,0));
+ _jxr_4OverlapFilter(R2B(pp,14,1),R2B(pp,15,1),R2B(dp,0,1),R2B(dp,1,1));
+ }
+ }
+
+ /* Top left corner */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP3(image,ch, tx, 0).data;
+ _jxr_4OverlapFilter(R2B(dp, 0,0),R2B(dp, 1,0),R2B(dp, 0,1),R2B(dp, 1,1));
+ }
+ /* Top right corner */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP3(image,ch,tx, image->tile_column_width[tx] - 1 ).data;
+ _jxr_4OverlapFilter(R2B(dp, 14,0),R2B(dp, 15,0),R2B(dp, 14,1),R2B(dp, 15,1));
+ }
+
+ }
+
+ /* Bottom edge */
+ if ((top_my+1) == (int) EXTENDED_HEIGHT_BLOCKS(image) || (image->disableTileOverlapFlag && BOTTOM_Y(top_my))) {
+
+ /* This is the last row, so there is no UP below
+ TOP. finish up with 4Overlap filters. */
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ int*tp = MACROBLK_UP3(image,ch,tx,idx).data;
+
+ _jxr_4OverlapFilter(R2B(tp, 2,14),R2B(tp, 3,14),R2B(tp, 4,14),R2B(tp, 5,14));
+ _jxr_4OverlapFilter(R2B(tp, 6,14),R2B(tp, 7,14),R2B(tp, 8,14),R2B(tp, 9,14));
+ _jxr_4OverlapFilter(R2B(tp,10,14),R2B(tp,11,14),R2B(tp,12,14),R2B(tp,13,14));
+
+ _jxr_4OverlapFilter(R2B(tp, 2,15),R2B(tp, 3,15),R2B(tp, 4,15),R2B(tp, 5,15));
+ _jxr_4OverlapFilter(R2B(tp, 6,15),R2B(tp, 7,15),R2B(tp, 8,15),R2B(tp, 9,15));
+ _jxr_4OverlapFilter(R2B(tp,10,15),R2B(tp,11,15),R2B(tp,12,15),R2B(tp,13,15));
+
+ /* Bottom edge across */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag)
+ || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+ int*tn = MACROBLK_UP3(image,ch,tx,idx-1).data;
+ _jxr_4OverlapFilter(R2B(tn,14,14),R2B(tn,15,14),R2B(tp, 0,14),R2B(tp, 1,14));
+ _jxr_4OverlapFilter(R2B(tn,14,15),R2B(tn,15,15),R2B(tp, 0,15),R2B(tp, 1,15));
+ }
+ }
+
+ /* Bottom left corner */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP3(image,ch,tx,0).data;
+ _jxr_4OverlapFilter(R2B(dp, 0,14),R2B(dp, 1, 14),R2B(dp, 0,15),R2B(dp, 1, 15));
+ }
+ /* Bottom right corner */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP3(image,ch,tx, image->tile_column_width[tx] - 1 ).data;
+ _jxr_4OverlapFilter(R2B(dp, 14, 14),R2B(dp, 15, 14),R2B(dp, 14,15),R2B(dp, 15, 15));
+ }
+
+ }
+
+ for (idx = 0 ; idx < image->tile_column_width[tx] ; idx += 1) {
+ int jdx;
+
+ for (jdx = 2 ; jdx < 14 ; jdx += 4) {
+
+ int*dp = MACROBLK_UP3(image,ch,tx,idx).data;
+ /* Fully interior 4x4 filter blocks... */
+ _jxr_4x4OverlapFilter(R2B(dp, 2,jdx+0),R2B(dp, 3,jdx+0),R2B(dp, 4,jdx+0),R2B(dp, 5,jdx+0),
+ R2B(dp, 2,jdx+1),R2B(dp, 3,jdx+1),R2B(dp, 4,jdx+1),R2B(dp, 5,jdx+1),
+ R2B(dp, 2,jdx+2),R2B(dp, 3,jdx+2),R2B(dp, 4,jdx+2),R2B(dp, 5,jdx+2),
+ R2B(dp, 2,jdx+3),R2B(dp, 3,jdx+3),R2B(dp, 4,jdx+3),R2B(dp, 5,jdx+3));
+ _jxr_4x4OverlapFilter(R2B(dp, 6,jdx+0),R2B(dp, 7,jdx+0),R2B(dp, 8,jdx+0),R2B(dp, 9,jdx+0),
+ R2B(dp, 6,jdx+1),R2B(dp, 7,jdx+1),R2B(dp, 8,jdx+1),R2B(dp, 9,jdx+1),
+ R2B(dp, 6,jdx+2),R2B(dp, 7,jdx+2),R2B(dp, 8,jdx+2),R2B(dp, 9,jdx+2),
+ R2B(dp, 6,jdx+3),R2B(dp, 7,jdx+3),R2B(dp, 8,jdx+3),R2B(dp, 9,jdx+3));
+ _jxr_4x4OverlapFilter(R2B(dp,10,jdx+0),R2B(dp,11,jdx+0),R2B(dp,12,jdx+0),R2B(dp,13,jdx+0),
+ R2B(dp,10,jdx+1),R2B(dp,11,jdx+1),R2B(dp,12,jdx+1),R2B(dp,13,jdx+1),
+ R2B(dp,10,jdx+2),R2B(dp,11,jdx+2),R2B(dp,12,jdx+2),R2B(dp,13,jdx+2),
+ R2B(dp,10,jdx+3),R2B(dp,11,jdx+3),R2B(dp,12,jdx+3),R2B(dp,13,jdx+3));
+
+ if ( (image->tile_column_position[tx] + idx < EXTENDED_WIDTH_BLOCKS(image)-1 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && !RIGHT_X(idx))) {
+ /* 4x4 at the right */
+ int*np = MACROBLK_UP3(image,ch,tx,idx+1).data;
+
+ _jxr_4x4OverlapFilter(R2B(dp,14,jdx+0),R2B(dp,15,jdx+0),R2B(np, 0,jdx+0),R2B(np, 1,jdx+0),
+ R2B(dp,14,jdx+1),R2B(dp,15,jdx+1),R2B(np, 0,jdx+1),R2B(np, 1,jdx+1),
+ R2B(dp,14,jdx+2),R2B(dp,15,jdx+2),R2B(np, 0,jdx+2),R2B(np, 1,jdx+2),
+ R2B(dp,14,jdx+3),R2B(dp,15,jdx+3),R2B(np, 0,jdx+3),R2B(np, 1,jdx+3));
+ }
+ }
+
+ if ((top_my+1) < (int) EXTENDED_HEIGHT_BLOCKS(image)) {
+
+ int*dp = MACROBLK_UP3(image,ch,tx,idx).data;
+ int*up = MACROBLK_UP2(image,ch,tx,idx).data;
+
+ if ((tx == 0 && idx==0 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && LEFT_X(idx) && !BOTTOM_Y(top_my))) {
+ /* Across vertical blocks, left edge */
+ _jxr_4OverlapFilter(R2B(dp,0,14),R2B(dp,0,15),R2B(up,0,0),R2B(up,0,1));
+ _jxr_4OverlapFilter(R2B(dp,1,14),R2B(dp,1,15),R2B(up,1,0),R2B(up,1,1));
+ }
+ if((!image->disableTileOverlapFlag) || (image->disableTileOverlapFlag && !BOTTOM_Y(top_my)))
+ {
+ /* 4x4 bottom */
+ _jxr_4x4OverlapFilter(R2B(dp, 2,14),R2B(dp, 3,14),R2B(dp, 4,14),R2B(dp, 5,14),
+ R2B(dp, 2,15),R2B(dp, 3,15),R2B(dp, 4,15),R2B(dp, 5,15),
+ R2B(up, 2, 0),R2B(up, 3, 0),R2B(up, 4, 0),R2B(up, 5, 0),
+ R2B(up, 2, 1),R2B(up, 3, 1),R2B(up, 4, 1),R2B(up, 5, 1));
+ _jxr_4x4OverlapFilter(R2B(dp, 6,14),R2B(dp, 7,14),R2B(dp, 8,14),R2B(dp, 9,14),
+ R2B(dp, 6,15),R2B(dp, 7,15),R2B(dp, 8,15),R2B(dp, 9,15),
+ R2B(up, 6, 0),R2B(up, 7, 0),R2B(up, 8, 0),R2B(up, 9, 0),
+ R2B(up, 6, 1),R2B(up, 7, 1),R2B(up, 8, 1),R2B(up, 9, 1));
+ _jxr_4x4OverlapFilter(R2B(dp,10,14),R2B(dp,11,14),R2B(dp,12,14),R2B(dp,13,14),
+ R2B(dp,10,15),R2B(dp,11,15),R2B(dp,12,15),R2B(dp,13,15),
+ R2B(up,10, 0),R2B(up,11, 0),R2B(up,12, 0),R2B(up,13, 0),
+ R2B(up,10, 1),R2B(up,11, 1),R2B(up,12, 1),R2B(up,13, 1));
+ }
+
+ if (((image->tile_column_position[tx] + idx < EXTENDED_WIDTH_BLOCKS(image)-1) && !image->disableTileOverlapFlag ) ||
+ ( image->disableTileOverlapFlag && !RIGHT_X(idx) && !BOTTOM_Y(top_my) )
+ ) {
+ /* Blocks that span the MB to the right */
+ int*dn = MACROBLK_UP3(image,ch,tx,idx+1).data;
+ int*un = MACROBLK_UP2(image,ch,tx,idx+1).data;
+
+ /* 4x4 on right, below, below-right */
+ _jxr_4x4OverlapFilter(R2B(dp,14,14),R2B(dp,15,14),R2B(dn, 0,14),R2B(dn, 1,14),
+ R2B(dp,14,15),R2B(dp,15,15),R2B(dn, 0,15),R2B(dn, 1,15),
+ R2B(up,14, 0),R2B(up,15, 0),R2B(un, 0, 0),R2B(un, 1, 0),
+ R2B(up,14, 1),R2B(up,15, 1),R2B(un, 0, 1),R2B(un, 1, 1));
+ }
+ if((image->tile_column_position[tx] + idx == (int) EXTENDED_WIDTH_BLOCKS(image)-1 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && RIGHT_X(idx) && !BOTTOM_Y(top_my)))
+ {
+ /* Across vertical blocks, right edge */
+ _jxr_4OverlapFilter(R2B(dp,14,14),R2B(dp,14,15),R2B(up,14,0),R2B(up,14,1));
+ _jxr_4OverlapFilter(R2B(dp,15,14),R2B(dp,15,15),R2B(up,15,0),R2B(up,15,1));
+ }
+ }
+ }
+ }
+}
+
+static void overlap_level2_up3_422(jxr_image_t image, int use_my, int ch)
+{
+ int tx = 0; /* XXXX */
+ int top_my = use_my - 3;
+ int idx;
+ int ty = 0;
+
+
+ assert(ch > 0 && image->use_clr_fmt == 2/*YUV422*/);
+ assert(use_my >= 3);
+ DEBUG("Overlap Level2 for row %d\n", top_my);
+
+ /* Figure out which tile row the current strip of macroblocks belongs to. */
+ while(top_my > image->tile_row_position[ty]+image->tile_row_height[ty] - 1)
+ ty++;
+
+
+
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ /* Left edge */
+ if (tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*dp = MACROBLK_UP3(image,ch,tx,0).data;
+ _jxr_4OverlapFilter(R2B42(dp,0, 2),R2B42(dp,0, 3),R2B42(dp,0, 4),R2B42(dp,0, 5));
+ _jxr_4OverlapFilter(R2B42(dp,0, 6),R2B42(dp,0, 7),R2B42(dp,0, 8),R2B42(dp,0, 9));
+ _jxr_4OverlapFilter(R2B42(dp,0,10),R2B42(dp,0,11),R2B42(dp,0,12),R2B42(dp,0,13));
+
+ _jxr_4OverlapFilter(R2B42(dp,1, 2),R2B42(dp,1, 3),R2B42(dp,1, 4),R2B42(dp,1, 5));
+ _jxr_4OverlapFilter(R2B42(dp,1, 6),R2B42(dp,1, 7),R2B42(dp,1, 8),R2B42(dp,1, 9));
+ _jxr_4OverlapFilter(R2B42(dp,1,10),R2B42(dp,1,11),R2B42(dp,1,12),R2B42(dp,1,13));
+ }
+
+ /* Right edge */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag){
+
+ int*dp = MACROBLK_UP3(image,ch,tx,image->tile_column_width[tx]-1).data;
+ _jxr_4OverlapFilter(R2B42(dp,6,2),R2B42(dp,6,3),R2B42(dp,6,4),R2B42(dp,6,5));
+ _jxr_4OverlapFilter(R2B42(dp,7,2),R2B42(dp,7,3),R2B42(dp,7,4),R2B42(dp,7,5));
+
+ _jxr_4OverlapFilter(R2B42(dp,6,6),R2B42(dp,6,7),R2B42(dp,6,8),R2B42(dp,6,9));
+ _jxr_4OverlapFilter(R2B42(dp,7,6),R2B42(dp,7,7),R2B42(dp,7,8),R2B42(dp,7,9));
+
+ _jxr_4OverlapFilter(R2B42(dp,6,10),R2B42(dp,6,11),R2B42(dp,6,12),R2B42(dp,6,13));
+ _jxr_4OverlapFilter(R2B42(dp,7,10),R2B42(dp,7,11),R2B42(dp,7,12),R2B42(dp,7,13));
+ }
+
+ /* Top edge */
+ if(top_my == 0 || (image->disableTileOverlapFlag && TOP_Y(top_my) ))
+ {
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ int*dp = MACROBLK_UP3(image,ch,tx,idx).data;
+
+ _jxr_4OverlapFilter(R2B42(dp, 2,0),R2B42(dp, 3,0),R2B42(dp, 4,0),R2B42(dp, 5,0));
+ _jxr_4OverlapFilter(R2B42(dp, 2,1),R2B42(dp, 3,1),R2B42(dp, 4,1),R2B42(dp, 5,1));
+
+ /* Top across for soft tiles */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag) || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+ int*pp = MACROBLK_UP3(image,ch,tx,idx-1).data;
+ _jxr_4OverlapFilter(R2B42(pp,6,0),R2B42(pp,7,0),R2B(dp,0,0),R2B42(dp,1,0));
+ _jxr_4OverlapFilter(R2B42(pp,6,1),R2B42(pp,7,1),R2B(dp,0,1),R2B42(dp,1,1));
+ }
+ }
+
+ /* Top left corner */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP3(image,ch, tx, 0).data;
+ _jxr_4OverlapFilter(R2B42(dp,0,0),R2B42(dp,1,0),R2B42(dp,0,1),R2B42(dp,1,1));
+ }
+ /* Top right corner */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP3(image,ch,tx, image->tile_column_width[tx] - 1 ).data;
+ _jxr_4OverlapFilter(R2B42(dp,6,0),R2B42(dp,7,0),R2B42(dp,6,1),R2B42(dp,7,1));
+ }
+ }
+
+ /* Bottom edge */
+ if ((top_my+1) == (int) EXTENDED_HEIGHT_BLOCKS(image) || (image->disableTileOverlapFlag && BOTTOM_Y(top_my))) {
+
+ /* This is the last row, so there is no UP below
+ TOP. finish up with 4Overlap filters. */
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ int*tp = MACROBLK_UP3(image,ch,tx,idx).data;
+
+ _jxr_4OverlapFilter(R2B42(tp,2,14),R2B42(tp,3,14),R2B42(tp,4,14),R2B42(tp,5,14));
+ _jxr_4OverlapFilter(R2B42(tp,2,15),R2B42(tp,3,15),R2B42(tp,4,15),R2B42(tp,5,15));
+
+ /* Bottom across for soft tiles */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag)
+ || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+ /* Blocks that span the MB to the right */
+ int*tn = MACROBLK_UP3(image,ch,tx,idx-1).data;
+ _jxr_4OverlapFilter(R2B42(tn,6,14),R2B42(tn,7,14),R2B42(tp,0,14),R2B42(tp,1,14));
+ _jxr_4OverlapFilter(R2B42(tn,6,15),R2B42(tn,7,15),R2B42(tp,0,15),R2B42(tp,1,15));
+ }
+ }
+
+ /* Bottom left corner */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP3(image,ch,tx,0).data;
+ _jxr_4OverlapFilter(R2B42(dp,0,14),R2B42(dp,1,14),R2B42(dp,0,15),R2B42(dp,1,15));
+ }
+ /* Bottom right corner */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP3(image,ch,tx, image->tile_column_width[tx] - 1 ).data;
+ _jxr_4OverlapFilter(R2B42(dp,6,14),R2B42(dp,7,14),R2B42(dp,6,15),R2B42(dp,7,15));
+ }
+ }
+
+ for (idx = 0 ; idx < image->tile_column_width[tx] ; idx += 1) {
+ int*dp = MACROBLK_UP3(image,ch,tx,idx).data;
+
+ /* Fully interior 4x4 filter blocks... */
+ _jxr_4x4OverlapFilter(R2B42(dp,2,2),R2B42(dp,3,2),R2B42(dp,4,2),R2B42(dp,5,2),
+ R2B42(dp,2,3),R2B42(dp,3,3),R2B42(dp,4,3),R2B42(dp,5,3),
+ R2B42(dp,2,4),R2B42(dp,3,4),R2B42(dp,4,4),R2B42(dp,5,4),
+ R2B42(dp,2,5),R2B42(dp,3,5),R2B42(dp,4,5),R2B42(dp,5,5));
+
+ _jxr_4x4OverlapFilter(R2B42(dp,2,6),R2B42(dp,3,6),R2B42(dp,4,6),R2B42(dp,5,6),
+ R2B42(dp,2,7),R2B42(dp,3,7),R2B42(dp,4,7),R2B42(dp,5,7),
+ R2B42(dp,2,8),R2B42(dp,3,8),R2B42(dp,4,8),R2B42(dp,5,8),
+ R2B42(dp,2,9),R2B42(dp,3,9),R2B42(dp,4,9),R2B42(dp,5,9));
+
+ _jxr_4x4OverlapFilter(R2B42(dp,2,10),R2B42(dp,3,10),R2B42(dp,4,10),R2B42(dp,5,10),
+ R2B42(dp,2,11),R2B42(dp,3,11),R2B42(dp,4,11),R2B42(dp,5,11),
+ R2B42(dp,2,12),R2B42(dp,3,12),R2B42(dp,4,12),R2B42(dp,5,12),
+ R2B42(dp,2,13),R2B42(dp,3,13),R2B42(dp,4,13),R2B42(dp,5,13));
+
+ if ( (image->tile_column_position[tx] + idx < EXTENDED_WIDTH_BLOCKS(image)-1 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && !RIGHT_X(idx))) {
+ /* Blocks that span the MB to the right */
+ int*np = MACROBLK_UP3(image,ch,tx,idx+1).data;
+ _jxr_4x4OverlapFilter(R2B42(dp,6,2),R2B42(dp,7,2),R2B42(np,0,2),R2B42(np,1,2),
+ R2B42(dp,6,3),R2B42(dp,7,3),R2B42(np,0,3),R2B42(np,1,3),
+ R2B42(dp,6,4),R2B42(dp,7,4),R2B42(np,0,4),R2B42(np,1,4),
+ R2B42(dp,6,5),R2B42(dp,7,5),R2B42(np,0,5),R2B42(np,1,5));
+
+ _jxr_4x4OverlapFilter(R2B42(dp,6,6),R2B42(dp,7,6),R2B42(np,0,6),R2B42(np,1,6),
+ R2B42(dp,6,7),R2B42(dp,7,7),R2B42(np,0,7),R2B42(np,1,7),
+ R2B42(dp,6,8),R2B42(dp,7,8),R2B42(np,0,8),R2B42(np,1,8),
+ R2B42(dp,6,9),R2B42(dp,7,9),R2B42(np,0,9),R2B42(np,1,9));
+
+ _jxr_4x4OverlapFilter(R2B42(dp,6,10),R2B42(dp,7,10),R2B42(np,0,10),R2B42(np,1,10),
+ R2B42(dp,6,11),R2B42(dp,7,11),R2B42(np,0,11),R2B42(np,1,11),
+ R2B42(dp,6,12),R2B42(dp,7,12),R2B42(np,0,12),R2B42(np,1,12),
+ R2B42(dp,6,13),R2B42(dp,7,13),R2B42(np,0,13),R2B42(np,1,13));
+ }
+
+ if ((top_my+1) < (int) EXTENDED_HEIGHT_BLOCKS(image)) {
+
+ /* Blocks that MB below */
+ int*dp = MACROBLK_UP3(image,ch,tx,idx).data;
+ int*up = MACROBLK_UP2(image,ch,tx,idx).data;
+
+ if ((tx == 0 && idx==0 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && LEFT_X(idx) && !BOTTOM_Y(top_my))) {
+ _jxr_4OverlapFilter(R2B42(dp,0,14),R2B42(dp,0,15),R2B42(up,0,0),R2B42(up,0,1));
+ _jxr_4OverlapFilter(R2B42(dp,1,14),R2B42(dp,1,15),R2B42(up,1,0),R2B42(up,1,1));
+ }
+ if((!image->disableTileOverlapFlag) || (image->disableTileOverlapFlag && !BOTTOM_Y(top_my)))
+ {
+ _jxr_4x4OverlapFilter(R2B42(dp,2,14),R2B42(dp,3,14),R2B42(dp,4,14),R2B42(dp,5,14),
+ R2B42(dp,2,15),R2B42(dp,3,15),R2B42(dp,4,15),R2B42(dp,5,15),
+ R2B42(up,2, 0),R2B42(up,3, 0),R2B42(up,4, 0),R2B42(up,5, 0),
+ R2B42(up,2, 1),R2B42(up,3, 1),R2B42(up,4, 1),R2B42(up,5, 1));
+
+ }
+
+ if (((image->tile_column_position[tx] + idx < EXTENDED_WIDTH_BLOCKS(image)-1) && !image->disableTileOverlapFlag ) ||
+ ( image->disableTileOverlapFlag && !RIGHT_X(idx) && !BOTTOM_Y(top_my) )
+ ) {
+ /* Blocks that span the MB to the right, below, below-right */
+ int*dn = MACROBLK_UP3(image,ch,tx,idx+1).data;
+ int*un = MACROBLK_UP2(image,ch,tx,idx+1).data;
+
+ _jxr_4x4OverlapFilter(R2B42(dp,6,14),R2B42(dp,7,14),R2B42(dn,0,14),R2B42(dn,1,14),
+ R2B42(dp,6,15),R2B42(dp,7,15),R2B42(dn,0,15),R2B42(dn,1,15),
+ R2B42(up,6, 0),R2B42(up,7, 0),R2B42(un,0, 0),R2B42(un,1, 0),
+ R2B42(up,6, 1),R2B42(up,7, 1),R2B42(un,0, 1),R2B42(un,1, 1));
+ }
+ if((image->tile_column_position[tx] + idx == (int) EXTENDED_WIDTH_BLOCKS(image)-1 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && RIGHT_X(idx) && !BOTTOM_Y(top_my)))
+ {
+ _jxr_4OverlapFilter(R2B42(dp,6,14),R2B42(dp,6,15),R2B42(up,6,0),R2B42(up,6,1));
+ _jxr_4OverlapFilter(R2B42(dp,7,14),R2B42(dp,7,15),R2B42(up,7,0),R2B42(up,7,1));
+ }
+ }
+ }
+ }
+}
+/*
+*/
+
+static void overlap_level2_up3_420(jxr_image_t image, int use_my, int ch)
+{
+ int tx = 0; /* XXXX */
+ int top_my = use_my - 3;
+ int idx;
+ int ty = 0;
+
+ assert(ch > 0 && image->use_clr_fmt == 1/*YUV420*/);
+ assert(use_my >= 3);
+
+ DEBUG("Overlap Level2 (YUV420) for row %d\n", top_my);
+
+
+ /* Figure out which tile row the current strip of macroblocks belongs to. */
+ while(top_my > image->tile_row_position[ty]+image->tile_row_height[ty] - 1)
+ ty++;
+
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+
+ /* Left edge */
+ if (tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*dp = MACROBLK_UP3(image,ch,tx,0).data;
+ _jxr_4OverlapFilter(R2B42(dp,0,2),R2B42(dp,0,3),R2B42(dp,0,4),R2B42(dp,0,5));
+ _jxr_4OverlapFilter(R2B42(dp,1,2),R2B42(dp,1,3),R2B42(dp,1,4),R2B42(dp,1,5));
+ }
+
+ /* Right edge */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag){
+ int*dp = MACROBLK_UP3(image,ch,tx,image->tile_column_width[tx]-1).data;
+ _jxr_4OverlapFilter(R2B42(dp,6,2),R2B42(dp,6,3),R2B42(dp,6,4),R2B42(dp,6,5));
+ _jxr_4OverlapFilter(R2B42(dp,7,2),R2B42(dp,7,3),R2B42(dp,7,4),R2B42(dp,7,5));
+ }
+
+ /* Top edge */
+ if(top_my == 0 )/* || (image->disableTileOverlapFlag && TOP_Y(top_my) )) */
+ {
+ /* If this is the very first strip of blocks, then process the
+ first two scan lines with the smaller 4Overlap filter. */
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ int*dp = MACROBLK_UP3(image,ch,tx,idx).data;
+ _jxr_4OverlapFilter(R2B42(dp, 2,0),R2B42(dp, 3,0),R2B42(dp, 4,0),R2B42(dp, 5,0));
+ _jxr_4OverlapFilter(R2B42(dp, 2,1),R2B42(dp, 3,1),R2B42(dp, 4,1),R2B42(dp, 5,1));
+ /* Top edge across */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag) || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+ int*pp = MACROBLK_UP3(image,ch,tx,idx-1).data;
+ _jxr_4OverlapFilter(R2B42(pp,6,0),R2B42(pp,7,0),R2B(dp,0,0),R2B42(dp,1,0));
+ _jxr_4OverlapFilter(R2B42(pp,6,1),R2B42(pp,7,1),R2B(dp,0,1),R2B42(dp,1,1));
+ }
+ }
+
+ /* Top left corner */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP3(image,ch,tx,0).data;
+ _jxr_4OverlapFilter(R2B42(dp, 0,0),R2B42(dp, 1, 0),R2B42(dp, 0 ,1),R2B42(dp, 1,1));
+ }
+ /* Top right corner */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP3(image,ch,tx, image->tile_column_width[tx] - 1 ).data;
+ _jxr_4OverlapFilter(R2B42(dp, 6,0),R2B42(dp, 7,0),R2B42(dp, 6,1),R2B42(dp, 7,1));;
+ }
+
+ }
+
+ /* Bottom edge */
+ if ((top_my+1) == (int) EXTENDED_HEIGHT_BLOCKS(image) || (image->disableTileOverlapFlag && BOTTOM_Y(top_my))) {
+
+ /* This is the last row, so there is no UP below
+ TOP. finish up with 4Overlap filters. */
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ int*tp = MACROBLK_UP3(image,ch,tx,idx).data;
+
+ _jxr_4OverlapFilter(R2B42(tp,2,6),R2B42(tp,3,6),R2B42(tp,4,6),R2B42(tp,5,6));
+ _jxr_4OverlapFilter(R2B42(tp,2,7),R2B42(tp,3,7),R2B42(tp,4,7),R2B42(tp,5,7));
+
+
+ /* Bottom edge across */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag)
+ || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+ int*tn = MACROBLK_UP3(image,ch,tx,idx-1).data;
+ _jxr_4OverlapFilter(R2B42(tn,6,6),R2B42(tn,7,6),R2B42(tp,0,6),R2B42(tp,1,6));
+ _jxr_4OverlapFilter(R2B42(tn,6,7),R2B42(tn,7,7),R2B42(tp,0,7),R2B42(tp,1,7));
+ }
+ }
+
+ /* Bottom left corner */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP3(image,ch,tx,0).data;
+ _jxr_4OverlapFilter(R2B42(dp, 0,6),R2B42(dp, 1, 6),R2B42(dp, 0,7),R2B42(dp, 1, 7));
+ }
+
+ /* Bottom right corner */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP3(image,ch,tx, image->tile_column_width[tx] - 1 ).data;
+ _jxr_4OverlapFilter(R2B42(dp, 6, 6),R2B42(dp, 7, 6),R2B42(dp, 6, 7),R2B42(dp, 7, 7));
+ }
+
+ if(image->disableTileOverlapFlag && BOTTOM_Y(top_my) && top_my <EXTENDED_HEIGHT_BLOCKS(image)-1)
+ {
+ /* Also process Top edge of next macroblock row */
+ /* In the case of YUV 420, the next row of macroblocks needs to be transformed */
+ /* before yuv420_to_yuv422 is called */
+ /* In the soft tile case the top 2 lines of the MB below are processed by the 2x2 operators spanning the MB below*/
+ /* In the case of hard tiles, if this is the bottom most row of MBs in the Hard Tile */
+ /* we need to process the top edge of the next hard tile */
+ /* Also see HARDTILE_NOTE in yuv420_to_yuv422() */
+
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ int*dp = MACROBLK_UP2(image,ch,tx,idx).data;
+ _jxr_4OverlapFilter(R2B42(dp, 2,0),R2B42(dp, 3,0),R2B42(dp, 4,0),R2B42(dp, 5,0));
+ _jxr_4OverlapFilter(R2B42(dp, 2,1),R2B42(dp, 3,1),R2B42(dp, 4,1),R2B42(dp, 5,1));
+ /* Top edge across */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag) || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+ int*pp = MACROBLK_UP2(image,ch,tx,idx-1).data;
+ _jxr_4OverlapFilter(R2B42(pp,6,0),R2B42(pp,7,0),R2B(dp,0,0),R2B42(dp,1,0));
+ _jxr_4OverlapFilter(R2B42(pp,6,1),R2B42(pp,7,1),R2B(dp,0,1),R2B42(dp,1,1));
+ }
+ }
+
+ /* Top left corner */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP2(image,ch,tx,0).data;
+ _jxr_4OverlapFilter(R2B42(dp, 0,0),R2B42(dp, 1, 0),R2B42(dp, 0 ,1),R2B42(dp, 1,1));
+ }
+
+ /* Top right corner */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP2(image,ch,tx, image->tile_column_width[tx] - 1 ).data;
+ _jxr_4OverlapFilter(R2B42(dp, 6,0),R2B42(dp, 7,0),R2B42(dp, 6,1),R2B42(dp, 7,1));;
+ }
+ }
+ }
+
+ for (idx = 0 ; idx < image->tile_column_width[tx] ; idx += 1) {
+
+ int*dp = MACROBLK_UP3(image,ch,tx,idx).data;
+ int*up = MACROBLK_UP2(image,ch,tx,idx).data;
+
+ /* Fully interior 4x4 filter blocks... */
+ _jxr_4x4OverlapFilter(R2B42(dp,2,2),R2B42(dp,3,2),R2B42(dp,4,2),R2B42(dp,5,2),
+ R2B42(dp,2,3),R2B42(dp,3,3),R2B42(dp,4,3),R2B42(dp,5,3),
+ R2B42(dp,2,4),R2B42(dp,3,4),R2B42(dp,4,4),R2B42(dp,5,4),
+ R2B42(dp,2,5),R2B42(dp,3,5),R2B42(dp,4,5),R2B42(dp,5,5));
+
+ if ( (image->tile_column_position[tx] + idx < EXTENDED_WIDTH_BLOCKS(image)-1 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && !RIGHT_X(idx)))
+ {
+ /* 4x4 at the right */
+ int*np = MACROBLK_UP3(image,ch,tx,idx+1).data;
+
+ _jxr_4x4OverlapFilter(R2B42(dp,6,2),R2B42(dp,7,2),R2B42(np,0,2),R2B42(np,1,2),
+ R2B42(dp,6,3),R2B42(dp,7,3),R2B42(np,0,3),R2B42(np,1,3),
+ R2B42(dp,6,4),R2B42(dp,7,4),R2B42(np,0,4),R2B42(np,1,4),
+ R2B42(dp,6,5),R2B42(dp,7,5),R2B42(np,0,5),R2B42(np,1,5));
+ }
+
+ if ((top_my+1) < (int) EXTENDED_HEIGHT_BLOCKS(image)) {
+
+ int*dp = MACROBLK_UP3(image,ch,tx,idx).data;
+ int*up = MACROBLK_UP2(image,ch,tx,idx).data;
+
+ if ((tx == 0 && idx==0 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && LEFT_X(idx) && !BOTTOM_Y(top_my))) {
+ /* Across vertical blocks, left edge */
+ _jxr_4OverlapFilter(R2B42(dp,0,6),R2B42(dp,0,7),R2B42(up,0,0),R2B42(up,0,1));
+ _jxr_4OverlapFilter(R2B42(dp,1,6),R2B42(dp,1,7),R2B42(up,1,0),R2B42(up,1,1));
+ }
+ if((!image->disableTileOverlapFlag) || (image->disableTileOverlapFlag && !BOTTOM_Y(top_my)))
+ {
+ /* 4x4 straddling lower MB */
+ _jxr_4x4OverlapFilter(R2B42(dp,2,6),R2B42(dp,3,6),R2B42(dp,4,6),R2B42(dp,5,6),
+ R2B42(dp,2,7),R2B42(dp,3,7),R2B42(dp,4,7),R2B42(dp,5,7),
+ R2B42(up,2,0),R2B42(up,3,0),R2B42(up,4,0),R2B42(up,5,0),
+ R2B42(up,2,1),R2B42(up,3,1),R2B42(up,4,1),R2B42(up,5,1));
+ }
+
+ if (((image->tile_column_position[tx] + idx < EXTENDED_WIDTH_BLOCKS(image)-1) && !image->disableTileOverlapFlag ) ||
+ ( image->disableTileOverlapFlag && !RIGHT_X(idx) && !BOTTOM_Y(top_my) )
+ ) {
+ /* Blocks that span the MB to the right */
+ int*dn = MACROBLK_UP3(image,ch,tx,idx+1).data;
+ int*un = MACROBLK_UP2(image,ch,tx,idx+1).data;
+
+ /* 4x4 right, below, below-right */
+ _jxr_4x4OverlapFilter(R2B42(dp,6,6),R2B42(dp,7,6),R2B42(dn,0,6),R2B42(dn,1,6),
+ R2B42(dp,6,7),R2B42(dp,7,7),R2B42(dn,0,7),R2B42(dn,1,7),
+ R2B42(up,6,0),R2B42(up,7,0),R2B42(un,0,0),R2B42(un,1,0),
+ R2B42(up,6,1),R2B42(up,7,1),R2B42(un,0,1),R2B42(un,1,1));
+ }
+ if((image->tile_column_position[tx] + idx == (int) EXTENDED_WIDTH_BLOCKS(image)-1 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && RIGHT_X(idx) && !BOTTOM_Y(top_my)))
+ {
+ /* Across vertical blocks, right edge */
+ _jxr_4OverlapFilter(R2B42(dp,6,6),R2B42(dp,6,7),R2B42(up,6,0),R2B42(up,6,1));
+ _jxr_4OverlapFilter(R2B42(dp,7,6),R2B42(dp,7,7),R2B42(up,7,0),R2B42(up,7,1));
+ }
+ }
+ }
+ }
+}
+
+
+static void overlap_level2_up3(jxr_image_t image, int use_my, int ch)
+{
+ if (ch == 0) {
+ overlap_level2_up3_444(image, use_my, ch);
+ }
+ else {
+ switch (image->use_clr_fmt) {
+ case 1: /*YUV420*/
+ overlap_level2_up3_420(image, use_my, ch);
+ break;
+ case 2: /*YUV422*/
+ overlap_level2_up3_422(image, use_my, ch);
+ break;
+ default:
+ overlap_level2_up3_444(image, use_my, ch);
+ break;
+ }
+ }
+}
+
+
+static void yuv444_to_rgb(jxr_image_t image, int mx)
+{
+ int px;
+ for (px = 0 ; px < 256 ; px += 1) {
+ int Y = image->strip[0].up3[mx].data[px];
+ int U = image->strip[1].up3[mx].data[px];
+ int V = image->strip[2].up3[mx].data[px];
+ int G = Y - _jxr_floor_div2(-U);
+ int R = G - U - _jxr_ceil_div2(V);
+ int B = V + R;
+
+ image->strip[0].up3[mx].data[px] = R;
+ image->strip[1].up3[mx].data[px] = G;
+ image->strip[2].up3[mx].data[px] = B;
+ }
+}
+
+static const int iH[5][4] = {{4, 4 , 0, 8}, {5, 3, 1, 7}, {6, 2, 2, 6}, {7, 1, 3, 5}, {8, 0, 4, 4}};
+
+static void upsample(int inbuf[], int outbuf[], int upsamplelen, int chroma_center)
+{
+ int k;
+ if(chroma_center == 5 || chroma_center == 6 || chroma_center == 7)
+ {
+ chroma_center = 0;
+ DEBUG("Treating chroma_center as 0 in upsample\n");
+ }
+
+ for (k = 0; k <= (upsamplelen - 2) / 2; k++)
+ outbuf[2*k+1] = (( iH[chroma_center][0]*inbuf[k+1] + iH[chroma_center][1]*inbuf[k+2] + 4) >> 3);
+ for (k = -1; k <= (upsamplelen - 4) / 2; k++)
+ outbuf[2*k+2] = ((iH[chroma_center][2] * inbuf[k+1] + iH[chroma_center][3] * inbuf[k+2] + 4) >> 3);
+}
+
+static void yuv422_to_yuv444(jxr_image_t image, int mx)
+{
+ int buf[256];
+
+ int ch;
+ int px, py, idx;
+
+ for(ch =1; ch < 3; ch ++) {
+
+ for (py = 0 ; py < 16 ; py += 1)
+ {
+ int inbuf [10];
+
+ if(mx == 0) /* Repeat to the left */
+ image->strip[ch].upsample_memory_x[py] = image->strip[ch].up3[mx].data[8*py];
+
+ /* Prep input array */
+ for(px =0; px <=7; px++)
+ {
+ inbuf[px+1] = image->strip[ch].up3[mx].data[8*py+ px];
+
+ }
+ inbuf[0] = image->strip[ch].upsample_memory_x[py];
+ if(mx+1 < (int) EXTENDED_WIDTH_BLOCKS(image))
+ inbuf[9] = image->strip[ch].up3[mx+1].data[8*py];
+ else
+ inbuf[9] = inbuf[8]; /* Repeat to the right */
+
+ /* Call upsample */
+ upsample(inbuf, buf + 16*py, 16, image->chroma_centering_x);
+
+ /* Remember right most vals */
+ image->strip[ch].upsample_memory_x[py] = image->strip[ch].up3[mx].data[8*py+7];
+ }
+
+ for (idx = 0 ; idx < 256 ; idx += 1)
+ image->strip[ch].up3[mx].data[idx] = buf[idx];
+
+ }
+}
+
+static void yuv420_to_yuv444(jxr_image_t image, int use_my, int mx)
+{
+ int buf[256];
+ int intermediatebuf[2][16 * 8];
+
+ int ch;
+ int inbuf [10];
+ int px, py, idx;
+
+ /* Upsample in the y direction */
+ for (ch = 1 ; ch < 3 ; ch += 1) {
+ for(px = 0; px < 8; px ++)
+ {
+ if(use_my-2 == 1) /* Repeat to the top */
+ image->strip[ch].upsample_memory_y[8*mx+ px] = image->strip[ch].up3[mx].data[px];/* Store the top most values */
+
+ /* Prep input buffer */
+ for(py =0; py < 8 ; py++)
+ inbuf[py+1] = image->strip[ch].up3[mx].data[8*py+ px];
+ inbuf[0] = image->strip[ch].upsample_memory_y[8*mx + px];
+ if((use_my-2) < (int) EXTENDED_HEIGHT_BLOCKS(image))
+ {
+ if(px <= 3)
+ inbuf[9] = image->strip[ch].up2[mx].data[px]; /* Get the lower MB sample */
+ else
+ inbuf[9] = image->strip[ch].up2[mx].data[px + 12]; /* Since unblock_shuffle420 has not been called on up2 */
+ }
+ else
+ inbuf[9] = inbuf[8]; /* Repeat to the right */
+
+ /* Call upsample */
+ upsample(inbuf, buf, 16, image->chroma_centering_y);
+
+ for(py =0; py < 16; py ++)
+ intermediatebuf[ch-1][8*py + px] = buf[py];
+
+ image->strip[ch].upsample_memory_y[8*mx + px] = image->strip[ch].up3[mx].data[8*7+px];/* Store the bottom most values */
+ }
+ }
+
+ /* Upsample in the X direction */
+ for (ch = 1 ; ch < 3 ; ch += 1) {
+ int nextmbrow[16];
+
+ /* To upsample in the X direction, we need the Y-direction upsampled values from the left most row of the next MB */
+ /* Prep input buffer */
+ for(py = 0; py < 8; py ++)
+ {
+ if(mx + 1 < (int) EXTENDED_WIDTH_BLOCKS(image))
+ inbuf[py + 1] = image->strip[ch].up3[mx+1].data[8*py];
+ else
+ inbuf[py + 1] = image->strip[ch].up3[mx].data[8*py];
+ }
+ if(use_my - 2 < (int) EXTENDED_HEIGHT_BLOCKS(image) && mx + 1 < (int) EXTENDED_WIDTH_BLOCKS(image))
+ inbuf[9] = image->strip[ch].up2[mx+1].data[0];
+ else
+ inbuf[9] = inbuf[8];/* Repeat to the right */
+ if(use_my -2 != 1 && mx + 1 < (int) EXTENDED_WIDTH_BLOCKS(image))
+ inbuf[0] = image->strip[ch].upsample_memory_y[8*(mx+1)];
+ else
+ inbuf[0] = inbuf[1];
+
+ /*Call upsample */
+ upsample(inbuf, nextmbrow, 16, image->chroma_centering_y);
+
+ for(py = 0; py < 16; py ++)
+ {
+ if(mx == 0) /* Repeat to the left */
+ image->strip[ch].upsample_memory_x[py] = intermediatebuf[ch-1][8*py];
+
+ /* Prepare the input buffer */
+ for(px =0; px <=7; px++)
+ inbuf[px+1] = intermediatebuf[ch-1][8*py+ px];
+
+ inbuf[0] = image->strip[ch].upsample_memory_x[py];
+ if(mx + 1 < (int) EXTENDED_WIDTH_BLOCKS(image))
+ {
+ inbuf[9] = nextmbrow[py];
+ }
+ else
+ inbuf[9] = inbuf[8]; /* Repeat to the right */
+
+ /* Call upsample */
+ upsample(inbuf, buf + 16*py, 16, image->chroma_centering_x);
+ image->strip[ch].upsample_memory_x[py] = intermediatebuf[ch-1][8*py + 7];/* Store the right most values */
+ }
+
+ for(idx =0; idx < 256; idx ++)
+ image->strip[ch].up3[mx].data[idx] = buf[idx];
+ }
+}
+
+static void yuvk_to_cmyk(jxr_image_t image, int mx)
+{
+ int px;
+ for (px = 0 ; px < 256 ; px += 1) {
+ int Y = image->strip[0].up3[mx].data[px];
+ int U = image->strip[1].up3[mx].data[px];
+ int V = image->strip[2].up3[mx].data[px];
+ int K = image->strip[3].up3[mx].data[px];
+ int k = K + _jxr_floor_div2(Y);
+ int m = k - Y - _jxr_floor_div2(U);
+ int c = U + m + _jxr_floor_div2(V);
+ int y = c - V;
+
+ image->strip[0].up3[mx].data[px] = c;
+ image->strip[1].up3[mx].data[px] = m;
+ image->strip[2].up3[mx].data[px] = y;
+ image->strip[3].up3[mx].data[px] = k;
+ }
+}
+
+static int PostScalingFloat(int iPixVal, unsigned int expBias, unsigned char lenMantissa, int bitdepth)
+{
+ int convVal = 0;
+ if (bitdepth == JXR_BD16F)
+ {
+ uint8_t iS = 0;
+ unsigned int fV = 0;
+ unsigned int iEM = abs(iPixVal);
+ if(iPixVal < 0)
+ iS = 1;
+ if (iEM > 0x7FFF)
+ iEM = 0x7FFF;
+ convVal = ((iS << 15) | iEM); /* Concatenate these fields*/
+ }
+ else
+ {
+ int sign, iTempH, mantissa, exp, lmshift = (1 << lenMantissa);
+
+ assert (expBias <= 127);
+
+ iTempH = (int) iPixVal ;
+ sign = (iTempH >> 31);
+ iTempH = (iTempH ^ sign) - sign; /* abs(iTempH) */
+
+ exp = (unsigned int) iTempH >> lenMantissa;/* & ((1 << (31 - lenMantissa)) - 1); */
+ mantissa = (iTempH & (lmshift - 1)) | lmshift; /* actual mantissa, with normalizer */
+ if (exp == 0) { /* denormal land */
+ mantissa ^= lmshift; /* normalizer removed */
+ exp = 1; /* actual exponent */
+ }
+
+ exp += (127 - expBias);
+ while (mantissa < lmshift && exp > 1 && mantissa > 0) { /* denormal originally, see if normal is possible */
+ exp--;
+ mantissa <<= 1;
+ }
+ if (mantissa < lmshift) /* truly denormal */
+ exp = 0;
+ else
+ mantissa ^= lmshift;
+ mantissa <<= (23 - lenMantissa);
+
+ convVal = (sign & 0x80000000) | (exp << 23) | mantissa;
+ }
+ return convVal;
+}
+
+static void PostScalingFl2(int arrayOut[], int arrayIn[]) {
+ /* arrayIn[ ]= {R, G, B} */
+ /* arrayOut[ ]= {Rrgbe, Grgbe, Brgbe, Ergbe} */
+ int iEr, iEg, iEb;
+ int iShift;
+
+ if (arrayIn[0] <= 0) {
+ arrayOut[0] = 0;
+ iEr = 0;
+ }
+ else if ((arrayIn[0] >> 7) > 1) {
+ arrayOut[0] = (arrayIn[0] & 0x7F) + 0x80;
+ iEr = (arrayIn[0] >> 7);
+ }
+ else {
+ arrayOut[0] = arrayIn[0];
+ iEr = 1;
+ }
+ if (arrayIn[1] <= 0) {
+ arrayOut[1] = 0;
+ iEg = 0;
+ }
+ else if ((arrayIn[1] >> 7) > 1) {
+ arrayOut[1] = (arrayIn[1] & 0x7F) + 0x80;
+ iEg = (arrayIn[1] >> 7);
+ }
+ else {
+ arrayOut[1] = arrayIn[1];
+ iEg = 1;
+ }
+ if (arrayIn[2] <= 0) {
+ arrayOut[2] = 0;
+ iEb = 0;
+ }
+ else if ((arrayIn[2] >> 7) > 1) {
+ arrayOut[2] = (arrayIn[2] & 0x7F) + 0x80;
+ iEb = (arrayIn[2] >> 7);
+ }
+ else {
+ arrayOut[2] = arrayIn[2];
+ iEb = 1;
+ }
+
+ /* Max(iEr, iEg, iEb) */
+ arrayOut[3] = iEr> iEg? (iEr>iEb?iEr:iEb):(iEg>iEb?iEg:iEb);
+
+ if( arrayOut[3] > iEr){
+ iShift = ( arrayOut[3] - iEr);
+ arrayOut[0] = (unsigned char)((((int) arrayOut[0]) * 2 + 1) >> (iShift + 1));
+ }
+ if( arrayOut[3] > iEg){
+ iShift = ( arrayOut[3]- iEg);
+ arrayOut[1] = (unsigned char)((((int) arrayOut[1]) * 2 + 1) >> (iShift + 1));
+ }
+ if( arrayOut[3] > iEb){
+ iShift = ( arrayOut[3]- iEb);
+ arrayOut[2] = (unsigned char)((((int) arrayOut[2]) * 2 + 1) >> (iShift + 1));
+ }
+}
+
+static void scale_and_emit_top(jxr_image_t image, int tx, int use_my)
+{
+ int scale = image->scaled_flag? 3 : 0;
+ int bias;
+ int round;
+ int shift_bits = image->shift_bits;
+ /* Clipping based on 8bit values. */
+ int clip_low = 0;
+ int clip_hig = 255;
+ int idx;
+ int buffer[(MAX_CHANNELS + 1)*256];
+ unsigned int bSkipColorTransform = 0;
+ memset(buffer, 0,(MAX_CHANNELS + 1)*256);
+
+
+ switch (SOURCE_BITDEPTH(image)) {
+ case 0: /* BD1WHITE1*/
+
+ case 15: /* BD1BLACK1 */
+ bias = 0;
+ round = image->scaled_flag? 4 : 0;
+ clip_low = 0;
+ clip_hig = 1;
+ break;
+ case 1: /* BD8 */
+ bias = 1 << 7;
+ round = image->scaled_flag? 3 : 0;
+ clip_low = 0;
+ clip_hig = 255;
+ break;
+ case 2: /* BD16 */
+ bias = 1 << 15;
+ round = image->scaled_flag? 4 : 0;
+ clip_low = 0;
+ clip_hig = 65535;
+ break;
+ case 3: /* BD16S */
+ bias = 0;
+ round = image->scaled_flag? 3 : 0;
+ clip_low = -32768;
+ clip_hig = 32767;
+ break;
+
+ case 6: /*BD32S */
+ bias = 0;
+ round = image->scaled_flag? 3 : 0;
+ clip_hig = 0x7fffffff;
+ clip_low = -(clip_hig + 1);
+ break;
+
+ case 4: /* BD16F */
+
+ case 7: /* BD32F */
+ bias = 0;
+ round = image->scaled_flag? 3 : 0;
+ break;
+
+ case 8: /* BD5 */
+ bias = 16;
+ round = image->scaled_flag? 3 : 0;
+ clip_hig = 31;
+ clip_low = 0;
+ break;
+
+ case 9: /* BD10 */
+ bias = 512;
+ round = image->scaled_flag? 3 : 0;
+ clip_hig = 1023;
+ clip_low = 0;
+ break;
+
+ case 10: /* BD565 */
+ bias = 32;
+ round = image->scaled_flag? 3 : 0;
+ clip_hig = 31;
+ clip_low = 0;
+ break;
+
+ case 5: /* Reserved */
+
+ default:
+ fprintf(stderr, "XXXX Don't know how to scale bit depth %d?\n", SOURCE_BITDEPTH(image));
+ bias = 0;
+ round = image->scaled_flag? 3 : 0;
+ clip_low = 0;
+ clip_hig = 255;
+ break;
+ }
+
+ DEBUG("scale_and_emit_top: scale=%d, bias=%d, round=%d, shift_bits=%d, clip_low=%d, clip_hig=%d\n",
+ scale, bias, round, shift_bits, clip_low, clip_hig);
+
+ /* Up 'til this point, the MB contains 4x4 sub-blocks. We are
+ now ready for the MB to contain only raster data within, so
+ this loop rasterizes all the MBs in this strip. */
+ for (idx = 0 ; idx < (int) EXTENDED_WIDTH_BLOCKS(image); idx += 1) {
+
+ int ch;
+ int*dp = image->strip[0].up3[idx].data;
+ unblock_shuffle444(dp);
+ for (ch = 1 ; ch < image->num_channels ; ch += 1) {
+ dp = image->strip[ch].up3[idx].data;
+ switch (image->use_clr_fmt) {
+ case 1: /* YUV420 */
+ unblock_shuffle420(dp);
+ break;
+ case 2: /* YUV422 */
+ unblock_shuffle422(dp);
+ break;
+ default:
+ unblock_shuffle444(dp);
+ break;
+ }
+ }
+ }
+
+ for (idx = 0 ; idx < (int) EXTENDED_WIDTH_BLOCKS(image); idx += 1) {
+
+ int ch;
+#if defined(DETAILED_DEBUG) && 1
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ int count = 256;
+ if (ch > 0 && image->use_clr_fmt==2/*YUV422*/)
+ count = 128;
+ if (ch > 0 && image->use_clr_fmt==1/*YUV420*/)
+ count = 64;
+
+ DEBUG("image yuv mx=%3d my=%3d ch=%d:", idx, use_my-3, ch);
+ int jdx;
+ for (jdx = 0 ; jdx < count ; jdx += 1) {
+ if (jdx%8 == 0 && jdx != 0)
+ DEBUG("\n%*s", 29, "");
+ DEBUG(" %08x", image->strip[ch].up3[idx].data[jdx]);
+ }
+ DEBUG("\n");
+ }
+#endif
+
+ if(SOURCE_CLR_FMT(image) == JXR_OCF_YUV420 || SOURCE_CLR_FMT(image) == JXR_OCF_YUV422 || SOURCE_CLR_FMT(image) == JXR_OCF_YUV444 || SOURCE_CLR_FMT(image) == JXR_OCF_CMYKDIRECT)
+ {
+ bSkipColorTransform = 1;
+ }
+
+ /* Perform transform in place, if needed. */
+ /* For YCC output, no color transform is needed */
+ if(!bSkipColorTransform)
+ {
+ switch (image->use_clr_fmt ) {
+
+ case 1: /* YUV420 */
+ yuv420_to_yuv444(image, use_my, idx);
+ yuv444_to_rgb(image, idx);
+ break;
+
+ case 2: /* YUV422 */
+ yuv422_to_yuv444(image, idx);
+ yuv444_to_rgb(image, idx);
+ break;
+
+ case 3: /* YUV444 */
+ yuv444_to_rgb(image, idx);
+ break;
+
+ case 4: /* CMYK */
+ yuvk_to_cmyk(image, idx);
+ break;
+ }
+ }
+
+ /* The strip data is now in the output color space. */
+
+ /* AddBias and ComputeScaling */
+ if (image->use_clr_fmt == 4 && SOURCE_CLR_FMT(image) != JXR_OCF_CMYKDIRECT/*CMYK*/) {
+ /* The CMYK format has a different and unique set
+ of bias/rounding calculations. Treat it as a
+ special case. And treat the K plane even more
+ special. */
+ int*dp;
+ int jdx;
+ for (ch = 0 ; ch < 3 ; ch += 1) {
+ dp = image->strip[ch].up3[idx].data;
+ for (jdx = 0 ; jdx < 256 ; jdx += 1) {
+ dp[jdx] = (dp[jdx] + ((bias>>(shift_bits+1))<<scale) + round) >> scale;
+ dp[jdx] <<= shift_bits;
+ if (dp[jdx] > clip_hig)
+ dp[jdx] = clip_hig;
+ if (dp[jdx] < clip_low)
+ dp[jdx] = clip_low;
+ }
+ }
+ dp = image->strip[3].up3[idx].data;
+ for (jdx = 0 ; jdx < 256 ; jdx += 1) {
+ dp[jdx] = (dp[jdx] - ((bias>>(shift_bits+1))<<scale) + round) >> scale;
+ dp[jdx] <<= shift_bits;
+ if (dp[jdx] > clip_hig)
+ dp[jdx] = clip_hig;
+ if (dp[jdx] < clip_low)
+ dp[jdx] = clip_low;
+ }
+ }
+ else
+ {
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ /* PostScalingInt and clip, 16s and 32s */
+ if( SOURCE_BITDEPTH(image)!= JXR_BD565 && SOURCE_BITDEPTH(image) != JXR_BD16F && SOURCE_BITDEPTH(image) != JXR_BD32F && SOURCE_CLR_FMT(image) != JXR_OCF_RGBE)
+ {
+ int*dp = image->strip[ch].up3[idx].data;
+ int jdx;
+ for (jdx = 0 ; jdx < 256 ; jdx += 1) {
+ dp[jdx] = (dp[jdx] + ((bias>>shift_bits)<<scale) + round) >> scale;
+ dp[jdx] <<= shift_bits;
+ if (dp[jdx] > clip_hig)
+ dp[jdx] = clip_hig;
+ if (dp[jdx] < clip_low)
+ dp[jdx] = clip_low;
+ }
+#if defined(DETAILED_DEBUG) && 0
+ DEBUG("scale_and_emit: block at mx=%d, my=%d, ch=%d:", idx, use_my-3, ch);
+ for (jdx = 0 ; jdx < 256 ; jdx += 1) {
+ if (jdx%8 == 0 && jdx > 0)
+ DEBUG("\n%*s:", 41, "");
+ DEBUG(" %04x", dp[jdx]);
+ }
+ DEBUG("\n");
+#endif
+ }
+ else if(SOURCE_BITDEPTH(image) == JXR_BD565)
+ {
+ /* Special case where R and B have different clip thresholds from G */
+ int*dp = image->strip[ch].up3[idx].data;
+ int jdx;
+ assert(image->num_channels == 3);
+ if(ch != 1)
+ {
+ clip_hig = 31;
+ clip_low = 0;
+ }
+ else
+ {
+ clip_hig = 63;
+ clip_low = 0;
+ }
+ for (jdx = 0 ; jdx < 256 ; jdx += 1) {
+ if(ch == 1)
+ dp[jdx] = (dp[jdx] + ((bias)<<scale) + round) >> scale;
+ else
+ dp[jdx] = (dp[jdx] + ((bias)<<scale) + round) >> (scale + 1);
+ if (dp[jdx] > clip_hig)
+ dp[jdx] = clip_hig;
+ if (dp[jdx] < clip_low)
+ dp[jdx] = clip_low;
+ }
+ }
+
+ /* PostScalingFl */
+ else
+ {
+ int* dp = image->strip[ch].up3[idx].data;
+ int jdx;
+ if(SOURCE_BITDEPTH(image) == JXR_BD16F || SOURCE_BITDEPTH(image) == JXR_BD32F)
+ {
+ for (jdx = 0 ; jdx < 256 ; jdx += 1) {
+ dp[jdx] = (dp[jdx] + round) >> scale;
+ dp[jdx] = PostScalingFloat(dp[jdx], image->exp_bias, image->len_mantissa, SOURCE_BITDEPTH(image));
+ }
+ }
+ else /* RGBE : PostScalingFl2 requires one extra sample per pixel - Write directly into buffer */
+ {
+ int *dp0 = image->strip[0].up3[idx].data;
+ int *dp1 = image->strip[1].up3[idx].data;
+ int *dp2 = image->strip[2].up3[idx].data;
+ assert(image->num_channels == 3);
+ assert(ch == 0);
+
+ for (jdx = 0 ; jdx < 256 ; jdx += 1) {
+ /* There is no bias in this case */
+ int idp0 = (dp0[jdx] + round) >> scale;
+ int idp1 = (dp1[jdx] + round) >> scale;
+ int idp2 = (dp2[jdx] + round) >> scale;
+
+ int arrIn[3] = {idp0, idp1, idp2};
+
+ PostScalingFl2(buffer + (image->num_channels + 1) * jdx, arrIn);
+ ch = 3;/* We have taken care of all channels in one go */
+ }
+
+ }
+
+
+
+#if defined(DETAILED_DEBUG) && 0
+ DEBUG("scale_and_emit: block at mx=%d, my=%d, ch=%d:", idx, use_my-3, ch);
+ for (jdx = 0 ; jdx < 256 ; jdx += 1) {
+ if (jdx%8 == 0 && jdx > 0)
+ DEBUG("\n%*s:", 41, "");
+ DEBUG(" %04x", dp[jdx]);
+ }
+ DEBUG("\n");
+#endif
+ }
+ }
+ }
+
+ if ( image->primary == 1 ) { /* alpha channel output is combined with primary channel */
+ int px;
+ int channels = image->num_channels;
+
+ if(!bSkipColorTransform) /* Interleave channels in buffer */
+ {
+ if (ALPHACHANNEL_FLAG(image))
+ channels ++;
+
+ for (px = 0 ; px < 256 && (SOURCE_CLR_FMT(image) != JXR_OCF_RGBE) ; px += 1) /*RGBE is a special case that is already taken care of */
+ for (ch = 0 ; ch < image->num_channels ; ch += 1)
+ buffer[channels*px + ch] = image->strip[ch].up3[idx].data[px];
+
+ if (ALPHACHANNEL_FLAG(image))
+ for (px = 0 ; px < 256 ; px += 1)
+ buffer[channels*px + image->num_channels] = image->alpha->strip[0].up3[idx].data[px];
+ }
+ else
+ {
+ int size = 256*sizeof(uint32_t);
+ int i = 0;
+ for(i = 0; i < image->num_channels; i ++)
+ {
+ memcpy(((uint8_t *)buffer + i*size), image->strip[i].up3[idx].data, size);
+
+ }
+ if(ALPHACHANNEL_FLAG(image))
+ memcpy(((uint8_t *)buffer) + image->num_channels*size, image->alpha->strip[0].up3[idx].data, size);
+ }
+
+
+ _jxr_send_mb_to_output(image, idx, use_my-3, buffer);
+ }
+ }
+}
+
+/*
+* The tile_row_buffer holds flushed mb data in image raster order,
+* along with other per-mb data. This is in support of SPATIAL processing.
+*/
+static void rflush_to_tile_buffer(jxr_image_t image, int tx, int my)
+{
+ int format_scale = 256;
+ int mx;
+ DEBUG("rflush_mb_strip: rflush_to_tile_buffer tx=%d, my=%d\n", tx, my);
+
+ if (image->use_clr_fmt == 2 /* YUV422 */) {
+ format_scale = 16 + 8*15;
+ } else if (image->use_clr_fmt == 1 /* YUV420 */) {
+ format_scale = 16 + 4*15;
+ }
+
+ for (mx = 0 ; mx < (int) image->tile_column_width[tx] ; mx += 1) {
+ int off;
+ int ch;
+ DEBUG("rflush_mb_strip: rflush_to_tile_buffer tx=%d, mx=%d, CUR=0x%08x UP1=0x%08x, UP2=0x%08x, UP3=0x%08x, LP_QUANT=%d\n",
+ tx, mx, MACROBLK_CUR(image,0,tx,mx).data[0],
+ MACROBLK_UP1(image,0,tx,mx).data[0],
+ MACROBLK_UP2(image,0,tx,mx).data[0],
+ MACROBLK_UP3(image,0,tx,mx).data[0],
+ MACROBLK_CUR_LP_QUANT(image,0,tx,mx));
+
+ off = my * EXTENDED_WIDTH_BLOCKS(image) + image->tile_column_position[tx] + mx;
+ for (ch = 0; ch < image->num_channels; ch += 1) {
+ int count;
+ int idx;
+ struct macroblock_s*mb = image->mb_row_buffer[ch] + off;
+ mb->lp_quant = MACROBLK_CUR_LP_QUANT(image,ch,tx,mx);
+ mb->hp_quant = MACROBLK_CUR(image,ch,tx,mx).hp_quant;
+ count = (ch==0)? 256 : format_scale;
+ for (idx = 0 ; idx < count ; idx += 1)
+ mb->data[idx] = MACROBLK_CUR(image,ch,tx,mx).data[idx];
+ }
+ }
+}
+
+/*
+* Recover a strip of data from all but the last column of data. Skip
+* the last column because this function is called while the last
+* column is being processed.
+*/
+static void rflush_collect_mb_strip_data(jxr_image_t image, int my)
+{
+ int format_scale = 256;
+ int tx;
+
+ DEBUG("rflush_mb_strip: rflush_collect_mb_strip_data my=%d\n", my);
+
+ if (image->use_clr_fmt == 2 /* YUV422 */) {
+ format_scale = 16 + 8*15;
+ } else if (image->use_clr_fmt == 1 /* YUV420 */) {
+ format_scale = 16 + 4*15;
+ }
+
+ for (tx = 0; tx < (int) image->tile_columns-1 ; tx += 1) {
+ int mx;
+ for (mx = 0; mx < (int) image->tile_column_width[tx]; mx += 1) {
+ int off = my * EXTENDED_WIDTH_BLOCKS(image) + image->tile_column_position[tx] + mx;
+ int ch;
+ for (ch = 0; ch < image->num_channels; ch += 1) {
+ struct macroblock_s*mb = image->mb_row_buffer[ch] + off;
+ int count;
+ int idx;
+ MACROBLK_CUR_LP_QUANT(image,ch,tx,mx) = mb->lp_quant;
+ MACROBLK_CUR(image,ch,tx,mx).hp_quant = mb->hp_quant;
+ count = (ch==0)? 256 : format_scale;
+ for (idx = 0 ; idx < count; idx += 1)
+ MACROBLK_CUR(image,ch,tx,mx).data[idx] = mb->data[idx];
+ }
+ DEBUG("rflush_mb_strip: rflush_collect_mb_strip_data tx=%d, mx=%d, CUR=0x%08x UP1=0x%08x, UP2=0x%08x, UP3=0x%08x lp_quant=%d\n",
+ tx, mx, MACROBLK_CUR(image,0,tx,mx).data[0],
+ MACROBLK_UP1(image,0,tx,mx).data[0],
+ MACROBLK_UP2(image,0,tx,mx).data[0],
+ MACROBLK_UP3(image,0,tx,mx).data[0],
+ MACROBLK_CUR_LP_QUANT(image,0,tx,mx));
+ }
+ }
+}
+
+/*
+* The save_ and recover_context functions save the 3 strips of data
+* currently in the strip buffer. This is used at the end of a tile
+* row and beginning of the next tile row to save context while
+* columns of tiles are collected, and restore it when processing the
+* last tile column.
+*/
+static void rflush_save_context(jxr_image_t image)
+{
+ int format_scale = 256;
+ int tx;
+ DEBUG("rflush_mb_strip: rflush_save_context\n");
+
+ if (image->use_clr_fmt == 2 /* YUV422 */) {
+ format_scale = 16 + 8*15;
+ } else if (image->use_clr_fmt == 1 /* YUV420 */) {
+ format_scale = 16 + 4*15;
+ }
+
+ for (tx = 0; tx < (int) image->tile_columns ; tx += 1) {
+ int mx;
+ for (mx = 0; mx < (int) image->tile_column_width[tx]; mx += 1) {
+ int off0 = image->tile_column_position[tx] + mx;
+ int off1 = off0 + EXTENDED_WIDTH_BLOCKS(image);
+ int off2 = off1 + EXTENDED_WIDTH_BLOCKS(image);
+ int off3 = off2 + EXTENDED_WIDTH_BLOCKS(image);
+ int ch;
+ DEBUG("rflush_mb_strip: rflush_save_context tx=%d, mx=%d, CUR=0x%08x UP1=0x%08x, UP2=0x%08x, UP3=0x%08x\n",
+ tx, mx, MACROBLK_CUR(image,0,tx,mx).data[0],
+ MACROBLK_UP1(image,0,tx,mx).data[0],
+ MACROBLK_UP2(image,0,tx,mx).data[0],
+ MACROBLK_UP3(image,0,tx,mx).data[0]);
+ for (ch = 0; ch < image->num_channels; ch += 1) {
+ int count;
+ int idx;
+
+ image->mb_row_context[ch][off0].lp_quant = MACROBLK_CUR_LP_QUANT(image,ch,tx,mx);
+ image->mb_row_context[ch][off1].lp_quant = MACROBLK_UP1_LP_QUANT(image,ch,tx,mx);
+ image->mb_row_context[ch][off2].lp_quant = MACROBLK_UP2(image,ch,tx,mx).lp_quant;
+ image->mb_row_context[ch][off3].lp_quant = MACROBLK_UP3(image,ch,tx,mx).lp_quant;
+ image->mb_row_context[ch][off0].hp_quant = MACROBLK_CUR(image,ch,tx,mx).hp_quant;
+ image->mb_row_context[ch][off1].hp_quant = MACROBLK_UP1(image,ch,tx,mx).hp_quant;
+ image->mb_row_context[ch][off2].hp_quant = MACROBLK_UP2(image,ch,tx,mx).hp_quant;
+ image->mb_row_context[ch][off3].hp_quant = MACROBLK_UP3(image,ch,tx,mx).hp_quant;
+ count = (ch==0)? 256 : format_scale;
+ for (idx = 0 ; idx < count; idx += 1)
+ image->mb_row_context[ch][off0].data[idx] = MACROBLK_CUR(image,ch,tx,mx).data[idx];
+ for (idx = 0 ; idx < count; idx += 1)
+ image->mb_row_context[ch][off1].data[idx] = MACROBLK_UP1(image,ch,tx,mx).data[idx];
+ for (idx = 0 ; idx < count; idx += 1)
+ image->mb_row_context[ch][off2].data[idx] = MACROBLK_UP2(image,ch,tx,mx).data[idx];
+ for (idx = 0 ; idx < count; idx += 1)
+ image->mb_row_context[ch][off3].data[idx] = MACROBLK_UP3(image,ch,tx,mx).data[idx];
+ }
+ }
+ }
+}
+
+static void rflush_recover_context(jxr_image_t image)
+{
+
+ int format_scale = 256;
+ int tx;
+ DEBUG("rflush_mb_strip: recover contex\n");
+ if (image->use_clr_fmt == 2 /* YUV422 */) {
+ format_scale = 16 + 8*15;
+ } else if (image->use_clr_fmt == 1 /* YUV420 */) {
+ format_scale = 16 + 4*15;
+ }
+
+ for (tx = 0; tx < (int) image->tile_columns ; tx += 1) {
+ int mx;
+ for (mx = 0; mx < (int) image->tile_column_width[tx]; mx += 1) {
+ int off0 = image->tile_column_position[tx] + mx;
+ int off1 = off0 + EXTENDED_WIDTH_BLOCKS(image);
+ int off2 = off1 + EXTENDED_WIDTH_BLOCKS(image);
+ int off3 = off2 + EXTENDED_WIDTH_BLOCKS(image);
+ int ch;
+ for (ch = 0; ch < image->num_channels; ch += 1) {
+ int count;
+ int idx;
+ MACROBLK_CUR_LP_QUANT(image,ch,tx,mx) = image->mb_row_context[ch][off0].lp_quant;
+ MACROBLK_UP1_LP_QUANT(image,ch,tx,mx) = image->mb_row_context[ch][off1].lp_quant;
+ MACROBLK_UP2(image,ch,tx,mx).lp_quant = image->mb_row_context[ch][off2].lp_quant;
+ MACROBLK_UP3(image,ch,tx,mx).lp_quant = image->mb_row_context[ch][off3].lp_quant;
+ MACROBLK_CUR(image,ch,tx,mx).hp_quant = image->mb_row_context[ch][off0].hp_quant;
+ MACROBLK_UP1(image,ch,tx,mx).hp_quant = image->mb_row_context[ch][off1].hp_quant;
+ MACROBLK_UP2(image,ch,tx,mx).hp_quant = image->mb_row_context[ch][off2].hp_quant;
+ MACROBLK_UP3(image,ch,tx,mx).hp_quant = image->mb_row_context[ch][off3].hp_quant;
+
+ for (idx = 0 ; idx < count; idx += 1)
+ MACROBLK_CUR(image,ch,tx,mx).data[idx] = image->mb_row_context[ch][off0].data[idx];
+ for (idx = 0 ; idx < count; idx += 1)
+ MACROBLK_UP1(image,ch,tx,mx).data[idx] = image->mb_row_context[ch][off1].data[idx];
+ for (idx = 0 ; idx < count; idx += 1)
+ MACROBLK_UP2(image,ch,tx,mx).data[idx] = image->mb_row_context[ch][off2].data[idx];
+ for (idx = 0 ; idx < count; idx += 1)
+ MACROBLK_UP3(image,ch,tx,mx).data[idx] = image->mb_row_context[ch][off3].data[idx];
+ }
+ }
+ }
+}
+
+
+/*
+* When the parser calls this function, the current strip is done
+* being parsed, so it no longer needs the previous strip. Complete
+* the processing of the previous ("up") strip and arrange for it to
+* be delivered to the applications. Then shuffle the current strip to
+* the "up" position for the next round.
+*
+* cur_my is the number of the current line. If this is -1, then there
+* are no lines complete yet and this function is being called to get
+* things started.
+*/
+void _jxr_rflush_mb_strip(jxr_image_t image, int tx, int ty, int my)
+{
+ /* This is the position within the image of the current
+ line. It accounts for the current tile row. */
+ const int use_my = my + (ty>=0? image->tile_row_position[ty] : 0) - 1;
+
+ DEBUG("rflush_mb_strip: cur_my=%d, tile-x/y=%d/%d, my=%d, use_my=%d\n", image->cur_my, tx, ty, my, use_my);
+
+ if (image->tile_columns > 1 && tx >= 0) {
+ if (tx+1 < (int) image->tile_columns) {
+ /* We're actually working on a tile, and this is
+ not the last tile in the row. Deliver the data
+ to the correct tile buffer and return. */
+
+ if (my == 0 && image->cur_my >= 0) {
+ /* starting a new tile, dump previous */
+
+ if (tx == 0 && ty > 0) {
+ /* First column of a row */
+ /* Complete last line of previous row */
+ rflush_collect_mb_strip_data(image, image->cur_my);
+ /* Save previous strip context */
+ rflush_save_context(image);
+ /* Flush last column of previous row. */
+ rflush_to_tile_buffer(image, image->tile_columns-1, image->cur_my);
+ } else if (tx > 0) {
+ /* Column within a row, dump previous column */
+ rflush_to_tile_buffer(image, tx-1, image->cur_my);
+ }
+
+ } else if (image->cur_my >= 0) {
+ rflush_to_tile_buffer(image, tx, image->cur_my);
+ }
+ image->cur_my = my;
+ _jxr_r_rotate_mb_strip(image);
+ return;
+
+ } else {
+ /* We are tiling, and this is the last tile of the
+ row, so collect rows from the left tiles to
+ finish the row, and proceed to processing. */
+ if (my == 0) {
+ /* Starting last tile of row */
+ /* Flush end of previous tile */
+ rflush_to_tile_buffer(image, tx-1, image->cur_my);
+ image->cur_my = -1;
+ /* Recover previous strip context */
+ if (ty > 0) {
+ rflush_recover_context(image);
+ }
+ } else if (my <= (int) image->tile_row_height[ty]) {
+ rflush_collect_mb_strip_data(image, image->cur_my);
+ }
+ }
+ }
+
+
+ if (use_my >= 1) {
+ int ch;
+
+ /* Dequantize the PREVIOUS strip of macroblocks DC and LP. */
+
+ /* Reverse transform the DC/LP to 16 DC values. */
+
+ for (ch = 0 ; ch < image->num_channels ; ch += 1)
+ IPCT_level1_up1(image, use_my, ch);
+
+ if (use_my >= 2) {
+ if (OVERLAP_INFO(image) >= 2)
+ for (ch = 0 ; ch < image->num_channels ; ch += 1)
+ overlap_level1_up2(image, use_my, ch);
+
+ /* Do the second level IPCT transform to include HP values. */
+ for (ch = 0 ; ch < image->num_channels ; ch += 1)
+ IPCT_level2_up2(image,use_my, ch);
+
+ if (use_my >= 3) {
+
+ /* Do the second level post filter */
+ if (OVERLAP_INFO(image) >= 1)
+ for (ch = 0 ; ch < image->num_channels ; ch += 1)
+ overlap_level2_up3(image, use_my, ch);
+
+ /* The reverse transformation is complete for the
+ PREVIOUS strip, so perform the "Output Formatting"
+ and deliver the data for the application. */
+
+ scale_and_emit_top(image, tx, use_my);
+ }
+ }
+
+ /* read lwf test flag into image container */
+ if (image->lwf_test == 0)
+ image->lwf_test = _jxr_read_lwf_test_flag();
+
+ }
+
+ /* Now completely done with strip_up. Rotate the storage to
+ strip_down. */
+ image->cur_my = my;
+
+ _jxr_r_rotate_mb_strip(image);
+}
+
+/*
+* The input to this function is 256 samples arranged like this:
+*
+* DC..DC (16 DC values) HP..HP (240 HP values)
+*
+* Shuffle the values so that there is 1 DC, then 15 HP, and so on 16
+* times. This prepares the array for 16 calls to the 4x4IPCT transform.
+*/
+static void dclphp_shuffle(int*data, int dclp_count)
+{
+ int tmp[256];
+ int dc, hp, dst;
+ assert(dclp_count <= 16);
+
+ for (dc=0, hp=16, dst=0; dc<dclp_count ; ) {
+ int idx;
+ tmp[dst++] = data[dc++];
+ for (idx = 0 ; idx < 15 ; idx += 1)
+ tmp[dst++] = data[hp++];
+ }
+
+ assert(dst == 16*dclp_count);
+ assert(dc == dclp_count);
+ assert(hp == 16+15*dclp_count);
+
+ for (dst = 0 ; dst<256 ; dst+=1)
+ data[dst] = tmp[dst];
+}
+
+/*
+* The input to this function is 256 intensities arranged as blocks,
+* with each 4x4 block in raster order is together, i.e.
+*
+* 00..0011..1122..22...
+*
+* It reorders the values into a raster order that is not blocked:
+*
+* 0000111122223333
+* 0000111122223333
+* 0000111122223333, etc.
+*/
+static void unblock_shuffle444(int*data)
+{
+ int tmp[256];
+
+ int idx;
+ for (idx = 0 ; idx < 256 ; idx += 4) {
+ int blk = idx/16;
+ int mbx = blk%4;
+ int mby = blk/4;
+ int pix = idx%16;
+ int py = pix/4;
+
+ int ptr = 16*4*mby + 4*mbx + 16*py;
+ tmp[ptr+0] = data[idx+0];
+ tmp[ptr+1] = data[idx+1];
+ tmp[ptr+2] = data[idx+2];
+ tmp[ptr+3] = data[idx+3];
+ }
+
+ for (idx = 0 ; idx < 256 ; idx += 1)
+ data[idx] = tmp[idx];
+}
+
+/*
+* 0 1 2 3 16 17 18 19
+* 4 5 6 7 20 21 22 23
+* 8 9 10 11 24 25 26 27
+* 12 13 14 15 28 29 30 31
+* 32 33 34 35 48 49 50 51
+* 36 37 38 39 52 53 54 55
+* 40 41 42 43 56 57 58 59
+* 44 45 46 47 60 61 62 63 ...
+*/
+static void unblock_shuffle422(int*data)
+{
+ int tmp[128];
+
+ int idx;
+ for (idx = 0 ; idx < 128 ; idx += 4) {
+ int blk = idx/16;
+ int mbx = blk%2;
+ int mby = blk/2;
+ int pix = idx%16;
+ int py = pix/4;
+
+ int ptr = 16*2*mby + 4*mbx + 8*py;
+ tmp[ptr+0] = data[idx+0];
+ tmp[ptr+1] = data[idx+1];
+ tmp[ptr+2] = data[idx+2];
+ tmp[ptr+3] = data[idx+3];
+ }
+
+ for (idx = 0 ; idx < 128 ; idx += 1)
+ data[idx] = tmp[idx];
+}
+
+/*
+* 0 1 2 3 16 17 18 19
+* 4 5 6 7 20 21 22 23
+* 8 9 10 11 24 25 26 27
+* 12 13 14 15 28 29 30 31
+* 32 33 34 35 48 49 50 51
+* 36 37 38 39 52 53 54 55
+* 40 41 42 43 56 57 58 59
+* 44 45 46 47 60 61 62 63
+*/
+static void unblock_shuffle420(int*data)
+{
+ int tmp[64];
+
+ int idx;
+ for (idx = 0 ; idx < 64 ; idx += 4) {
+ int blk = idx/16;
+ int mbx = blk%2;
+ int mby = blk/2;
+ int pix = idx%16;
+ int py = pix/4;
+
+ int ptr = 16*2*mby + 4*mbx + 8*py;
+ tmp[ptr+0] = data[idx+0];
+ tmp[ptr+1] = data[idx+1];
+ tmp[ptr+2] = data[idx+2];
+ tmp[ptr+3] = data[idx+3];
+ }
+
+ for (idx = 0 ; idx < 64 ; idx += 1)
+ data[idx] = tmp[idx];
+}
+
+void _jxr_r_rotate_mb_strip(jxr_image_t image)
+{
+ if(image->primary) {
+ int ch;
+
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ struct macroblock_s*tmp = image->strip[ch].up3;
+ image->strip[ch].up3 = image->strip[ch].up2;
+ image->strip[ch].up2 = image->strip[ch].up1;
+ image->strip[ch].up1 = image->strip[ch].cur;
+ image->strip[ch].cur = tmp;
+ }
+
+ _jxr_clear_strip_cur(image);
+
+ if (ALPHACHANNEL_FLAG(image)) {
+ struct macroblock_s*tmp = image->alpha->strip[0].up3;
+ image->alpha->strip[0].up3 = image->alpha->strip[0].up2;
+ image->alpha->strip[0].up2 = image->alpha->strip[0].up1;
+ image->alpha->strip[0].up1 = image->alpha->strip[0].cur;
+ image->alpha->strip[0].cur = tmp;
+ _jxr_clear_strip_cur(image->alpha);
+ }
+ }
+}
+
+
+/*
+* $Log: r_strip.c,v $
+* Revision 1.53 2009/05/29 12:00:00 microsoft
+* Reference Software v1.6 updates.
+*
+* Revision 1.52 2009/04/13 12:00:00 microsoft
+* Reference Software v1.5 updates.
+*
+* Revision 1.51 2008/03/24 18:06:56 steve
+* Imrpove DEBUG messages around quantization.
+*
+* Revision 1.50 2008/03/20 22:38:53 steve
+* Use MB HPQP instead of first HPQP in decode.
+*
+* Revision 1.49 2008/03/18 21:09:11 steve
+* Fix distributed color prediction.
+*
+* Revision 1.48 2008/03/17 23:48:12 steve
+* Bias and Scaling for CMYK
+*
+* Revision 1.47 2008/03/17 21:48:56 steve
+* CMYK decode support
+*
+* Revision 1.46 2008/03/14 17:08:51 gus
+* *** empty log message ***
+*
+* Revision 1.45 2008/03/13 17:49:31 steve
+* Fix problem with YUV422 CBP prediction for UV planes
+*
+* Add support for YUV420 encoding.
+*
+* Revision 1.44 2008/03/11 22:12:49 steve
+* Encode YUV422 through DC.
+*
+* Revision 1.43 2008/03/05 06:58:10 gus
+* *** empty log message ***
+*
+* Revision 1.42 2008/03/03 23:33:53 steve
+* Implement SHIFT_BITS functionality.
+*
+* Revision 1.41 2008/03/02 18:35:27 steve
+* Add support for BD16
+*
+* Revision 1.40 2008/02/26 23:52:44 steve
+* Remove ident for MS compilers.
+*
+* Revision 1.39 2008/02/01 22:49:53 steve
+* Handle compress of YUV444 color DCONLY
+*
+* Revision 1.38 2008/01/08 23:23:18 steve
+* Clean up some DEBUG messages.
+*
+* Revision 1.37 2008/01/04 17:07:35 steve
+* API interface for setting QP values.
+*
+* Revision 1.36 2007/11/26 01:47:15 steve
+* Add copyright notices per MS request.
+*
+* Revision 1.35 2007/11/22 19:02:05 steve
+* More fixes of color plane buffer sizes.
+*
+* Revision 1.34 2007/11/22 02:51:04 steve
+* Fix YUV422 strip save byte count - buffer overrun
+*
+* Revision 1.33 2007/11/21 23:26:14 steve
+* make all strip buffers store MB data.
+*
+* Revision 1.32 2007/11/21 00:34:30 steve
+* Rework spatial mode tile macroblock shuffling.
+*
+* Revision 1.31 2007/11/20 17:08:02 steve
+* Fix SPATIAL processing of QUANT values for color.
+*
+* Revision 1.30 2007/11/16 21:33:48 steve
+* Store MB Quant, not qp_index.
+*
+* Revision 1.29 2007/11/16 20:03:57 steve
+* Store MB Quant, not qp_index.
+*
+* Revision 1.28 2007/11/12 23:21:55 steve
+* Infrastructure for frequency mode ordering.
+*
+* Revision 1.27 2007/11/09 01:18:58 steve
+* Stub strip input processing.
+*
+* Revision 1.26 2007/11/06 21:45:04 steve
+* Fix MB of previous tile in row.
+*
+* Revision 1.25 2007/11/06 01:39:22 steve
+* Do not collect strip data for pad strips.
+*
+* Revision 1.24 2007/11/05 02:01:12 steve
+* Add support for mixed row/column tiles.
+*
+* Revision 1.23 2007/11/02 21:06:07 steve
+* Filtering when tile rows are present.
+*
+* Revision 1.22 2007/11/02 00:19:06 steve
+* Fix Multiple rows of tiles strip flush.
+*
+* Revision 1.21 2007/11/01 21:09:40 steve
+* Multiple rows of tiles.
+*
+* Revision 1.20 2007/10/30 21:32:46 steve
+* Support for multiple tile columns.
+*
+* Revision 1.19 2007/10/23 00:34:12 steve
+* Level1 filtering for YUV422 and YUV420
+*
+* Revision 1.18 2007/10/22 22:33:12 steve
+* Level2 filtering for YUV422
+*
+* Revision 1.17 2007/10/22 21:52:37 steve
+* Level2 filtering for YUV420
+*
+* Revision 1.16 2007/10/19 22:07:36 steve
+* Clean up YUV420 to YUV444 conversion corner cases.
+*
+* Revision 1.15 2007/10/19 20:48:53 steve
+* Convert YUV420 to YUV444 works.
+*
+* Revision 1.14 2007/10/17 23:43:20 steve
+* Add support for YUV420
+*
+* Revision 1.13 2007/10/01 20:39:34 steve
+* Add support for YUV422 LP bands.
+*
+* Revision 1.12 2007/09/20 18:04:11 steve
+* support render of YUV422 images.
+*
+* Revision 1.11 2007/09/12 01:10:22 steve
+* Fix rounding/floor/ceil of YUV to RGB transform.
+*
+* Revision 1.10 2007/09/11 00:40:06 steve
+* Fix rendering of chroma to add the missing *2.
+* Fix handling of the chroma LP samples
+* Parse some of the HP CBP data in chroma.
+*
+* Revision 1.9 2007/09/10 23:02:48 steve
+* Scale chroma channels?
+*
+* Revision 1.8 2007/09/08 01:01:44 steve
+* YUV444 color parses properly.
+*
+* Revision 1.7 2007/09/04 19:10:46 steve
+* Finish level1 overlap filtering.
+*
+* Revision 1.6 2007/08/15 01:54:11 steve
+* Add level2 filter to decoder.
+*
+* Revision 1.5 2007/08/13 22:55:12 steve
+* Cleanup rflush_md_strip function.
+*
+* Revision 1.4 2007/08/02 22:48:27 steve
+* Add missing clip of calculated values.
+*
+* Revision 1.3 2007/07/21 00:25:48 steve
+* snapshot 2007 07 20
+*
+* Revision 1.2 2007/07/11 00:53:36 steve
+* HP adaptation and precition corrections.
+*
+* Revision 1.1 2007/06/28 20:03:11 steve
+* LP processing seems to be OK now.
+*
+*/
+
diff --git a/jpegxr/r_tile_frequency.c b/jpegxr/r_tile_frequency.c
new file mode 100644
index 000000000..5b70e3db1
--- /dev/null
+++ b/jpegxr/r_tile_frequency.c
@@ -0,0 +1,699 @@
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+***********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: r_tile_frequency.c,v 1.14 2008/03/18 21:34:04 steve Exp $")
+#else
+#ident "$Id: r_tile_frequency.c,v 1.14 2008/03/18 21:34:04 steve Exp $"
+#endif
+
+# include "jxr_priv.h"
+# include <assert.h>
+
+static void backup_dc_strip(jxr_image_t image, int tx, int ty, int my);
+static void backup_dclp_strip(jxr_image_t image, int tx, int ty, int my);
+static void backup_hp_strip(jxr_image_t image, int tx, int ty, int my);
+static void recover_dc_strip(jxr_image_t image, int tx, int ty, int my);
+static void recover_dclp_strip(jxr_image_t image, int tx, int ty, int my);
+static void recover_dclphp_strip(jxr_image_t image, int tx, int ty, int my);
+
+int _jxr_r_TILE_DC(jxr_image_t image, struct rbitstream*str,
+ unsigned tx, unsigned ty)
+{
+ unsigned mx, my;
+ unsigned mb_height;
+ unsigned mb_width;
+ unsigned char s0, s1, s2, s3;
+ DEBUG("START TILE_DC at tile=[%u %u] bitpos=%zu\n", tx, ty, _jxr_rbitstream_bitpos(str));
+
+ /* TILE_STARTCODE == 1 */
+ s0 = _jxr_rbitstream_uint8(str); /* 0x00 */
+ s1 = _jxr_rbitstream_uint8(str); /* 0x00 */
+ s2 = _jxr_rbitstream_uint8(str); /* 0x01 */
+ s3 = _jxr_rbitstream_uint8(str); /* reserved */
+ DEBUG(" TILE_STARTCODE == %02x %02x %02x (reserved: %02x)\n", s0, s1, s2, s3);
+
+ _jxr_r_TILE_HEADER_DC(image, str, 0 /* alpha */, tx, ty);
+ if (ALPHACHANNEL_FLAG(image))
+ _jxr_r_TILE_HEADER_DC(image->alpha, str, 1, tx, ty);
+
+
+ /* Now form and write out all the compressed data for the
+ tile. This involves scanning the macroblocks, and the
+ blocks within the macroblocks, generating bits as we go. */
+
+ mb_height = EXTENDED_HEIGHT_BLOCKS(image);
+ mb_width = EXTENDED_WIDTH_BLOCKS(image);
+
+ if (TILING_FLAG(image)) {
+ mb_height = image->tile_row_height[ty];
+ mb_width = image->tile_column_width[tx];
+ }
+
+ for (my = 0 ; my < mb_height ; my += 1) {
+ _jxr_r_rotate_mb_strip(image);
+ image->cur_my = my;
+ for (mx = 0 ; mx < mb_width ; mx += 1) {
+ _jxr_r_MB_DC(image, str, 0, tx, ty, mx, my);
+ if (image->bands_present == 3 /* DCONLY */)
+ _jxr_complete_cur_dclp(image, tx, mx, my);
+ if (ALPHACHANNEL_FLAG(image)) {
+ _jxr_r_MB_DC(image->alpha, str, 1, tx, ty, mx, my);
+ if (image->alpha->bands_present == 3 /* DCONLY */)
+ _jxr_complete_cur_dclp(image->alpha, tx, mx, my);
+ }
+ }
+
+ if (ALPHACHANNEL_FLAG(image))
+ backup_dc_strip(image->alpha, tx, ty, my);
+
+ backup_dc_strip(image, tx, ty, my);
+ }
+
+ _jxr_rbitstream_syncbyte(str);
+ DEBUG("END TILE_DC\n");
+
+ return 0;
+}
+
+int _jxr_r_TILE_LP(jxr_image_t image, struct rbitstream*str,
+ unsigned tx, unsigned ty)
+{
+ unsigned mx, my;
+ unsigned plane_idx, num_planes;
+ unsigned mb_height;
+ unsigned mb_width;
+ unsigned char s0, s1, s2, s3;
+ DEBUG("START TILE_LOWPASS at tile=[%u %u] bitpos=%zu\n", tx, ty, _jxr_rbitstream_bitpos(str));
+
+ /* TILE_STARTCODE == 1 */
+ s0 = _jxr_rbitstream_uint8(str); /* 0x00 */
+ s1 = _jxr_rbitstream_uint8(str); /* 0x00 */
+ s2 = _jxr_rbitstream_uint8(str); /* 0x01 */
+ s3 = _jxr_rbitstream_uint8(str); /* reserved */
+ DEBUG(" TILE_STARTCODE == %02x %02x %02x (reserved: %02x)\n", s0, s1, s2, s3);
+ if (s0 != 0x00 || s1 != 0x00 || s2 != 0x01) {
+ DEBUG(" TILE_LOWPASS ERROR: Invalid marker.\n");
+ return JXR_EC_ERROR;
+ }
+
+ _jxr_r_TILE_HEADER_LOWPASS(image, str, 0 /* alpha */, tx, ty);
+ if (ALPHACHANNEL_FLAG(image))
+ _jxr_r_TILE_HEADER_LOWPASS(image->alpha, str, 1, tx, ty);
+
+ /* Now form and write out all the compressed data for the
+ tile. This involves scanning the macroblocks, and the
+ blocks within the macroblocks, generating bits as we go. */
+
+ mb_height = EXTENDED_HEIGHT_BLOCKS(image);
+ mb_width = EXTENDED_WIDTH_BLOCKS(image);
+
+ if (TILING_FLAG(image)) {
+ mb_height = image->tile_row_height[ty];
+ mb_width = image->tile_column_width[tx];
+ }
+
+ num_planes = ((ALPHACHANNEL_FLAG(image)) ? 2 : 1);
+ for (my = 0 ; my < mb_height ; my += 1) {
+ _jxr_r_rotate_mb_strip(image);
+ if (ALPHACHANNEL_FLAG(image)) {
+ image->alpha->cur_my = my;
+ recover_dc_strip(image->alpha, tx, ty, my);
+ }
+ image->cur_my = my;
+ recover_dc_strip(image, tx, ty, my);
+
+ for (mx = 0 ; mx < mb_width ; mx += 1)
+ for (plane_idx = 0; plane_idx < num_planes; plane_idx ++) {
+ /* The qp_index_lp table goes only into channel 0 */
+ int qp_index_lp = 0;
+ int ch;
+ jxr_image_t plane = (plane_idx == 0 ? image : image->alpha);
+
+ if (!plane->lp_use_dc_qp && plane->num_lp_qps>1) {
+ qp_index_lp = _jxr_DECODE_QP_INDEX(str, plane->num_lp_qps);
+ DEBUG(" DECODE_QP_INDEX(%d) --> %u\n", plane->num_lp_qps, qp_index_lp);
+ }
+ for (ch = 0 ; ch < plane->num_channels ; ch += 1) {
+ MACROBLK_CUR_LP_QUANT(plane,ch,tx,mx) = qp_index_lp;
+ DEBUG(" LP_QUANT for MBx=%d ch=%d is %d\n", mx, ch, MACROBLK_CUR_LP_QUANT(plane,ch,tx,mx));
+ }
+ _jxr_r_MB_LP(plane, str, 0, tx, ty, mx, my);
+ if (plane->bands_present != 3 /* !DCONLY */)
+ _jxr_complete_cur_dclp(plane, tx, mx, my);
+
+ }
+ if (ALPHACHANNEL_FLAG(image))
+ backup_dclp_strip(image->alpha, tx, ty, my);
+ backup_dclp_strip(image, tx, ty, my);
+ }
+
+ _jxr_rbitstream_syncbyte(str);
+ DEBUG("END TILE_LOWPASS\n");
+ return 0;
+}
+
+int _jxr_r_TILE_HP(jxr_image_t image, struct rbitstream*str,
+ unsigned tx, unsigned ty)
+{
+ unsigned mx, my;
+ unsigned plane_idx, num_planes;
+ unsigned mb_height;
+ unsigned mb_width;
+ unsigned char s0, s1, s2, s3;
+ DEBUG("START TILE_HIGHPASS at tile=[%u %u] bitpos=%zu\n", tx, ty, _jxr_rbitstream_bitpos(str));
+
+ /* TILE_STARTCODE == 1 */
+ s0 = _jxr_rbitstream_uint8(str); /* 0x00 */
+ s1 = _jxr_rbitstream_uint8(str); /* 0x00 */
+ s2 = _jxr_rbitstream_uint8(str); /* 0x01 */
+ s3 = _jxr_rbitstream_uint8(str); /* reserved */
+ DEBUG(" TILE_STARTCODE == %02x %02x %02x (reserved: %02x)\n", s0, s1, s2, s3);
+ if (s0 != 0x00 || s1 != 0x00 || s2 != 0x01) {
+ DEBUG(" TILE_HIGHPASS ERROR: Invalid marker.\n");
+ return JXR_EC_ERROR;
+ }
+
+ _jxr_r_TILE_HEADER_HIGHPASS(image, str, 0 /* alpha */, tx, ty);
+ if (ALPHACHANNEL_FLAG(image))
+ _jxr_r_TILE_HEADER_HIGHPASS(image->alpha, str, 1, tx, ty);
+
+ /* Now form and write out all the compressed data for the
+ tile. This involves scanning the macroblocks, and the
+ blocks within the macroblocks, generating bits as we go. */
+
+ mb_height = EXTENDED_HEIGHT_BLOCKS(image);
+ mb_width = EXTENDED_WIDTH_BLOCKS(image);
+
+ if (TILING_FLAG(image)) {
+ mb_height = image->tile_row_height[ty];
+ mb_width = image->tile_column_width[tx];
+ }
+
+ num_planes = ((ALPHACHANNEL_FLAG(image)) ? 2 : 1);
+ for (my = 0 ; my < mb_height ; my += 1) {
+ _jxr_r_rotate_mb_strip(image);
+
+ if (ALPHACHANNEL_FLAG(image)) {
+ image->alpha->cur_my = my;
+ recover_dclp_strip(image->alpha, tx, ty, my);
+ }
+ image->cur_my = my;
+ recover_dclp_strip(image, tx, ty, my);
+
+ for (mx = 0 ; mx < mb_width ; mx += 1)
+ for (plane_idx = 0; plane_idx < num_planes; plane_idx ++) {
+ /* The qp_index_hp table goes only into channel 0 */
+ int qp_index_hp = 0;
+ int ch;
+ int rc;
+ jxr_image_t plane = (plane_idx == 0 ? image : image->alpha);
+ if (plane->num_hp_qps>1) {
+ if (!plane->hp_use_lp_qp)
+ qp_index_hp = _jxr_DECODE_QP_INDEX(str, plane->num_hp_qps);
+ else
+ qp_index_hp = MACROBLK_CUR_LP_QUANT(plane,0,tx,mx);
+ }
+ DEBUG(" HP_QP_INDEX for MBx=%d is %d\n", mx, qp_index_hp);
+ for (ch = 0 ; ch < plane->num_channels ; ch += 1) {
+ MACROBLK_CUR_HP_QUANT(plane,ch,tx,mx) = plane->hp_quant_ch[ch][qp_index_hp];
+ DEBUG(" HP_QUANT for MBx=%d ch=%d is %d\n", mx, ch, MACROBLK_CUR_HP_QUANT(plane,ch,tx,mx));
+ }
+
+ rc = _jxr_r_MB_CBP(plane, str, 0, tx, ty, mx, my);
+ if (rc < 0) {
+ DEBUG("r_MB_CBP returned ERROR rc=%d\n", rc);
+ return rc;
+ }
+ rc = _jxr_r_MB_HP(plane, str, 0, tx, ty, mx, my);
+ if (rc < 0) {
+ DEBUG("r_MB_HP returned ERROR rc=%d\n", rc);
+ return rc;
+ }
+ }
+ if (ALPHACHANNEL_FLAG(image))
+ backup_hp_strip(image->alpha, tx, ty, my);
+ backup_hp_strip(image, tx, ty, my);
+ }
+
+ _jxr_rbitstream_syncbyte(str);
+ DEBUG("END TILE_HIGHPASS\n");
+ return 0;
+}
+
+int _jxr_r_TILE_FLEXBITS(jxr_image_t image, struct rbitstream*str,
+ unsigned tx, unsigned ty)
+{
+ int mx, my;
+ int plane_idx, num_planes;
+ unsigned mb_height;
+ unsigned mb_width;
+ int use_num_channels;
+ unsigned char s0, s1, s2, s3;
+
+ DEBUG("START TILE_FLEXBITS at tile=[%u %u] bitpos=%zu\n", tx, ty, _jxr_rbitstream_bitpos(str));
+
+ /* TILE_STARTCODE == 1 */
+ s0 = _jxr_rbitstream_uint8(str); /* 0x00 */
+ s1 = _jxr_rbitstream_uint8(str); /* 0x00 */
+ s2 = _jxr_rbitstream_uint8(str); /* 0x01 */
+ s3 = _jxr_rbitstream_uint8(str); /* reserved */
+ DEBUG(" TILE_STARTCODE == %02x %02x %02x (reserved: %02x)\n", s0, s1, s2, s3);
+ if (s0 != 0x00 || s1 != 0x00 || s2 != 0x01) {
+ DEBUG(" TILE_FLEXBITS ERROR: Invalid marker.\n");
+ return JXR_EC_ERROR;
+ }
+
+ image->trim_flexbits = 0;
+ if (TRIM_FLEXBITS_FLAG(image)) {
+ image->trim_flexbits =_jxr_rbitstream_uint4(str);
+ DEBUG(" TRIM_FLEXBITS = %u\n", image->trim_flexbits);
+ }
+
+ use_num_channels = image->num_channels;
+ if (image->use_clr_fmt == 1/*YUV420*/ || image->use_clr_fmt == 2/*YUV422*/)
+ use_num_channels = 1;
+
+ /* Now form and write out all the compressed data for the
+ tile. This involves scanning the macroblocks, and the
+ blocks within the macroblocks, generating bits as we go. */
+
+ mb_height = EXTENDED_HEIGHT_BLOCKS(image);
+ mb_width = EXTENDED_WIDTH_BLOCKS(image);
+
+ if (TILING_FLAG(image)) {
+ mb_height = image->tile_row_height[ty];
+ mb_width = image->tile_column_width[tx];
+ }
+
+ num_planes = ((ALPHACHANNEL_FLAG(image)) ? 2 : 1);
+ for (my = 0 ; my < (int) mb_height ; my += 1) {
+ _jxr_r_rotate_mb_strip(image);
+ if (ALPHACHANNEL_FLAG(image)) {
+ image->alpha->cur_my = my;
+ recover_dclphp_strip(image->alpha, tx, ty, my);
+ }
+ image->cur_my = my;
+ recover_dclphp_strip(image, tx, ty, my);
+
+ for (mx = 0 ; mx < (int) mb_width ; mx += 1)
+ for (plane_idx = 0; plane_idx < num_planes; plane_idx ++) {
+ jxr_image_t plane = (plane_idx == 0 ? image : image->alpha);
+ int channels = (plane_idx == 0 ? use_num_channels : 1);
+ int rc = _jxr_r_MB_FLEXBITS(plane, str, 0, tx, ty, mx, my);
+ int mbhp_pred_mode;
+ int idx;
+ if (rc < 0) {
+ DEBUG("r_MB_FLEXBITS returned ERROR rc=%d\n", rc);
+ return rc;
+ }
+
+ /* Now the HP values are complete, so run the propagation
+ process. This involves recovering some bits of data saved
+ by the HP tile. */
+ mbhp_pred_mode = MACROBLK_CUR(plane,0,tx,mx).mbhp_pred_mode;
+ for (idx = 0 ; idx < channels ; idx += 1) {
+ DEBUG(" MB_FLEXBITS: propagate HP predictions in MB_FLEXBITS\n");
+ _jxr_propagate_hp_predictions(plane, idx, tx, mx, mbhp_pred_mode);
+ }
+ }
+ if (ALPHACHANNEL_FLAG(image))
+ backup_hp_strip(image->alpha, tx, ty, my);
+ backup_hp_strip(image, tx, ty, my);
+ }
+
+ _jxr_rbitstream_syncbyte(str);
+ DEBUG("END TILE_FLEXBITS bitpos=%zu\n", _jxr_rbitstream_bitpos(str));
+ return 0;
+}
+
+/*
+* This function handles the special case that the FLEXBITS tile is
+* escaped away. Do all the soft processing that is otherwise needed.
+*/
+int _jxr_r_TILE_FLEXBITS_ESCAPE(jxr_image_t image, unsigned tx, unsigned ty)
+{
+ int use_num_channels = image->num_channels;
+ unsigned mb_height = EXTENDED_HEIGHT_BLOCKS(image);
+ unsigned mb_width = EXTENDED_WIDTH_BLOCKS(image);
+ int mx, my;
+
+ DEBUG("START TILE_FLEXBITS_ESCAPE at tile=[%u %u]\n", tx, ty);
+
+ if (image->use_clr_fmt == 1/*YUV420*/ || image->use_clr_fmt == 2/*YUV422*/)
+ use_num_channels = 1;
+
+ if (TILING_FLAG(image)) {
+ mb_height = image->tile_row_height[ty];
+ mb_width = image->tile_column_width[tx];
+ }
+
+ for (my = 0 ; my < (int) mb_height ; my += 1) {
+ _jxr_r_rotate_mb_strip(image);
+ image->cur_my = my;
+ recover_dclphp_strip(image, tx, ty, my);
+
+ for (mx = 0 ; mx < (int) mb_width ; mx += 1) {
+ /* */
+ int mbhp_pred_mode = MACROBLK_CUR(image,0,tx,mx).mbhp_pred_mode;
+ int idx;
+ for (idx = 0 ; idx < use_num_channels ; idx += 1) {
+ DEBUG(" MB_FLEXBITS_ESCAPE: propagate HP predictions in MB_FLEXBITS\n");
+ _jxr_propagate_hp_predictions(image, idx, tx, mx, mbhp_pred_mode);
+ }
+ }
+ backup_hp_strip(image, tx, ty, my);
+ }
+
+ DEBUG("END TILE_FLEXBIT_ESCAPE\n");
+ return 0;
+}
+
+static void backup_dc_strip(jxr_image_t image, int tx, int ty, int my)
+{
+ int mx;
+ int use_my = my + image->tile_row_position[ty];
+ int use_mx = image->tile_column_position[tx];
+ int ptr = use_my*EXTENDED_WIDTH_BLOCKS(image) + use_mx;
+
+ int ch;
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ struct macroblock_s*mb = image->mb_row_buffer[ch] + ptr;
+
+ for (mx = 0 ; mx < (int) image->tile_column_width[tx] ; mx += 1) {
+ mb[mx].data[0] = MACROBLK_CUR_DC(image,ch,tx,mx);
+ DEBUG(" backup_dc_strip: tx=%d, ty=%d, mx=%d, my=%d, ch=%d, DC=0x%0x8\n",
+ tx, ty, mx, my, ch, mb[mx].data[0]);
+ }
+ }
+}
+
+static void backup_dclp_strip(jxr_image_t image, int tx, int ty, int my)
+{
+ int mx;
+ int use_my = my + image->tile_row_position[ty];
+ int use_mx = image->tile_column_position[tx];
+ int ptr = use_my*EXTENDED_WIDTH_BLOCKS(image) + use_mx;
+
+
+ int format_scale = 15;
+ int ch;
+ if (image->use_clr_fmt == 2 /* YUV422 */) {
+ format_scale = 7;
+ } else if (image->use_clr_fmt == 1 /* YUV420 */) {
+ format_scale = 3;
+ }
+
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ struct macroblock_s*mb = image->mb_row_buffer[ch] + ptr;
+ int count = ch==0? 15 : format_scale;
+
+ for (mx = 0 ; mx < (int) image->tile_column_width[tx] ; mx += 1) {
+ int idx;
+ mb[mx].data[0] = MACROBLK_CUR_DC(image,ch,tx,mx);
+ DEBUG(" backup_dclp_strip: tx=%d, ty=%d, mx=%d, my=%d, ch=%d, DC=0x%x, LP=",
+ tx, ty, mx, my, ch, mb[mx].data[0]);
+ for (idx = 0 ; idx < count ; idx += 1) {
+ mb[mx].data[idx+1] = MACROBLK_CUR_LP(image,ch,tx,mx,idx);
+ DEBUG(" 0x%x", mb[mx].data[idx+1]);
+ }
+ DEBUG("\n");
+ mb[mx].lp_quant = MACROBLK_CUR_LP_QUANT(image,ch,tx,mx);
+ }
+ }
+}
+
+static void backup_hp_strip(jxr_image_t image, int tx, int ty, int my)
+{
+ int mx;
+ int use_my = my + image->tile_row_position[ty];
+ int use_mx = image->tile_column_position[tx];
+ int ptr = use_my*EXTENDED_WIDTH_BLOCKS(image) + use_mx;
+
+
+ int format_scale = 16;
+ int ch;
+ if (image->use_clr_fmt == 2 /* YUV422 */) {
+ format_scale = 8;
+ } else if (image->use_clr_fmt == 1 /* YUV420 */) {
+ format_scale = 4;
+ }
+
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ struct macroblock_s*mb = image->mb_row_buffer[ch] + ptr;
+ int count = ch==0? 16 : format_scale;
+
+ if (ch == 0) {
+ /* Backup also the hp_model_bits, which are
+ stored only in the channel-0 blocks. */
+ for (mx = 0 ; mx < (int) image->tile_column_width[tx] ; mx += 1) {
+ mb[mx].hp_model_bits[0] = MACROBLK_CUR(image,0,tx,mx).hp_model_bits[0];
+ mb[mx].hp_model_bits[1] = MACROBLK_CUR(image,0,tx,mx).hp_model_bits[1];
+ mb[mx].mbhp_pred_mode = MACROBLK_CUR(image,0,tx,mx).mbhp_pred_mode;
+ }
+ }
+ for (mx = 0 ; mx < (int) image->tile_column_width[tx] ; mx += 1) {
+ int blk;
+ mb[mx].data[0] = MACROBLK_CUR_DC(image,ch,tx,mx);
+ DEBUG(" backup_hp_strip: tx=%d, ty=%d, mx=%d, my=%d, ch=%d\n",
+ tx, ty, mx, my, ch);
+ for (blk = 0 ; blk < count ; blk += 1) {
+ int idx;
+ for (idx = 0 ; idx < 15 ; idx += 1)
+ mb[mx].data[count+15*blk+idx] = MACROBLK_CUR_HP(image,ch,tx,mx,blk,idx);
+ }
+ mb[mx].hp_quant = MACROBLK_CUR_HP_QUANT(image,ch,tx,mx);
+ }
+ }
+}
+
+static void recover_dc_strip(jxr_image_t image, int tx, int ty, int my)
+{
+ int mx;
+ int use_my = my + image->tile_row_position[ty];
+ int use_mx = image->tile_column_position[tx];
+ int ptr = use_my*EXTENDED_WIDTH_BLOCKS(image) + use_mx;
+
+ int ch;
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ struct macroblock_s*mb = image->mb_row_buffer[ch] + ptr;
+
+ for (mx = 0 ; mx < (int) image->tile_column_width[tx] ; mx += 1) {
+ MACROBLK_CUR_DC(image,ch,tx,mx) = mb[mx].data[0];
+ DEBUG(" recover_dc_strip: tx=%d, ty=%d, mx=%d, my=%d, ch=%d, DC=0x%0x8\n",
+ tx, ty, mx, my, ch, mb[mx].data[0]);
+ }
+ }
+}
+
+static void recover_dclp_strip(jxr_image_t image, int tx, int ty, int my)
+{
+ int mx;
+ int use_my = my + image->tile_row_position[ty];
+ int use_mx = image->tile_column_position[tx];
+ int ptr = use_my*EXTENDED_WIDTH_BLOCKS(image) + use_mx;
+ int ch;
+
+ int format_scale = 15;
+ if (image->use_clr_fmt == 2 /* YUV422 */) {
+ format_scale = 7;
+ } else if (image->use_clr_fmt == 1 /* YUV420 */) {
+ format_scale = 3;
+ }
+
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ struct macroblock_s*mb = image->mb_row_buffer[ch] + ptr;
+ int count = ch==0? 15 : format_scale;
+
+ for (mx = 0 ; mx < (int) image->tile_column_width[tx] ; mx += 1) {
+ int idx;
+ MACROBLK_CUR_DC(image,ch,tx,mx) = mb[mx].data[0];
+ DEBUG(" recover_dclp_strip: tx=%d, ty=%d, mx=%d, my=%d, ch=%d, DC=0x%0x8, LP=\n",
+ tx, ty, mx, my, ch, mb[mx].data[0]);
+ for (idx = 0 ; idx < count ; idx += 1) {
+ MACROBLK_CUR_LP(image,ch,tx,mx,idx) = mb[mx].data[idx+1];
+ DEBUG(" 0x%x", mb[mx].data[idx+1]);
+ }
+ DEBUG("\n");
+ MACROBLK_CUR_LP_QUANT(image,ch,tx,mx) = mb[mx].lp_quant;
+ }
+ }
+}
+
+static void recover_dclphp_strip(jxr_image_t image, int tx, int ty, int my)
+{
+ int mx;
+ int use_my = my + image->tile_row_position[ty];
+ int use_mx = image->tile_column_position[tx];
+ int ptr = use_my*EXTENDED_WIDTH_BLOCKS(image) + use_mx;
+
+ int format_scale = 16;
+ int ch;
+ if (image->use_clr_fmt == 2 /* YUV422 */) {
+ format_scale = 8;
+ } else if (image->use_clr_fmt == 1 /* YUV420 */) {
+ format_scale = 4;
+ }
+
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ struct macroblock_s*mb = image->mb_row_buffer[ch] + ptr;
+ int count = ch==0? 16 : format_scale;
+
+ if (ch == 0) {
+ /* Recover also the hp_model_bits, which are
+ stored only in the channel-0 blocks. */
+ for (mx = 0 ; mx < (int) image->tile_column_width[tx] ; mx += 1) {
+ MACROBLK_CUR(image,0,tx,mx).hp_model_bits[0] = mb[mx].hp_model_bits[0];
+ MACROBLK_CUR(image,0,tx,mx).hp_model_bits[1] = mb[mx].hp_model_bits[1];
+ MACROBLK_CUR(image,0,tx,mx).mbhp_pred_mode = mb[mx].mbhp_pred_mode;
+ }
+ }
+ for (mx = 0 ; mx < (int) image->tile_column_width[tx] ; mx += 1) {
+ int blk;
+ MACROBLK_CUR_DC(image,ch,tx,mx) = mb[mx].data[0];
+ DEBUG(" recover_dclphp_strip: tx=%d, ty=%d, mx=%d, my=%d, ch=%d, DC=0x%0x8, LP=\n",
+ tx, ty, mx, my, ch, mb[mx].data[0]);
+ for (blk = 1 ; blk < count ; blk += 1) {
+ MACROBLK_CUR_LP(image,ch,tx,mx,blk-1) = mb[mx].data[blk];
+ DEBUG(" 0x%x", mb[mx].data[blk]);
+ }
+
+ for (blk = 0 ; blk < count ; blk += 1) {
+ int idx;
+ for (idx = 0 ; idx < 15 ; idx += 1) {
+ int data_ptr = count+15*blk+idx;
+ MACROBLK_CUR_HP(image,ch,tx,mx,blk,idx) = mb[mx].data[data_ptr];
+ }
+ }
+ DEBUG("\n");
+ MACROBLK_CUR_LP_QUANT(image,ch,tx,mx) = mb[mx].lp_quant;
+ MACROBLK_CUR_HP_QUANT(image,ch,tx,mx) = mb[mx].hp_quant;
+ }
+ }
+}
+
+void _jxr_frequency_mode_render(jxr_image_t image)
+{
+
+ int ty;
+ for (ty = 0 ; ty < (int) image->tile_rows ; ty += 1) {
+ int my;
+ for (my = 0 ; my < (int) image->tile_row_height[ty] ; my += 1) {
+ int tx;
+ if (ALPHACHANNEL_FLAG(image))
+ _jxr_rflush_mb_strip(image->alpha, -1, -1, my + image->alpha->tile_row_position[ty]);
+ _jxr_rflush_mb_strip(image, -1, -1, my + image->tile_row_position[ty]);
+ for (tx = 0 ; tx < (int) image->tile_columns ; tx += 1) {
+ if (ALPHACHANNEL_FLAG(image))
+ recover_dclphp_strip(image->alpha, tx, ty, my);
+ recover_dclphp_strip(image, tx, ty, my);
+ }
+ }
+ }
+
+ if (ALPHACHANNEL_FLAG(image))
+ _jxr_rflush_mb_strip(image->alpha, -1, -1, EXTENDED_HEIGHT_BLOCKS(image->alpha)+0);
+ _jxr_rflush_mb_strip(image, -1, -1, EXTENDED_HEIGHT_BLOCKS(image)+0);
+
+ if (ALPHACHANNEL_FLAG(image))
+ _jxr_rflush_mb_strip(image->alpha, -1, -1, EXTENDED_HEIGHT_BLOCKS(image->alpha)+1);
+ _jxr_rflush_mb_strip(image, -1, -1, EXTENDED_HEIGHT_BLOCKS(image)+1);
+
+ if (ALPHACHANNEL_FLAG(image))
+ _jxr_rflush_mb_strip(image->alpha, -1, -1, EXTENDED_HEIGHT_BLOCKS(image->alpha)+2);
+ _jxr_rflush_mb_strip(image, -1, -1, EXTENDED_HEIGHT_BLOCKS(image)+2);
+
+ if (ALPHACHANNEL_FLAG(image))
+ _jxr_rflush_mb_strip(image->alpha, -1, -1, EXTENDED_HEIGHT_BLOCKS(image->alpha)+3);
+ _jxr_rflush_mb_strip(image, -1, -1, EXTENDED_HEIGHT_BLOCKS(image)+3);
+}
+
+/*
+* $Log: r_tile_frequency.c,v $
+* Revision 1.16 2009/05/29 12:00:00 microsoft
+* Reference Software v1.6 updates.
+*
+* Revision 1.15 2009/04/13 12:00:00 microsoft
+* Reference Software v1.5 updates.
+*
+* Revision 1.14 2008/03/18 21:34:04 steve
+* Fix distributed color prediction.
+*
+* Revision 1.13 2008/03/05 06:58:10 gus
+* *** empty log message ***
+*
+* Revision 1.12 2008/02/26 23:52:44 steve
+* Remove ident for MS compilers.
+*
+* Revision 1.11 2007/11/26 01:47:15 steve
+* Add copyright notices per MS request.
+*
+* Revision 1.10 2007/11/21 00:34:30 steve
+* Rework spatial mode tile macroblock shuffling.
+*
+* Revision 1.9 2007/11/20 00:05:47 steve
+* Complex handling of mbhp_pred_mode in frequency dmoe.
+*
+* Revision 1.8 2007/11/16 21:33:48 steve
+* Store MB Quant, not qp_index.
+*
+* Revision 1.7 2007/11/16 20:03:57 steve
+* Store MB Quant, not qp_index.
+*
+* Revision 1.6 2007/11/16 17:33:24 steve
+* Do HP prediction after FLEXBITS frequency tiles.
+*
+* Revision 1.5 2007/11/16 00:29:06 steve
+* Support FREQUENCY mode HP and FLEXBITS
+*
+* Revision 1.4 2007/11/15 17:44:13 steve
+* Frequency mode color support.
+*
+* Revision 1.3 2007/11/14 23:56:17 steve
+* Fix TILE ordering, using seeks, for FREQUENCY mode.
+*
+* Revision 1.2 2007/11/13 03:27:23 steve
+* Add Frequency mode LP support.
+*
+* Revision 1.1 2007/11/12 23:21:55 steve
+* Infrastructure for frequency mode ordering.
+*
+*/
+
diff --git a/jpegxr/r_tile_spatial.c b/jpegxr/r_tile_spatial.c
new file mode 100644
index 000000000..4f43c0518
--- /dev/null
+++ b/jpegxr/r_tile_spatial.c
@@ -0,0 +1,380 @@
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+**********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: r_tile_spatial.c,v 1.53 2008/03/20 22:39:41 steve Exp $")
+#else
+#ident "$Id: r_tile_spatial.c,v 1.53 2008/03/20 22:39:41 steve Exp $"
+#endif
+
+# include "jxr_priv.h"
+# include <assert.h>
+
+
+
+/*
+* Process a single spatial time. The tx/ty is the coordintes of the
+* tile in units of tiles. tx=0 for the first time, tx=1 for the
+* second, and so forth.
+*/
+int _jxr_r_TILE_SPATIAL(jxr_image_t image, struct rbitstream*str,
+ unsigned tx, unsigned ty)
+{
+ int rc = 0;
+ unsigned mx, my, plane_idx;
+ unsigned char s0, s1, s2, s3;
+ unsigned mb_height;
+ unsigned mb_width;
+
+ DEBUG("START TILE_SPATIAL at tile=[%u %u] bitpos=%zu\n", tx, ty, _jxr_rbitstream_bitpos(str));
+
+ /* TILE_STARTCODE == 1 */
+ s0 = _jxr_rbitstream_uint8(str); /* 0x00 */
+ s1 = _jxr_rbitstream_uint8(str); /* 0x00 */
+ s2 = _jxr_rbitstream_uint8(str); /* 0x01 */
+ s3 = _jxr_rbitstream_uint8(str); /* reserved */
+ DEBUG(" TILE_STARTCODE == %02x %02x %02x (reserved: %02x)\n", s0, s1, s2, s3);
+
+ image->trim_flexbits = 0;
+ if (TRIM_FLEXBITS_FLAG(image)) {
+ image->trim_flexbits =_jxr_rbitstream_uint4(str);
+ DEBUG(" TRIM_FLEXBITS = %u\n", image->trim_flexbits);
+ }
+
+ /* Read the tile header (which includes sub-headers for
+ all the major passes). */
+
+ _jxr_r_TILE_HEADER_DC(image, str, 0, tx, ty);
+ if (image->bands_present != 3 /* DCONLY */) {
+ _jxr_r_TILE_HEADER_LOWPASS(image, str, 0, tx, ty);
+
+ if (image->bands_present != 2 /* NO_HIGHPASS */) {
+ _jxr_r_TILE_HEADER_HIGHPASS(image, str, 0, tx, ty);
+ }
+ }
+
+ /* If the alpha channel is present, then run another set of
+ headers for the alpha channel. */
+ if (ALPHACHANNEL_FLAG(image)) {
+ _jxr_r_TILE_HEADER_DC(image->alpha, str, 1, tx, ty);
+ if (image->bands_present != 3 /* DCONLY */) {
+ _jxr_r_TILE_HEADER_LOWPASS(image->alpha, str, 1, tx, ty);
+
+ if (image->bands_present != 2 /* NO_HIGHPASS */) {
+ _jxr_r_TILE_HEADER_HIGHPASS(image->alpha, str, 1, tx, ty);
+ }
+ }
+ }
+
+
+ /* Now form and write out all the compressed data for the
+ tile. This involves scanning the macroblocks, and the
+ blocks within the macroblocks, generating bits as we go. */
+
+ mb_height = EXTENDED_HEIGHT_BLOCKS(image);
+ mb_width = EXTENDED_WIDTH_BLOCKS(image);
+
+ if (TILING_FLAG(image)) {
+ mb_height = image->tile_row_height[ty];
+ mb_width = image->tile_column_width[tx];
+ }
+
+ for (my = 0 ; my < mb_height ; my += 1) {
+ if (ALPHACHANNEL_FLAG(image))
+ _jxr_rflush_mb_strip(image->alpha, tx, ty, my);
+ _jxr_rflush_mb_strip(image, tx, ty, my);
+
+ for (mx = 0 ; mx < mb_width ; mx += 1) {
+ for(plane_idx = 0U; plane_idx < (ALPHACHANNEL_FLAG(image) ? 2U : 1U); plane_idx ++){
+ int ch;
+
+ /* There is one LP_QP_INDEX per macroblock (if any)
+ and that value applies to all the channels.
+ Same for HP_QP_INDEX. There is no DC_QP_INDEX
+ because DC QP values are per-tile, not per MB. */
+ int qp_index_lp = 0;
+ int qp_index_hp = 0;
+ jxr_image_t plane = (plane_idx == 0 ? image : image->alpha);
+
+ if (plane->bands_present!=3) {
+ if (plane->num_lp_qps>1 && !plane->lp_use_dc_qp) {
+ qp_index_lp = _jxr_DECODE_QP_INDEX(str, plane->num_lp_qps);
+ DEBUG(" DECODE_QP_INDEX(%d) --> %u (LP)\n", plane->num_lp_qps, qp_index_lp);
+ }
+ qp_index_hp = 0;
+ if (plane->bands_present!=2 && plane->num_hp_qps>1) {
+ if (!plane->hp_use_lp_qp) {
+ qp_index_hp = _jxr_DECODE_QP_INDEX(str, plane->num_hp_qps);
+ DEBUG(" DECODE_QP_INDEX(%d) --> %u (HP)\n", plane->num_hp_qps, qp_index_hp);
+ }
+ else {
+ qp_index_hp = qp_index_lp;
+ }
+ }
+ }
+ for (ch = 0 ; ch < plane->num_channels ; ch += 1) {
+ /* Save the LP Quant *INDEX* here. Prediction needs it. */
+ MACROBLK_CUR_LP_QUANT(plane,ch,tx,mx) = qp_index_lp;
+ DEBUG(" LP_QUANT INDEX for tx=%u ty=%u ch=%u MBx=%d is %d\n", tx, ty, ch, mx,
+ MACROBLK_CUR_LP_QUANT(plane,ch,tx,mx));
+ MACROBLK_CUR_HP_QUANT(plane,ch,tx,mx) = plane->hp_quant_ch[ch][qp_index_hp];
+ DEBUG(" HP_QUANT VALUE for tx=%u ty=%u ch=%u MBx=%d is %d\n", tx, ty, ch, mx,
+ MACROBLK_CUR_HP_QUANT(plane,ch,tx,mx));
+ }
+
+ _jxr_r_MB_DC(plane, str, plane_idx, tx, ty, mx, my);
+ if (plane->bands_present != 3 /* DCONLY */) {
+ _jxr_r_MB_LP(plane, str, plane_idx, tx, ty, mx, my);
+ _jxr_complete_cur_dclp(plane, tx, mx, my);
+ if (plane->bands_present != 2 /* NOHIGHPASS */) {
+ rc = _jxr_r_MB_CBP(plane, str, plane_idx, tx, ty, mx, my);
+ if (rc < 0) {
+ DEBUG("r_MB_CBP returned ERROR rc=%d\n", rc);
+ return rc;
+ }
+ rc = _jxr_r_MB_HP(plane, str, plane_idx, tx, ty, mx, my);
+ if (rc < 0) {
+ DEBUG("r_MB_HP returned ERROR rc=%d\n", rc);
+ return rc;
+ }
+ }
+ } else {
+ _jxr_complete_cur_dclp(plane, tx, mx, my);
+ }
+ }
+ }
+ }
+
+ /* Flush the remaining strips to output. */
+ if (tx+1 == image->tile_columns && ty+1 == image->tile_rows) {
+ DEBUG(" Cleanup flush after last tile (tx=%d, ty=%d)\n", tx, ty);
+ if (ALPHACHANNEL_FLAG(image))
+ _jxr_rflush_mb_strip(image->alpha, tx, ty, mb_height);
+ _jxr_rflush_mb_strip(image, tx, ty, mb_height);
+
+ if (ALPHACHANNEL_FLAG(image))
+ _jxr_rflush_mb_strip(image->alpha, tx, ty, mb_height+1);
+ _jxr_rflush_mb_strip(image, tx, ty, mb_height+1);
+
+ if (ALPHACHANNEL_FLAG(image))
+ _jxr_rflush_mb_strip(image->alpha, tx, ty, mb_height+2);
+ _jxr_rflush_mb_strip(image, tx, ty, mb_height+2);
+
+ if (ALPHACHANNEL_FLAG(image))
+ _jxr_rflush_mb_strip(image->alpha, tx, ty, mb_height+3);
+ _jxr_rflush_mb_strip(image, tx, ty, mb_height+3);
+ }
+ _jxr_rbitstream_syncbyte(str);
+ DEBUG("END TILE_SPATIAL\n");
+ return 0;
+}
+
+/*
+* $Log: r_tile_spatial.c,v $
+* Revision 1.55 2009/05/29 12:00:00 microsoft
+* Reference Software v1.6 updates.
+*
+* Revision 1.54 2009/04/13 12:00:00 microsoft
+* Reference Software v1.5 updates.
+*
+* Revision 1.53 2008/03/20 22:39:41 steve
+* Fix various debug prints of QP data.
+*
+* Revision 1.52 2008/03/20 18:11:25 steve
+* Handle case of NumLPQP==1 and NumHPQPS>1
+*
+* Revision 1.51 2008/03/18 21:09:12 steve
+* Fix distributed color prediction.
+*
+* Revision 1.50 2008/03/07 19:00:52 steve
+* Improved comments.
+*
+* Revision 1.49 2008/03/06 22:47:39 steve
+* Clean up parsing/encoding of QP counts
+*
+* Revision 1.48 2008/03/06 02:05:48 steve
+* Distributed quantization
+*
+* Revision 1.47 2008/02/26 23:52:44 steve
+* Remove ident for MS compilers.
+*
+* Revision 1.46 2007/11/26 01:47:15 steve
+* Add copyright notices per MS request.
+*
+* Revision 1.45 2007/11/21 23:26:14 steve
+* make all strip buffers store MB data.
+*
+* Revision 1.44 2007/11/20 17:08:02 steve
+* Fix SPATIAL processing of QUANT values for color.
+*
+* Revision 1.43 2007/11/16 21:33:48 steve
+* Store MB Quant, not qp_index.
+*
+* Revision 1.42 2007/11/16 20:03:57 steve
+* Store MB Quant, not qp_index.
+*
+* Revision 1.41 2007/11/16 00:29:06 steve
+* Support FREQUENCY mode HP and FLEXBITS
+*
+* Revision 1.40 2007/11/14 23:56:17 steve
+* Fix TILE ordering, using seeks, for FREQUENCY mode.
+*
+* Revision 1.39 2007/11/14 00:17:27 steve
+* Fix parsing of QP indices.
+*
+* Revision 1.38 2007/11/13 03:27:24 steve
+* Add Frequency mode LP support.
+*
+* Revision 1.37 2007/11/12 23:21:55 steve
+* Infrastructure for frequency mode ordering.
+*
+* Revision 1.36 2007/11/08 19:38:38 steve
+* Get stub DCONLY compression to work.
+*
+* Revision 1.35 2007/11/01 21:09:40 steve
+* Multiple rows of tiles.
+*
+* Revision 1.34 2007/10/31 21:20:54 steve
+* Init, not Adapt, on tile boundaries.
+*
+* Revision 1.33 2007/10/30 21:32:46 steve
+* Support for multiple tile columns.
+*
+* Revision 1.32 2007/10/19 16:20:21 steve
+* Parse YUV420 HP
+*
+* Revision 1.31 2007/10/04 23:03:26 steve
+* HP blocks uf YUV42X chroma are not shuffled.
+*
+* Revision 1.30 2007/10/04 00:30:47 steve
+* Fix prediction of HP CBP for YUV422 data.
+*
+* Revision 1.29 2007/10/02 20:36:29 steve
+* Fix YUV42X DC prediction, add YUV42X HP parsing.
+*
+* Revision 1.28 2007/10/01 20:39:34 steve
+* Add support for YUV422 LP bands.
+*
+* Revision 1.27 2007/09/18 17:00:50 steve
+* Fix bad calculation of lap_mean for chroma.
+*
+* Revision 1.26 2007/09/13 23:12:34 steve
+* Support color HP bands.
+*
+* Revision 1.25 2007/09/12 01:09:24 steve
+* Dump the TRIM_FLEXBITS value.
+*
+* Revision 1.24 2007/09/11 01:06:12 steve
+* Forgot to properly save LP data.
+*
+* Revision 1.23 2007/09/11 00:40:06 steve
+* Fix rendering of chroma to add the missing *2.
+* Fix handling of the chroma LP samples
+* Parse some of the HP CBP data in chroma.
+*
+* Revision 1.22 2007/09/10 23:42:00 steve
+* Fix LP processing steps when color involved.
+*
+* Revision 1.21 2007/09/08 01:01:44 steve
+* YUV444 color parses properly.
+*
+* Revision 1.20 2007/09/04 22:48:09 steve
+* Fix calculation of flex bits on 0 coefficients.
+*
+* Revision 1.19 2007/09/04 19:10:46 steve
+* Finish level1 overlap filtering.
+*
+* Revision 1.18 2007/08/31 23:31:49 steve
+* Initialize CBP VLC tables at the right time.
+*
+* Revision 1.17 2007/08/31 23:20:57 steve
+* Dump MB_CBP details.
+*
+* Revision 1.16 2007/08/15 01:54:11 steve
+* Add level2 filter to decoder.
+*
+* Revision 1.15 2007/08/13 22:24:43 steve
+* Fix Reset Context of absLevelInd.
+*
+* Revision 1.14 2007/07/31 15:27:19 steve
+* Get transpose of FLEXBITS right.
+*
+* Revision 1.13 2007/07/30 23:09:57 steve
+* Interleave FLEXBITS within HP block.
+*
+* Revision 1.12 2007/07/24 20:56:28 steve
+* Fix HP prediction and model bits calculations.
+*
+* Revision 1.11 2007/07/21 00:25:48 steve
+* snapshot 2007 07 20
+*
+* Revision 1.10 2007/07/12 22:48:17 steve
+* Decode FLEXBITS
+*
+* Revision 1.9 2007/07/11 00:53:36 steve
+* HP adaptation and precition corrections.
+*
+* Revision 1.8 2007/07/06 23:18:41 steve
+* calculate and propagate HP band predictions.
+*
+* Revision 1.7 2007/07/05 20:19:13 steve
+* Fix accumulation of HP CBP, and add HP predictions.
+*
+* Revision 1.6 2007/07/03 20:45:11 steve
+* Parse and place HP data.
+*
+* Revision 1.5 2007/06/28 20:03:11 steve
+* LP processing seems to be OK now.
+*
+* Revision 1.4 2007/06/21 17:31:22 steve
+* Successfully parse LP components.
+*
+* Revision 1.3 2007/06/11 20:00:09 steve
+* Parse FLEXBITS
+*
+* Revision 1.2 2007/06/07 18:53:06 steve
+* Parse HP coeffs that are all 0.
+*
+* Revision 1.1 2007/06/06 17:19:12 steve
+* Introduce to CVS.
+*
+*/
+
diff --git a/jpegxr/sample.qp b/jpegxr/sample.qp
new file mode 100644
index 000000000..50f3de15d
--- /dev/null
+++ b/jpegxr/sample.qp
@@ -0,0 +1,96 @@
+
+# This is a sample QP map file that defines a QP map for a
+# color image with a tile 4x4 macroblocks. The format is simple enough
+# and this example illustrates all the aspects of the format.
+#
+# The file is free-formatted. Comments start with a '#' and continue
+# to the end of the text line. white space separates tokens and can be
+# used freely. Keywords are case sensitive, and numbers are unsigned
+# decimal.
+
+# The complete list of keywords is:
+#
+# DC, HP, LP, channel, independent, separate, tile, uniform
+#
+
+# A tile section is needed for each tile in the image to compress. The
+# values in the () are the column and row of the tile that you are
+# configuring. In this case, the (0,0) means this is the upper left tile.
+tile (0,0) {
+
+ # Specify a component mode. The value values are:
+ #
+ # uniform - all the components are the same. In this case, you
+ # only need to specify channel 0, and all the other
+ # channels will copy their values from that channel.
+ #
+ # separate - The first channel uses one QP set, and all the other
+ # channels use another QP set. You will only need to
+ # specify channel-0 and channel-1.
+ # independent
+ # - All the channels have their own channel set. You
+ # need to specify the channel set for all the channels
+ # in the image.
+ separate
+
+ # Next, give all the QP parameters for the channels that you
+ # need. For each channel, specify the DC, LP and HP qp values. The
+ # QP values range from 0-255 inclusive, with 0 being lossless and
+ # 255 being most lossy.
+ #
+ # There is always exactly 1 DC QP value for each channel.
+ #
+ # There is at least 1 and at most 16 LP(HP) QP values, and the
+ # number of LP(HP) values must be the same for each channel. For
+ # example, if channel 0 has 2 LP values, channel 1 must also have 2
+ # LP values. The same is true for HP values. (There can be different
+ # numbers of LP and HP QP values. For example, it is OK to have 2 LP
+ # QP values and 1 HP QP value.
+ channel 0 {
+ DC { 1 }
+ LP { 1, 100 }
+ HP { 1, 150 }
+ }
+ # Note that the comma listing the QP values is optional.
+ channel 1 {
+ DC { 5 }
+ LP { 5 240 }
+ HP { 5 250 }
+ }
+
+ # Finally, map each macroblock to an LP(HP) QP value by specifying
+ # the index here. For this step you need the dimensions of the tile
+ # in macroblocks, and you need to specify a map value for each
+ # macroblock. In this example, there are 16 macroblocks in this tile
+ # (it doesn't matter if they are arranged 4x4 or 8x2 or whatever)
+ # and they are assigned in raster order.
+ #
+ # The number in the map is an index into the LP or HP list above,
+ # and can range from 0 to the number of items in the list above. For
+ # example, in this example the channels have 2 LP QP values so the
+ # index value can be 0 or 1. If there were 5 LP QP items then the
+ # values would range from 0-4.
+ #
+ # You need to map the LP and HP values independently.
+ #
+ # Each map selects the LP(HP) QP values for all the channels. Recall
+ # the constraint above that the LP(HP) QP list have the same length
+ # for all the channels.
+ #
+ # If an LP or HP map is left out, then it is assumed to contain all
+ # zeros. This is useful if for example there is only 1 QP value for
+ # LP/HP subband, or if the subband is to be dropped by the
+ # compressor.
+ #
+ # Note that the map is surrounded by [] instead of {} to more
+ # clearly distinguish this map from the QP list inside the channels.
+ LP [ 0 0 0 0
+ 0 0 0 0
+ 1 1 1 1
+ 1 1 1 1 ]
+
+ HP [ 0 0 0 0
+ 0 0 0 0
+ 1 1 1 1
+ 1 1 1 1 ]
+}
diff --git a/jpegxr/stdint_minimal.h b/jpegxr/stdint_minimal.h
new file mode 100644
index 000000000..c2ebee20e
--- /dev/null
+++ b/jpegxr/stdint_minimal.h
@@ -0,0 +1,71 @@
+#ifndef __stdint_minimal_H
+#define __stdint_minimal_H
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+**********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: stdint_minimal.h,v 1.2 2008/02/28 18:50:31 steve Exp $")
+#else
+#ident "$Id: stdint_minimal.h,v 1.2 2008/02/28 18:50:31 steve Exp $"
+#endif
+
+/*
+* Microsoft VC compilers do not support C99, so we provide here a few
+* of the basic typedefs that we need to get the code to
+* compile. Since C99 stdint.h is not supported, the typedefs cannot
+* be done portably, so we just do the most likely types.
+*
+* Note that this is specific to Microsoft compilers and not the
+* Microsoft system. Mingw32, for example, does support C99 and this
+* header file is not used in that case.
+*/
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+
+typedef char int8_t;
+typedef short int16_t;
+typedef int int32_t;
+typedef long long int64_t;
+
+#endif
diff --git a/jpegxr/versions-windows.txt b/jpegxr/versions-windows.txt
new file mode 100644
index 000000000..50d65744d
--- /dev/null
+++ b/jpegxr/versions-windows.txt
@@ -0,0 +1,11 @@
+ JPEG XR MSVS 2008 Versions
+
+0.1.0.0 20080227 Code ported to MSVS 2008 solution. 2 Projects in separate sub-directories - app and dll. JPEG XR library compiled as a DLL.
+
+0.1.0.1 20080228 The 2 projects directories are merged into a single directory (the top level solution directory). So sub-directories APP and DLL have been removed.
+
+0.1.1.0 20080304 Tweaks to SP setting API (at the C level) in preparation for distributed QP work.
+
+0.1.2.0 20090410 Several updates for April 2009 JPEG Maui meeting
+
+0.1.2.1 20090410 Bug fixes for October 2009 JPEG meeting
diff --git a/jpegxr/w_emit.c b/jpegxr/w_emit.c
new file mode 100644
index 000000000..224e96c85
--- /dev/null
+++ b/jpegxr/w_emit.c
@@ -0,0 +1,3307 @@
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+**********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: w_emit.c,v 1.25 2008/03/24 18:06:56 steve Exp $")
+#else
+#ident "$Id: w_emit.c,v 1.25 2008/03/24 18:06:56 steve Exp $"
+#endif
+
+# include "jxr_priv.h"
+# include <stdlib.h>
+# include <assert.h>
+
+void initialize_index_table(jxr_image_t image);
+
+static int w_image_header(jxr_image_t image, struct wbitstream*str);
+static int w_image_plane_header(jxr_image_t image, struct wbitstream*str, int alpha);
+static void w_INDEX_TABLE(jxr_image_t image, struct wbitstream*str);
+static uint64_t w_PROFILE_LEVEL_INFO(jxr_image_t image, struct wbitstream*str, uint64_t bytes);
+static void w_TILE(jxr_image_t image, struct wbitstream*str);
+
+static int short_header_ok(jxr_image_t image);
+static int need_windowing_flag(jxr_image_t image);
+static int need_trim_flexbits_flag(jxr_image_t image);
+
+
+static void w_MB_FLEXBITS(jxr_image_t image, struct wbitstream*str,
+ int alpha_flag,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my);
+static void w_BLOCK_FLEXBITS(jxr_image_t image, struct wbitstream*str,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my,
+ unsigned ch, unsigned bl, unsigned model_bits);
+static void w_DEC_DC(jxr_image_t image, struct wbitstream*str,
+ int model_bits, int chroma_flag, int is_dc_ch,
+ int32_t dc_val);
+static void w_DECODE_ABS_LEVEL(jxr_image_t image, struct wbitstream*str,
+ int band, int chroma_flag, uint32_t level);
+static void w_DECODE_BLOCK(jxr_image_t image, struct wbitstream*str, int band, int chroma_flag,
+ const int RLCoeffs[32], int num_non_zero);
+static void w_DECODE_FIRST_INDEX(jxr_image_t image, struct wbitstream*str,
+ int chroma_flag, int band, int index_code);
+static void w_DECODE_INDEX(jxr_image_t image, struct wbitstream*str,
+ int location, int chroma_flag, int band, int context,
+ int index_code);
+static void w_DECODE_RUN(jxr_image_t image, struct wbitstream*str, int max_run, int run);
+static int w_DECODE_BLOCK_ADAPTIVE(jxr_image_t image, struct wbitstream*str,
+ unsigned tx, unsigned mx,
+ int cbp_flag, int chroma_flag,
+ int channel, int block, int mbhp_pred_mode,
+ unsigned model_bits);
+static void w_REFINE_CBP(jxr_image_t image, struct wbitstream*str, int cbp_block_mask);
+static void w_REFINE_CBP_CHR(jxr_image_t image, struct wbitstream*str, int cbp_block_mask);
+static void refine_cbp_chr422(jxr_image_t image, struct wbitstream*str, int diff_cbp, int block);
+
+
+static const int transpose420[4] = {0, 2,
+1, 3 };
+static const int transpose422[8] = {0, 2, 1, 3, 4, 6, 5, 7};
+
+
+void initialize_index_table(jxr_image_t image)
+{
+ int num_index_table_entries;
+
+ if (FREQUENCY_MODE_CODESTREAM_FLAG(image) == 0 /* SPATIAL MODE */) {
+ num_index_table_entries = image->tile_columns * image->tile_rows;
+ }
+ else
+ {
+ num_index_table_entries = image->tile_columns * image->tile_rows;
+ switch (image->bands_present_of_primary) {
+ case 4: /* ISOLATED */
+ num_index_table_entries *= 4;
+ break;
+ default:
+ num_index_table_entries *= (4 - image->bands_present_of_primary);
+ break;
+ }
+ }
+ image->tile_index_table_length = num_index_table_entries;
+
+ assert(image->tile_index_table == 0);
+ image->tile_index_table = (int64_t*)calloc(num_index_table_entries, sizeof(int64_t));
+ DEBUG(" INDEX_TABLE has %d table entries\n", num_index_table_entries);
+}
+
+static int fill_in_image_defaults(jxr_image_t image)
+{
+ unsigned * temp_ptr, idx;
+
+ if (image->tile_columns == 0)
+ image->tile_columns = 1;
+ if (image->tile_rows == 0)
+ image->tile_rows = 1;
+
+ if (image->tile_columns > 1 || image->tile_rows > 1)
+ image->header_flags1 |= 0x80; /* TILING FLAG */
+
+ if (short_header_ok(image))
+ image->header_flags2 |= 0x80; /* SHORT_HEADER FLAG */
+ else
+ image->header_flags2 &= ~0x80;
+
+ if (need_windowing_flag(image))
+ image->header_flags2 |= 0x20; /* WINDOWING_FLAG */
+
+ image->window_extra_bottom = 15 - ((image->height1 + image->window_extra_top) % 16);
+ image->extended_height = image->height1 + 1 + image->window_extra_top + image->window_extra_bottom;
+ image->window_extra_right = 15 - ((image->width1 + image->window_extra_left) % 16);
+ image->extended_width = image->width1 + 1 + image->window_extra_left + image->window_extra_right;
+
+ if (need_trim_flexbits_flag(image))
+ image->header_flags2 |= 0x10; /* TRIM_FLEXBITS_FLAG */
+ else
+ image->header_flags2 &= ~0x10;
+
+ /* Test OUTPUT_CLR_FMT against size requirements */
+ switch(image->output_clr_fmt) {
+ case JXR_OCF_YUV420: /* YUV420 */
+ assert(image->height1 & 0x1);
+ assert((image->window_extra_top & 0x1) == 0);
+ assert((image->window_extra_bottom & 0x1) == 0);
+ case JXR_OCF_YUV422: /* YUV422 */
+ assert(image->width1 & 0x1);
+ assert((image->window_extra_left & 0x1) == 0);
+ assert((image->window_extra_right & 0x1) == 0);
+ break;
+ }
+
+ /* Force scaling ON if we are using a subsampled color format. */
+ switch (image->use_clr_fmt) {
+
+ /* If external and internal formats are both YUV420 (or YUV422), don't change scaled_flag.
+ Otherwise, color format is subsampled(lossy) and scaled_flag should be set as 1. */
+ case 1: /*YUV420*/
+ if (OVERLAP_INFO(image) == 2)
+ assert(image->extended_width >= 32);
+ if (image->output_clr_fmt != JXR_OCF_YUV420)
+ image->scaled_flag = 1;
+ break;
+ case 2: /*YUV422*/
+ if (OVERLAP_INFO(image) == 2)
+ assert(image->extended_width >= 32);
+ if (image->output_clr_fmt != JXR_OCF_YUV422)
+ image->scaled_flag = 1;
+ break;
+ }
+
+ temp_ptr = image->tile_column_width;
+ image->tile_column_width = (unsigned*)calloc(2*image->tile_columns, sizeof(unsigned));
+ for (idx = 0 ; idx < image->tile_columns ; idx++)
+ image->tile_column_width[idx] = temp_ptr[idx];
+ image->tile_column_position = image->tile_column_width + image->tile_columns;
+
+ temp_ptr = image->tile_row_height;
+ image->tile_row_height = (unsigned*)calloc(2*image->tile_rows, sizeof(unsigned));
+ for (idx = 0 ; idx < image->tile_rows ; idx++)
+ image->tile_row_height[idx] = temp_ptr[idx];
+ image->tile_row_position = image->tile_row_height + image->tile_rows;
+
+ if (TILING_FLAG(image)) {
+ unsigned width_MB = EXTENDED_WIDTH_BLOCKS(image), height_MB = EXTENDED_HEIGHT_BLOCKS(image);
+ unsigned min_width = 1, total_width = 0, min_height = 1, total_height = 0;
+
+ if (image->tile_column_width[0] == 0) {
+ total_width = 0;
+ for ( idx = 0 ; idx < image->tile_columns - 1 ; idx++ ) {
+ image->tile_column_width[idx] = width_MB / image->tile_columns;
+ image->tile_column_position[idx] = total_width;
+ total_width += image->tile_column_width[idx];
+ }
+ image->tile_column_width[image->tile_columns - 1] = width_MB - total_width;
+ image->tile_column_position[image->tile_columns - 1] = total_width;
+ }
+ total_width = 0;
+
+ if ((OVERLAP_INFO(image) == 2) && ((image->use_clr_fmt == 1/*YUV420*/) || (image->use_clr_fmt == 2/*YUV422*/)) && image->disableTileOverlapFlag)
+ min_width = 2;
+ for ( idx = 0 ; idx < image->tile_columns - 1 ; idx++ ) {
+ if (image->tile_column_width[idx] < min_width) {
+ DEBUG(" Tile %d width is below minimum width\n", idx);
+ assert(0);
+ break;
+ }
+ image->tile_column_position[idx] = total_width;
+ total_width += image->tile_column_width[idx];
+ }
+ if ((total_width + min_width) > width_MB) {
+ DEBUG(" Total specified tile width is above image width\n");
+ assert(0);
+ }
+ image->tile_column_position[image->tile_columns - 1] = total_width;
+ image->tile_column_width[image->tile_columns - 1] = (width_MB - total_width);
+
+ if (image->tile_row_height[0] == 0) {
+ total_height = 0;
+ for ( idx = 0 ; idx < image->tile_rows - 1 ; idx++ ) {
+ image->tile_row_height[idx] = height_MB / image->tile_rows;
+ image->tile_row_position[idx] = total_height;
+ total_height += image->tile_row_height[idx];
+ }
+ image->tile_row_height[image->tile_rows - 1] = height_MB - total_height;
+ image->tile_row_position[image->tile_rows - 1] = total_height;
+ }
+ total_height = 0;
+
+ for ( idx = 0 ; idx < image->tile_rows - 1 ; idx++ ) {
+ if (image->tile_row_height[idx] < min_height) {
+ DEBUG(" Tile %d height is below minimum height\n", idx);
+ assert(0);
+ break;
+ }
+ image->tile_row_position[idx] = total_height;
+ total_height += image->tile_row_height[idx];
+ }
+ if ((total_height + min_height) > height_MB) {
+ DEBUG(" Total specified tile height is above image height\n");
+ assert(0);
+ }
+ image->tile_row_position[image->tile_rows - 1] = total_height;
+ image->tile_row_height[image->tile_rows - 1] = (height_MB - total_height);
+
+ } else {
+ image->tile_column_width[0] = EXTENDED_WIDTH_BLOCKS(image);
+ image->tile_column_position[0] = 0;
+
+ image->tile_row_height[0] = EXTENDED_HEIGHT_BLOCKS(image);
+ image->tile_row_position[0] = 0;
+ }
+
+ image->lwf_test = 0;
+
+ _jxr_make_mbstore(image, 1);
+ image->cur_my = -5;
+ return 0;
+}
+
+int jxr_write_image_bitstream(jxr_image_t image, FILE*fd)
+{
+ int rc, res = 0;
+
+ struct wbitstream bits;
+ _jxr_wbitstream_initialize(&bits, fd);
+
+ /* Clean up the image structure in preparation for actually
+ writing the image. This checks for and configures any
+ values left to defaults, and checks for bogus settings. */
+ rc = fill_in_image_defaults(image);
+ if (rc < 0)
+ return rc;
+
+ /* Prepare index table storage */
+ initialize_index_table(image);
+
+
+ rc = w_image_header(image, &bits);
+ assert(rc >= 0);
+
+ rc = w_image_plane_header(image, &bits, 0);
+ assert(rc >= 0);
+
+ if (ALPHACHANNEL_FLAG(image)) {
+ unsigned char window_params[5];
+ if (image->window_extra_top || image->window_extra_right) {
+ window_params[0] = 1;
+ window_params[1] = image->window_extra_top;
+ window_params[2] = image->window_extra_left;
+ window_params[3] = image->window_extra_bottom;
+ window_params[4] = image->window_extra_right;
+ }
+ else {
+ window_params[4] = window_params[3] = window_params[2] = window_params[1] = window_params[0] = 0;
+ }
+
+ image->alpha = jxr_create_image(image->width1 + 1, image->height1 + 1, window_params);
+
+ *image->alpha = *image;
+ image->alpha->strip[0].up4 = image->alpha->strip[0].up3 = image->alpha->strip[0].up2 =
+ image->alpha->strip[0].up1 = image->alpha->strip[0].cur = NULL;
+
+ jxr_set_INTERNAL_CLR_FMT(image->alpha, JXR_YONLY, 1);
+ _jxr_make_mbstore(image->alpha, 1);
+ image->alpha->dc_component_mode = image->alpha->lp_component_mode = image->alpha->hp_component_mode = JXR_CM_UNIFORM;
+ image->alpha->primary = 0;
+ image->alpha->cur_my = -5;
+
+ rc = w_image_plane_header(image->alpha, &bits, 1);
+ assert(rc >= 0);
+ }
+
+ if (INDEXTABLE_PRESENT_FLAG(image)) {
+ struct wbitstream strCodedTiles;
+ FILE*fdCodedTiles = fopen("codedtiles.tmp", "wb");
+ uint64_t subsequent_bytes;
+ struct rbitstream strCodedTilesRead;
+ FILE*fdCodedTilesRead;
+ size_t idx;
+ _jxr_wbitstream_initialize(&strCodedTiles, fdCodedTiles);
+
+ /* CODED_TILES() */
+ w_TILE(image, &strCodedTiles);
+
+ w_INDEX_TABLE(image, &bits);
+
+ _jxr_wbitstream_flush(&strCodedTiles);
+ fclose(fdCodedTiles);
+
+ /* Profile / Level info */
+ subsequent_bytes = 4;
+ _jxr_wbitstream_intVLW(&bits, subsequent_bytes);
+
+ if (subsequent_bytes > 0) {
+ uint64_t additional_bytes;
+ uint64_t ibyte;
+
+ additional_bytes = w_PROFILE_LEVEL_INFO(image, &bits, subsequent_bytes) ;
+
+ for (ibyte = 0 ; ibyte < additional_bytes ; ibyte += 1)
+ _jxr_wbitstream_uint8(&bits, 0); /* RESERVED_A_BYTE */
+ }
+
+ DEBUG("MARK HERE as the tile base. bitpos=%zu\n", _jxr_wbitstream_bitpos(&bits));
+ _jxr_wbitstream_mark(&bits);
+
+ fdCodedTilesRead = fopen("codedtiles.tmp", "rb");
+ _jxr_rbitstream_initialize(&strCodedTilesRead, fdCodedTilesRead);
+
+ for (idx = 0; idx < strCodedTiles.write_count; idx++) {
+ _jxr_wbitstream_uint8(&bits, _jxr_rbitstream_uint8(&strCodedTilesRead));
+ }
+ fclose(fdCodedTilesRead);
+ /* delete file associated with CodedTiles */
+ remove("codedtiles.tmp");
+
+ }
+ else {
+ /* Profile / Level info */
+ uint64_t subsequent_bytes = 4;
+ _jxr_wbitstream_intVLW(&bits, subsequent_bytes);
+
+ if (subsequent_bytes > 0) {
+ uint64_t additional_bytes;
+ uint64_t ibyte;
+ additional_bytes = w_PROFILE_LEVEL_INFO(image, &bits, subsequent_bytes) ;
+
+ for (ibyte = 0 ; ibyte < additional_bytes ; ibyte += 1)
+ _jxr_wbitstream_uint8(&bits, 0); /* RESERVED_A_BYTE */
+ }
+
+ DEBUG("MARK HERE as the tile base. bitpos=%zu\n", _jxr_wbitstream_bitpos(&bits));
+ _jxr_wbitstream_mark(&bits);
+
+ /* CODED_TILES() */
+ w_TILE(image, &bits);
+ }
+
+ _jxr_wbitstream_flush(&bits);
+
+#ifdef VERIFY_16BIT
+ if(image->lwf_test == 0)
+ DEBUG("Meets conditions for LONG_WORD_FLAG == 0!");
+ else {
+ DEBUG("Does not meet conditions for LONG_WORD_FLAG == 0!");
+ if (LONG_WORD_FLAG(image) == 0)
+ return JXR_EC_BADFORMAT;
+ }
+#endif
+
+ return res;
+}
+
+#if defined(DETAILED_DEBUG)
+static const char*bitdepth_names[16] = {
+ "BD1WHITE1", "BD8", "BD16", "BD16S",
+ "BD16F", "RESERVED5", "BD32S", "BD32F",
+ "BD5", "BD10", "BD565", "RESERVED11"
+ "RESERVED12", "RESERVED12", "RESERVED12","BD1BLACK1"
+};
+
+#endif
+
+static int w_image_header(jxr_image_t image, struct wbitstream*str)
+{
+ const char GDI_SIG[] = "WMPHOTO\0";
+ int res = 0;
+ unsigned idx;
+
+ /* GDI SIGNATURE */
+ for (idx = 0 ; idx < 8 ; idx += 1) {
+ _jxr_wbitstream_uint8(str, GDI_SIG[idx]);
+ }
+
+ DEBUG("START IMAGE_HEADER (bitpos=%zu)\n", _jxr_wbitstream_bitpos(str));
+
+ _jxr_wbitstream_uint4(str, 1); /* VERSION_INFO */
+
+ _jxr_wbitstream_uint1(str, image->disableTileOverlapFlag); /* HARD_TILING_FLAG */
+
+ _jxr_wbitstream_uint3(str, 1); /* SUB_VERSION_INFO */
+
+ DEBUG(" Flags group1=0x%02x\n", image->header_flags1);
+ _jxr_wbitstream_uint8(str, image->header_flags1);
+
+ DEBUG(" Flags group2=0x%02x\n", image->header_flags2);
+ _jxr_wbitstream_uint8(str, image->header_flags2);
+
+ DEBUG(" OUTPUT_CLR_FMT=%d\n", SOURCE_CLR_FMT(image));
+ DEBUG(" OUTPUT_BITEDPTH=%d (%s)\n", SOURCE_BITDEPTH(image), bitdepth_names[SOURCE_BITDEPTH(image)]);
+ _jxr_wbitstream_uint8(str, image->header_flags_fmt);
+
+ if (SHORT_HEADER_FLAG(image)) {
+ DEBUG(" SHORT_HEADER_FLAG=true\n");
+ _jxr_wbitstream_uint16(str, image->width1);
+ _jxr_wbitstream_uint16(str, image->height1);
+ } else {
+ DEBUG(" SHORT_HEADER_FLAG=false\n");
+ _jxr_wbitstream_uint32(str, image->width1);
+ _jxr_wbitstream_uint32(str, image->height1);
+ }
+
+ DEBUG(" Image dimensions: %u x %u\n", image->width1+1, image->height1+1);
+
+ /* Write TILE geometry information, if there is TILING. */
+ if (jxr_get_TILING_FLAG(image)) {
+
+ DEBUG(" TILING %u columns, %u rows\n",
+ image->tile_columns, image->tile_rows);
+
+ _jxr_wbitstream_uint12(str, image->tile_columns -1);
+ _jxr_wbitstream_uint12(str, image->tile_rows -1);
+
+ for (idx = 0 ; idx < image->tile_columns-1 ; idx += 1) {
+ if (SHORT_HEADER_FLAG(image))
+ _jxr_wbitstream_uint8(str, image->tile_column_width[idx]);
+ else
+ _jxr_wbitstream_uint16(str,image->tile_column_width[idx]);
+ }
+ for (idx = 0 ; idx < image->tile_rows-1 ; idx += 1) {
+ if (SHORT_HEADER_FLAG(image))
+ _jxr_wbitstream_uint8(str, image->tile_row_height[idx]);
+ else
+ _jxr_wbitstream_uint16(str,image->tile_row_height[idx]);
+ }
+ } else {
+ DEBUG(" NO TILING\n");
+ }
+
+#if defined(DETAILED_DEBUG)
+ DEBUG(" Tile widths:");
+ for (idx = 0 ; idx < image->tile_columns ; idx += 1)
+ DEBUG(" %u", image->tile_column_width[idx]);
+ DEBUG("\n");
+ DEBUG(" Tile heights:");
+ for (idx = 0 ; idx < image->tile_rows ; idx += 1)
+ DEBUG(" %u", image->tile_row_height[idx]);
+ DEBUG("\n");
+#endif
+
+ /* Write out windowing bits. */
+ if (WINDOWING_FLAG(image)) {
+ _jxr_wbitstream_uint6(str, (uint8_t)image->window_extra_top);
+ _jxr_wbitstream_uint6(str, (uint8_t)image->window_extra_left);
+ _jxr_wbitstream_uint6(str, (uint8_t)image->window_extra_bottom);
+ _jxr_wbitstream_uint6(str, (uint8_t)image->window_extra_right);
+ }
+
+ DEBUG("END IMAGE_HEADER\n");
+ return res;
+}
+
+static int w_image_plane_header(jxr_image_t image, struct wbitstream*str, int alpha)
+{
+ DEBUG("START IMAGE_PLANE_HEADER (bitpos=%zu)\n", _jxr_wbitstream_bitpos(str));
+
+ DEBUG(" INTERNAL_CLR_FMT = %d\n", image->use_clr_fmt);
+ DEBUG(" SCALED_FLAG = %s\n", image->scaled_flag? "true" : "false");
+ DEBUG(" BANDS_PRESENT = %d\n", image->bands_present);
+
+ _jxr_wbitstream_uint3(str, image->use_clr_fmt);
+ _jxr_wbitstream_uint1(str, image->scaled_flag); /* SCALED_FLAG = 1 */
+ _jxr_wbitstream_uint4(str, image->bands_present);
+
+ switch (image->use_clr_fmt) {
+ case 0: /* YONLY */
+ image->num_channels = 1;
+ break;
+ case 1: /* YUV420 */
+ image->num_channels = 3;
+ _jxr_wbitstream_uint4(str, 0); /* CHROMA_CENTERING */
+ _jxr_wbitstream_uint4(str, 0); /* COLOR_INTERPRETATION==0 */
+ break;
+ case 2: /* YUV422 */
+ image->num_channels = 3;
+ _jxr_wbitstream_uint4(str, 0); /* CHROMA_CENTERING */
+ _jxr_wbitstream_uint4(str, 0); /* COLOR_INTERPRETATION==0 */
+ break;
+ case 3: /* YUV444 */
+ image->num_channels = 3;
+ _jxr_wbitstream_uint4(str, 0); /* CHROMA_CENTERING */
+ _jxr_wbitstream_uint4(str, 0); /* COLOR_INTERPRETATION==0 */
+ break;
+ case 4: /* YUVK */
+ image->num_channels = 4;
+ break;
+ case 6: /* NCOMPONENT */
+ _jxr_wbitstream_uint4(str, image->num_channels-1);
+ _jxr_wbitstream_uint4(str, 0); /* COLOR_INTERPRETATION==0 */
+ break;
+ case 5: /* RESERVED */
+ case 7: /* RESERVED */
+ break;
+ }
+
+ switch (SOURCE_BITDEPTH(image)) {
+ case 0: /* BD1WHITE1 */
+ case 1: /* BD8 */
+ case 4: /* BD16F */
+ case 8: /* BD5 */
+ case 9: /* BD10 */
+ case 10: /* BD565 */
+ case 15: /* BD1BLACK1 */
+ break;
+ case 2: /* BD16 */
+ case 3: /* BD16S */
+ case 6: /* BD32S */
+ _jxr_wbitstream_uint8(str, image->shift_bits); /* SHIFT_BITS */
+ break;
+ case 7: /* BD32F */
+ _jxr_wbitstream_uint8(str, image->len_mantissa); /* LEN_MANTISSA */
+ _jxr_wbitstream_uint8(str, image->exp_bias); /* EXP_BIAS */
+ break;
+ default: /* RESERVED */
+ break;
+ }
+
+ /* Emit QP information for DC pass. */
+ _jxr_wbitstream_uint1(str, image->dc_frame_uniform); /* DC_FRAME_UNIFORM */
+ if (image->dc_frame_uniform) {
+ DEBUG(" DC_FRAME_UNIFORM = %s\n", image->dc_frame_uniform?"true":"false");
+ _jxr_w_DC_QP(image, str);
+ }
+
+ if (image->bands_present != 3 /*DCONLY*/) {
+ /* Emit QP information for LP pass. */
+ _jxr_wbitstream_uint1(str, 0); /* RESERVED_I_BIT */
+ _jxr_wbitstream_uint1(str, image->lp_frame_uniform);
+ DEBUG(" LP_FRAME_UNIFORM = %s\n", image->lp_frame_uniform?"true":"false");
+ if (image->lp_frame_uniform) {
+ assert(image->num_lp_qps > 0);
+ /* _jxr_wbitstream_uint4(str, image->num_lp_qps-1); */
+ _jxr_w_LP_QP(image, str);
+ }
+
+ if (image->bands_present != 2 /*NOHIGHPASS*/) {
+ /* Emit QP information for HP pass. */
+ _jxr_wbitstream_uint1(str, 0); /* RESERVED_J_BIT */
+ _jxr_wbitstream_uint1(str, image->hp_frame_uniform);
+ DEBUG(" HP_FRAME_UNIFORM = %s\n", image->hp_frame_uniform?"true":"false");
+ if (image->hp_frame_uniform) {
+ _jxr_w_HP_QP(image, str);
+ }
+ }
+ }
+
+ _jxr_wbitstream_syncbyte(str);
+ DEBUG("END IMAGE_PLANE_HEADER (bitpos=%zu)\n", _jxr_wbitstream_bitpos(str));
+
+ return 0;
+}
+
+static int put_ch_mode(jxr_image_t image, struct wbitstream*str)
+{
+ int use_mode;
+ /* If there is only 1 channel, then CH_MODE==0 is implicit. */
+ if (image->num_channels == 1) {
+ assert(image->dc_component_mode == JXR_CM_UNIFORM);
+ return 0;
+ }
+
+ use_mode = image->dc_component_mode;
+ _jxr_wbitstream_uint2(str, use_mode);
+ return use_mode;
+}
+
+void _jxr_w_DC_QP(jxr_image_t image, struct wbitstream*str)
+{
+ int idx;
+ int ch_mode = put_ch_mode(image, str);
+ DEBUG(" DC_QP CH_MODE=%d ", ch_mode);
+
+ switch (ch_mode) {
+ case 0: /* UNIFORM */
+ DEBUG(" DC_QUANT UNIFORM =%u", image->dc_quant_ch[0]);
+ _jxr_wbitstream_uint8(str, image->dc_quant_ch[0]);
+ break;
+ case 1: /* SEPARATE */
+ DEBUG(" DC_QUANT SEPARATE Y=%u, Chr=%u", image->dc_quant_ch[0],image->dc_quant_ch[1]);
+ _jxr_wbitstream_uint8(str, image->dc_quant_ch[0]);
+ _jxr_wbitstream_uint8(str, image->dc_quant_ch[1]);
+ break;
+ case 2: /* INDEPENDENT */
+ DEBUG(" DC_QUANT INDEPENDENT =");
+ for (idx = 0 ; idx < image->num_channels ; idx +=1) {
+ DEBUG(" %u", image->dc_quant_ch[idx]);
+ _jxr_wbitstream_uint8(str, image->dc_quant_ch[idx]);
+ }
+ break;
+ case 3: /* Reserved */
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ DEBUG("\n");
+}
+
+void _jxr_w_LP_QP(jxr_image_t image, struct wbitstream*str)
+{
+ unsigned idx;
+ for (idx = 0 ; idx < image->num_lp_qps ; idx += 1) {
+ int ch_mode = put_ch_mode(image, str);
+ int ch;
+ DEBUG(" LP_QP[%d] CH_MODE=%d ", idx, ch_mode);
+
+ switch (ch_mode) {
+ case 0: /* UNIFORM */
+ DEBUG(" LP_QUANT UNIFORM =%u", image->lp_quant_ch[0][idx]);
+ _jxr_wbitstream_uint8(str, image->lp_quant_ch[0][idx]);
+ break;
+ case 1: /* SEPARATE */
+ DEBUG(" LP_QUANT SEPARATE Y=%u, Chr=%u", image->lp_quant_ch[0][idx],image->lp_quant_ch[1][idx]);
+ _jxr_wbitstream_uint8(str, image->lp_quant_ch[0][idx]);
+ _jxr_wbitstream_uint8(str, image->lp_quant_ch[1][idx]);
+ break;
+ case 2: /* INDEPENDENT */
+ DEBUG(" LP_QUANT INDEPENDENT =");
+ for (ch = 0 ; ch < image->num_channels ; ch +=1) {
+ DEBUG(" %u", image->lp_quant_ch[ch][idx]);
+ _jxr_wbitstream_uint8(str, image->lp_quant_ch[ch][idx]);
+ }
+ break;
+ case 3: /* Reserved */
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ DEBUG("\n");
+ }
+}
+
+void _jxr_w_HP_QP(jxr_image_t image, struct wbitstream*str)
+{
+ unsigned idx;
+ for (idx = 0 ; idx < image->num_hp_qps ; idx += 1) {
+ int ch_mode = put_ch_mode(image, str);
+ int ch;
+ DEBUG(" HP_QP[%d] CH_MODE=%d ", idx, ch_mode);
+
+ switch (ch_mode) {
+ case 0: /* UNIFORM */
+ _jxr_wbitstream_uint8(str, image->hp_quant_ch[0][idx]);
+ DEBUG("UNIFORM %d", image->hp_quant_ch[0][idx]);
+ break;
+ case 1: /* SEPARATE */
+ DEBUG("SEPARATE Y=%u, Chr=%u", image->hp_quant_ch[0][idx],image->hp_quant_ch[1][idx]);
+ _jxr_wbitstream_uint8(str, image->hp_quant_ch[0][idx]);
+ _jxr_wbitstream_uint8(str, image->hp_quant_ch[1][idx]);
+ break;
+ case 2: /* INDEPENDENT */
+ DEBUG("INDEPENDENT =");
+ for (ch = 0 ; ch < image->num_channels ; ch +=1) {
+ DEBUG(" %u", image->hp_quant_ch[ch][idx]);
+ _jxr_wbitstream_uint8(str, image->hp_quant_ch[ch][idx]);
+ }
+ break;
+ case 3: /* Reserved */
+ break;
+ default:
+ assert(0);
+ }
+ DEBUG(" bitpos=%zu\n", _jxr_wbitstream_bitpos(str));
+ }
+}
+
+static void w_INDEX_TABLE(jxr_image_t image, struct wbitstream*str)
+{
+ DEBUG("START INDEX_TABLE at bitpos=%zu\n", _jxr_wbitstream_bitpos(str));
+
+ if (INDEXTABLE_PRESENT_FLAG(image)) {
+ int idx;
+ /* INDEX_TABLE_STARTCODE == 0x0001 */
+ DEBUG(" INDEX_TAB:E_STARTCODE at bitpos=%zu\n", _jxr_wbitstream_bitpos(str));
+ _jxr_wbitstream_uint8(str, 0x00);
+ _jxr_wbitstream_uint8(str, 0x01);
+
+ for (idx = 0 ; idx < image->tile_index_table_length ; idx++) {
+ _jxr_wbitstream_intVLW(str, image->tile_index_table[idx]);
+ }
+
+ DEBUG(" INDEX_TABLE has %d table entries\n", image->tile_index_table_length);
+
+ }
+
+ DEBUG("INTEX_TABLE DONE bitpos=%zu\n", _jxr_wbitstream_bitpos(str));
+}
+
+static uint64_t w_PROFILE_LEVEL_INFO(jxr_image_t image, struct wbitstream*str, uint64_t bytes)
+{
+ uint64_t additional_bytes;
+ for (additional_bytes = bytes; additional_bytes > 3 ; additional_bytes -= 4) {
+ /* These profile and level values are default. More logic needed */
+ _jxr_wbitstream_uint8(str, image->profile_idc); /* PROFILE_IDC */
+ _jxr_wbitstream_uint8(str, image->level_idc); /* LEVEL_IDC */
+ _jxr_wbitstream_uint15(str, 0); /* RESERVED_L */
+ if (additional_bytes > 7)
+ _jxr_wbitstream_uint1(str, 0); /* LAST_FLAG */
+ else
+ _jxr_wbitstream_uint1(str, 1); /* LAST_FLAG */
+ }
+
+ return additional_bytes;
+}
+
+static void w_TILE(jxr_image_t image, struct wbitstream*str)
+{
+ unsigned tile_idx = 0;
+
+ if (FREQUENCY_MODE_CODESTREAM_FLAG(image) == 0 /* SPATIALMODE */) {
+
+ if (TILING_FLAG(image)) {
+ unsigned tx, ty;
+ for (ty = 0 ; ty < image->tile_rows ; ty += 1)
+ for (tx = 0 ; tx < image->tile_columns ; tx += 1) {
+ _jxr_w_TILE_SPATIAL(image, str, tx, ty);
+ image->tile_index_table[tile_idx] = str->write_count;
+ tile_idx++;
+ }
+ } else {
+ _jxr_w_TILE_SPATIAL(image, str, 0, 0);
+ }
+
+ } else { /* FREQUENCYMODE */
+ /* Temporarily declare these bitstreams til I figure out the tmp file vs in memory issue*/
+ unsigned tx, ty;
+ uint8_t bands_present = image->bands_present_of_primary;
+
+ for (ty = 0 ; ty < image->tile_rows ; ty += 1) {
+ for (tx = 0 ; tx < image->tile_columns ; tx += 1) {
+ _jxr_w_TILE_DC(image, str, tx, ty);
+ image->tile_index_table[tile_idx * (4 - bands_present) + 0] = str->write_count;
+ if (bands_present != 3) {
+ _jxr_w_TILE_LP(image, str, tx, ty);
+ image->tile_index_table[tile_idx * (4 - bands_present) + 1] = str->write_count;
+ if (bands_present != 2) {
+ _jxr_w_TILE_HP_FLEX(image, str, tx, ty);
+ }
+ }
+
+
+ tile_idx++;
+ }
+ }
+ }
+
+ if (INDEXTABLE_PRESENT_FLAG(image)) {
+ for (tile_idx = image->tile_index_table_length - 1 ; tile_idx > 0 ; tile_idx--) {
+ image->tile_index_table[tile_idx] = image->tile_index_table[tile_idx - 1];
+ }
+ image->tile_index_table[0] = 0;
+ }
+
+}
+
+
+static int short_header_ok(jxr_image_t image)
+{
+ /* If the image width or height is too big for short header,
+ then we need a long header. */
+ if (image->width1 >= 0x10000 || image->height1 >= 0x10000)
+ return 0;
+
+ /* If the tile width/height is too big for a short header,
+ then we need to use a long header. */
+ if (jxr_get_TILING_FLAG(image)) {
+ unsigned idx;
+
+ for (idx = 0 ; idx < image->tile_columns ; idx += 1)
+ if (jxr_get_TILE_WIDTH(image,idx)/16 > 0x100)
+ return 0;
+ for (idx = 0 ; idx < image->tile_rows ; idx += 1)
+ if (jxr_get_TILE_HEIGHT(image,idx)/16 > 0x100)
+ return 0;
+ }
+
+ /* If nothing else forces us to use a long header, then we can
+ use a short header. */
+ return 1;
+}
+
+static int need_windowing_flag(jxr_image_t image)
+{
+ if (image->window_extra_top > 0)
+ return 1;
+ if (image->window_extra_left > 0)
+ return 1;
+
+ return 0;
+}
+
+static int need_trim_flexbits_flag(jxr_image_t image)
+{
+ /* If no FLEXBTS data, then no TRIM_FLEXBITS flag */
+ if (image->bands_present != JXR_BP_ALL)
+ return 0;
+ if (image->trim_flexbits == 0)
+ return 0;
+
+ return 1;
+}
+
+void _jxr_w_TILE_HEADER_DC(jxr_image_t image, struct wbitstream*str,
+ int alpha_flag, unsigned tx, unsigned ty)
+{
+ if (image->dc_frame_uniform == 0) {
+ int ch;
+ struct jxr_tile_qp*cur;
+
+ /* per-tile configuration, so get the QP settings from the
+ per-tile store and make it current. */
+ assert(image->tile_quant);
+ cur = GET_TILE_QUANT(image, tx, ty);
+ image->dc_component_mode = cur->component_mode;
+ switch (image->dc_component_mode) {
+ case JXR_CM_UNIFORM:
+ for (ch = 0 ; ch < image->num_channels ; ch += 1)
+ image->dc_quant_ch[ch] = cur->channel[0].dc_qp;
+ break;
+ case JXR_CM_SEPARATE:
+ image->dc_quant_ch[0] = cur->channel[0].dc_qp;
+ for (ch = 1 ; ch < image->num_channels ; ch += 1)
+ image->dc_quant_ch[ch] = cur->channel[1].dc_qp;
+ break;
+ case JXR_CM_INDEPENDENT:
+ for (ch = 0 ; ch < image->num_channels ; ch += 1)
+ image->dc_quant_ch[ch] = cur->channel[ch].dc_qp;
+ break;
+ case JXR_CM_Reserved:
+ assert(0);
+ break;
+ }
+
+ _jxr_w_DC_QP(image, str);
+ }
+}
+
+void _jxr_w_TILE_HEADER_LOWPASS(jxr_image_t image, struct wbitstream*str,
+ int alpha_flag, unsigned tx, unsigned ty)
+{
+ if (image->lp_frame_uniform == 0) {
+ int ch;
+ unsigned idx;
+ struct jxr_tile_qp*cur;
+
+ /* per-tile configuration, so get the QP settings from the
+ per-tile store and make it current. */
+ assert(image->tile_quant);
+ cur = GET_TILE_QUANT(image, tx, ty);
+ image->lp_component_mode = cur->component_mode;
+ image->num_lp_qps = cur->channel[0].num_lp;
+
+ switch (image->lp_component_mode) {
+ case JXR_CM_UNIFORM:
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ for (idx = 0 ; idx < image->num_lp_qps ; idx += 1)
+ image->lp_quant_ch[ch][idx] = cur->channel[0].lp_qp[idx];
+ }
+ break;
+ case JXR_CM_SEPARATE:
+ for (idx = 0 ; idx < image->num_lp_qps ; idx += 1)
+ image->lp_quant_ch[0][idx] = cur->channel[0].lp_qp[idx];
+ for (ch = 1 ; ch < image->num_channels ; ch += 1) {
+ for (idx = 0 ; idx < image->num_lp_qps ; idx += 1)
+ image->lp_quant_ch[ch][idx] = cur->channel[1].lp_qp[idx];
+ }
+ break;
+ case JXR_CM_INDEPENDENT:
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ for (idx = 0 ; idx < image->num_lp_qps ; idx += 1)
+ image->lp_quant_ch[ch][idx] = cur->channel[ch].lp_qp[idx];
+ }
+ break;
+ case JXR_CM_Reserved:
+ assert(0);
+ break;
+ }
+
+ _jxr_wbitstream_uint1(str, 0); /* XXXX USE_DC_QP == FALSE */
+ assert(image->num_lp_qps > 0);
+ DEBUG(" TILE_HEADER_LP: NUM_LP_QPS = %d\n", image->num_lp_qps);
+ _jxr_wbitstream_uint4(str, image->num_lp_qps-1);
+ _jxr_w_LP_QP(image, str);
+ }
+}
+
+void _jxr_w_TILE_HEADER_HIGHPASS(jxr_image_t image, struct wbitstream*str,
+ int alpha_flag, unsigned tx, unsigned ty)
+{
+ if (image->hp_frame_uniform == 0) {
+ int ch;
+ unsigned idx;
+ struct jxr_tile_qp*cur;
+
+ /* per-tile configuration, so get the QP settings from the
+ per-tile store and make it current. */
+ assert(image->tile_quant);
+ cur = GET_TILE_QUANT(image, tx, ty);
+ image->hp_component_mode = cur->component_mode;
+ image->num_hp_qps = cur->channel[0].num_hp;
+
+ switch (image->hp_component_mode) {
+ case JXR_CM_UNIFORM:
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ for (idx = 0 ; idx < image->num_hp_qps ; idx += 1)
+ image->hp_quant_ch[ch][idx] = cur->channel[0].hp_qp[idx];
+ }
+ break;
+ case JXR_CM_SEPARATE:
+ for (idx = 0 ; idx < image->num_hp_qps ; idx += 1)
+ image->hp_quant_ch[0][idx] = cur->channel[0].hp_qp[idx];
+ for (ch = 1 ; ch < image->num_channels ; ch += 1) {
+ for (idx = 0 ; idx < image->num_hp_qps ; idx += 1)
+ image->hp_quant_ch[ch][idx] = cur->channel[1].hp_qp[idx];
+ }
+ break;
+ case JXR_CM_INDEPENDENT:
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ for (idx = 0 ; idx < image->num_hp_qps ; idx += 1)
+ image->hp_quant_ch[ch][idx] = cur->channel[ch].hp_qp[idx];
+ }
+ break;
+ case JXR_CM_Reserved:
+ assert(0);
+ break;
+ }
+
+ _jxr_wbitstream_uint1(str, 0); /* XXXX USE_LP_QP == FALSE */
+ assert(image->num_hp_qps > 0);
+ _jxr_wbitstream_uint4(str, image->num_hp_qps-1);
+ _jxr_w_HP_QP(image, str);
+ }
+}
+
+void _jxr_w_ENCODE_QP_INDEX(jxr_image_t image, struct wbitstream*str,
+ unsigned tx, unsigned ty, unsigned mx, unsigned my,
+ unsigned num_qps, unsigned qp_index)
+{
+ static const unsigned bits_qp_index[17] = {0, 0,1,1,2, 2,3,3,3, 3,4,4,4, 4,4,4,4};
+ int bits_count;
+
+ assert(num_qps > 1 && num_qps <= 16);
+
+ if (qp_index == 0) {
+ /* IS_QPINDEX_NONZERO_FLAG == false */
+ _jxr_wbitstream_uint1(str, 0);
+ return;
+ }
+
+ /* IS_QPINDEX_NONZERO_FLAG == true */
+ _jxr_wbitstream_uint1(str, 1);
+
+ bits_count = bits_qp_index[num_qps];
+ assert(bits_count > 0); /* num_qps must be >1 here. */
+
+ _jxr_wbitstream_uintN(str, qp_index-1, bits_count);
+}
+
+static void encode_val_dc_yuv(jxr_image_t image, struct wbitstream*str, int val)
+{
+ assert(val >= 0 && val <= 7);
+
+ switch (val) {
+ case 0: /* 10 */
+ _jxr_wbitstream_uint2(str, 2);
+ break;
+ case 1: /* 001 */
+ _jxr_wbitstream_uint2(str, 0);
+ _jxr_wbitstream_uint1(str, 1);
+ break;
+ case 2: /* 0000 1 */
+ _jxr_wbitstream_uint4(str, 0);
+ _jxr_wbitstream_uint1(str, 1);
+ break;
+ case 3: /* 0001 */
+ _jxr_wbitstream_uint4(str, 1);
+ break;
+ case 4: /* 11 */
+ _jxr_wbitstream_uint2(str, 3);
+ break;
+ case 5: /* 010 */
+ _jxr_wbitstream_uint2(str, 1);
+ _jxr_wbitstream_uint1(str, 0);
+ break;
+ case 6: /* 0000 0 */
+ _jxr_wbitstream_uint4(str, 0);
+ _jxr_wbitstream_uint1(str, 0);
+ break;
+ case 7: /* 011 */
+ _jxr_wbitstream_uint2(str, 1);
+ _jxr_wbitstream_uint1(str, 1);
+ break;
+ }
+}
+
+void _jxr_w_MB_DC(jxr_image_t image, struct wbitstream*str,
+ int alpha_flag,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my)
+{
+ int lap_mean[2];
+ lap_mean[0] = 0;
+ lap_mean[1] = 0;
+
+ DEBUG(" MB_DC tile=[%u %u] mb=[%u %u] bitpos=%zu\n",
+ tx, ty, mx, my, _jxr_wbitstream_bitpos(str));
+
+ if (_jxr_InitContext(image, tx, ty, mx, my)) {
+ DEBUG(" MB_DC: Initialize Context\n");
+ _jxr_InitVLCTable(image, AbsLevelIndDCLum);
+ _jxr_InitVLCTable(image, AbsLevelIndDCChr);
+ _jxr_InitializeModelMB(&image->model_dc, 0/*DC*/);
+ }
+
+ if (image->use_clr_fmt==0 || image->use_clr_fmt==4 || image->use_clr_fmt==6) {
+ int32_t dc_val = 0;
+
+ /* clr_fmt == YONLY, YUVK or NCOMPONENT */
+ unsigned idx;
+ for (idx = 0 ; idx < image->num_channels ; idx += 1) {
+ int m = (idx == 0)? 0 : 1;
+ int model_bits = image->model_dc.bits[m];
+
+ unsigned is_dc_ch = (labs(dc_val)>>model_bits) != 0 ? 1 : 0;
+
+ dc_val = MACROBLK_CUR_DC(image,idx,tx,mx);
+ m = (idx == 0)? 0 : 1;
+ model_bits = image->model_dc.bits[m];
+
+ is_dc_ch = (labs(dc_val)>>model_bits) != 0 ? 1 : 0;
+ _jxr_wbitstream_uint1(str, is_dc_ch);
+ DEBUG(" MB_DC: IS_DC_CH=%u, model_bits=%d\n",
+ is_dc_ch, model_bits);
+ if (is_dc_ch) {
+ lap_mean[m] += 1;
+ }
+ DEBUG(" dc_val at t=[%u %u], m=[%u %u] == %d (0x%08x)\n",
+ tx, ty, mx, my, dc_val, dc_val);
+ w_DEC_DC(image, str, model_bits, 0/*chroma*/, is_dc_ch, dc_val);
+ }
+ } else {
+ int32_t dc_val_Y = MACROBLK_CUR_DC(image,0,tx,mx);
+ int32_t dc_val_U = MACROBLK_CUR_DC(image,1,tx,mx);
+ int32_t dc_val_V = MACROBLK_CUR_DC(image,2,tx,mx);
+ int val_dc_yuv = 0;
+ int model_bits;
+ int is_dc_ch;
+
+ if ((labs(dc_val_Y) >> image->model_dc.bits[0]) != 0) {
+ val_dc_yuv |= 0x4;
+ lap_mean[0] += 1;
+ }
+ if ((labs(dc_val_U) >> image->model_dc.bits[1]) != 0) {
+ val_dc_yuv |= 0x2;
+ lap_mean[1] += 1;
+ }
+ if ((labs(dc_val_V) >> image->model_dc.bits[1]) != 0) {
+ val_dc_yuv |= 0x1;
+ lap_mean[1] += 1;
+ }
+
+ DEBUG(" VAL_DC_YUV = %x\n", val_dc_yuv);
+ encode_val_dc_yuv(image, str, val_dc_yuv);
+
+ DEBUG(" dc_val_Y at t=[%u %u], m=[%u %u] == %d (0x%08x)\n",
+ tx, ty, mx, my, dc_val_Y, dc_val_Y);
+ model_bits = image->model_dc.bits[0];
+ is_dc_ch = val_dc_yuv&0x4 ? 1 : 0;
+ w_DEC_DC(image, str, model_bits, 0/*chroma*/, is_dc_ch, dc_val_Y);
+
+ DEBUG(" dc_val_U at t=[%u %u], m=[%u %u] == %d (0x%08x)\n",
+ tx, ty, mx, my, dc_val_U, dc_val_U);
+ model_bits = image->model_dc.bits[1];
+ is_dc_ch = val_dc_yuv&0x2 ? 1 : 0;
+ w_DEC_DC(image, str, model_bits, 1/*chroma*/, is_dc_ch, dc_val_U);
+
+ DEBUG(" dc_val_V at t=[%u %u], m=[%u %u] == %d (0x%08x)\n",
+ tx, ty, mx, my, dc_val_V, dc_val_V);
+ model_bits = image->model_dc.bits[1];
+ is_dc_ch = val_dc_yuv&0x1 ? 1 : 0;
+ w_DEC_DC(image, str, model_bits, 1/*chroma*/, is_dc_ch, dc_val_V);
+ }
+
+ /* */
+ DEBUG(" MB_DC: UpdateModelMB: lap_mean={%u %u}\n", lap_mean[0], lap_mean[1]);
+ _jxr_UpdateModelMB(image, lap_mean, &image->model_dc, 0/*DC*/);
+ if (_jxr_ResetContext(image, tx, mx)) {
+ DEBUG(" MB_DC: Reset Context\n");
+ _jxr_AdaptVLCTable(image, AbsLevelIndDCLum);
+ _jxr_AdaptVLCTable(image, AbsLevelIndDCChr);
+ }
+
+ DEBUG(" MB_DC DONE tile=[%u %u] mb=[%u %u]\n", tx, ty, mx, my);
+}
+
+static void w_REFINE_LP(struct wbitstream*str, int coeff, int model_bits)
+{
+ if (coeff > 0) {
+ _jxr_wbitstream_uintN(str, coeff, model_bits);
+ coeff >>= model_bits;
+ if (coeff == 0)
+ _jxr_wbitstream_uint1(str, 0);
+ } else if (coeff < 0) {
+ coeff = -coeff;
+ _jxr_wbitstream_uintN(str, coeff, model_bits);
+ coeff >>= model_bits;
+ if (coeff == 0)
+ _jxr_wbitstream_uint1(str, 1);
+ } else {
+ _jxr_wbitstream_uintN(str, 0, model_bits);
+ coeff >>= model_bits;
+ /* No sign bit is needed for zero values. */
+ }
+}
+
+/*
+* This maps the values in src[1-15] into dst[1-15], and adapts the
+* map as it goes.
+*/
+static void AdaptiveLPPermute(jxr_image_t image, int dst[16], const int src[16])
+{
+ int idx;
+ for (idx = 1 ; idx < 16 ; idx += 1) {
+
+ int map = image->lopass_scanorder[idx-1];
+ dst[idx] = src[map];
+
+ if (dst[idx] == 0)
+ continue;
+
+ image->lopass_scantotals[idx-1] += 1;
+
+ if (idx > 1 && image->lopass_scantotals[idx-1] > image->lopass_scantotals[idx-2]) {
+ SWAP(image->lopass_scantotals[idx-1], image->lopass_scantotals[idx-2]);
+ SWAP(image->lopass_scanorder[idx-1], image->lopass_scanorder[idx-2]);
+ }
+ }
+}
+
+static void FixedLPPermuteUV(jxr_image_t image, int dst[16], int src[8][16])
+{
+ int k;
+ int count_chr = 14;
+ static const int remap_arr422[] = {4, 1, 2, 3, 5, 6, 7};
+
+ assert(image->use_clr_fmt==1/*YUV420*/ || image->use_clr_fmt==2/*YUV422*/);
+
+ if (image->use_clr_fmt==1/*YUV420*/)
+ count_chr = 6;
+
+ /* Shuffle the UV planes into a single dst */
+ for (k = 0; k < count_chr; k += 1) {
+ int remap = k>>1;
+ int plane = (k&1) + 1; /* 1 or 2 (U or V) */
+
+ if (image->use_clr_fmt==1/*YUV420*/)
+ remap += 1;
+ if (image->use_clr_fmt==2/*YUV422*/)
+ remap = remap_arr422[remap];
+
+ if (image->use_clr_fmt==1/*YUV420*/)
+ remap = transpose420[remap];
+ if (image->use_clr_fmt==2/*YUV422*/)
+ remap = transpose422[remap];
+ dst[k+1] = src[plane][remap];
+ }
+
+ for (k = count_chr; k < 15; k += 1)
+ dst[k+1] = 0;
+}
+
+static void AdaptiveHPPermute(jxr_image_t image, int dst[16], const int src[16], int mbhp_pred_mode)
+{
+ if (mbhp_pred_mode == 1) {
+ int idx;
+ for (idx = 1 ; idx < 16 ; idx += 1) {
+ int map = image->hipass_ver_scanorder[idx-1];
+ dst[idx] = src[map];
+
+ if (dst[idx] == 0)
+ continue;
+
+ image->hipass_ver_scantotals[idx-1] += 1;
+
+
+ if (idx > 1 && image->hipass_ver_scantotals[idx-1] > image->hipass_ver_scantotals[idx-2]) {
+ SWAP(image->hipass_ver_scantotals[idx-1], image->hipass_ver_scantotals[idx-2]);
+ SWAP(image->hipass_ver_scanorder[idx-1], image->hipass_ver_scanorder[idx-2]);
+ }
+ }
+ } else {
+ int idx;
+ for (idx = 1 ; idx < 16 ; idx += 1) {
+ int map = image->hipass_hor_scanorder[idx-1];
+ dst[idx] = src[map];
+
+ if (dst[idx] == 0)
+ continue;
+
+ image->hipass_hor_scantotals[idx-1] += 1;
+
+
+ if (idx > 1 && image->hipass_hor_scantotals[idx-1] > image->hipass_hor_scantotals[idx-2]) {
+ SWAP(image->hipass_hor_scantotals[idx-1], image->hipass_hor_scantotals[idx-2]);
+ SWAP(image->hipass_hor_scanorder[idx-1], image->hipass_hor_scanorder[idx-2]);
+ }
+ }
+ }
+}
+
+/*
+* Convert the string of LP values to a compact list of non-zero LP
+* values interspersed with the run of zero values. This is what will
+* ultimately be encoded. The idea is that an LP set is generally
+* sparse and it is more compact to encode the zero-runs then the
+* zeros themselves.
+*/
+static int RunLengthEncode(jxr_image_t image, int RLCoeffs[32], const int LPInput[16])
+{
+ int lp_index = 1;
+ int rl_index = 0;
+ int run_count = 0;
+
+ DEBUG(" RLCoeffs:");
+ while (lp_index < 16) {
+ if (LPInput[lp_index] == 0) {
+ lp_index += 1;
+ run_count += 1;
+ continue;
+ }
+
+ assert(rl_index <= 30);
+ RLCoeffs[rl_index+0] = run_count;
+ RLCoeffs[rl_index+1] = LPInput[lp_index];
+
+ DEBUG(" %d--0x%x", RLCoeffs[rl_index+0], RLCoeffs[rl_index+1]);
+
+ rl_index += 2;
+ run_count = 0;
+ lp_index += 1;
+ }
+
+ DEBUG(" num_non_zero=%d\n", rl_index/2);
+
+ /* Return the number of non-zero values. */
+ return rl_index/2;
+}
+
+static int collect_lp_input(jxr_image_t image, int ch, int tx, int mx, int LPInput[8][16], int model_bits)
+{
+ int num_non_zero = 0;
+
+ int count = 16;
+ int k;
+ if (ch > 0 && image->use_clr_fmt==2/*YUV422*/)
+ count = 8;
+ if (ch > 0 && image->use_clr_fmt==1/*YUV420*/)
+ count = 4;
+
+ /* Collect into LPInput the coefficient values with the
+ model_bits stripped out. Be careful to shift only POSITIVE
+ numbers because the encoding later on uses magnitude-sign
+ to encode these values. The values can come out differently. */
+ for (k = 1 ; k < count ; k += 1) {
+ int sign_flag = 0;
+ LPInput[ch][k] = MACROBLK_CUR_LP(image,ch,tx,mx,k-1);
+ if (LPInput[ch][k] < 0) {
+ sign_flag = 1;
+ LPInput[ch][k] = -LPInput[ch][k];
+ }
+ LPInput[ch][k] >>= model_bits;
+ if (LPInput[ch][k] != 0) {
+ num_non_zero += 1;
+ if (sign_flag)
+ LPInput[ch][k] = -LPInput[ch][k];
+ }
+ }
+
+ return num_non_zero;
+}
+
+void _jxr_w_MB_LP(jxr_image_t image, struct wbitstream*str,
+ int alpha_flag,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my)
+{
+ int LPInput[8][16];
+ int idx;
+ int full_planes;
+ int lap_mean[2];
+ int ndx;
+ int cbplp;
+
+ lap_mean[0] = 0;
+ lap_mean[1] = 0;
+
+ for (idx = 0 ; idx < 8 ; idx += 1) {
+ int k;
+ for (k = 0 ; k < 16 ; k += 1)
+ LPInput[idx][k] = 0;
+ }
+
+
+ DEBUG(" MB_LP tile=[%u %u] mb=[%u %u] bitpos=%zu\n",
+ tx, ty, mx, my, _jxr_wbitstream_bitpos(str));
+
+ if (_jxr_InitContext(image, tx, ty, mx, my)) {
+ DEBUG(" Init contexts\n");
+ _jxr_InitializeCountCBPLP(image);
+ _jxr_InitLPVLC(image);
+ _jxr_InitializeAdaptiveScanLP(image);
+ _jxr_InitializeModelMB(&image->model_lp, 1/*LP*/);
+ }
+
+ if (_jxr_ResetTotals(image, mx)) {
+ _jxr_ResetTotalsAdaptiveScanLP(image);
+ }
+
+ full_planes = image->num_channels;
+ if (image->use_clr_fmt==1/*YUV420*/ || image->use_clr_fmt==2/*YUV422*/)
+ full_planes = 2;
+
+ /* The CBPLP signals whether any non-zero coefficients are
+ present in the LP band for this macroblock. It is a bitmask
+ with a bit for each channel. So for example, YONLY, which
+ has 1 channel, has a 1-bit cbplp. */
+
+ cbplp = 0;
+ /* if CLR_FMT is YUV420, YUV422 or YUV444... */
+ if (image->use_clr_fmt==1 || image->use_clr_fmt==2 || image->use_clr_fmt==3) {
+ int max;
+ int model_bits0;
+ int model_bits1;
+ int num_non_zero;
+ assert(full_planes == 2 || full_planes == 3);
+
+ max = full_planes * 4 - 5;
+ model_bits0 = image->model_lp.bits[0];
+ model_bits1 = image->model_lp.bits[1];
+
+ num_non_zero = collect_lp_input(image, 0, tx, mx, LPInput, model_bits0);
+ if (num_non_zero > 0)
+ cbplp |= 1;
+
+ switch (image->use_clr_fmt) {
+ case 1:/*YUV420*/
+ case 2:/*YUV422*/
+ /* YUV422 has a 2-bit CBPLP, the low bit is the
+ CBP for Y, and the high bit for UV. */
+ num_non_zero = collect_lp_input(image, 1, tx, mx, LPInput, model_bits1);
+ if (num_non_zero > 0)
+ cbplp |= 2;
+ num_non_zero = collect_lp_input(image, 2, tx, mx, LPInput, model_bits1);
+ if (num_non_zero > 0)
+ cbplp |= 2;
+ break;
+
+ case 3:/*YUV444*/
+ num_non_zero = collect_lp_input(image, 1, tx, mx, LPInput, model_bits1);
+ if (num_non_zero > 0)
+ cbplp |= 2;
+ num_non_zero = collect_lp_input(image, 2, tx, mx, LPInput, model_bits1);
+ if (num_non_zero > 0)
+ cbplp |= 4;
+ break;
+ }
+
+ DEBUG(" MB_LP: count_zero_CBPLP=%d, count_max_CBPLP=%d, bitpos=%zu\n",
+ image->count_zero_CBPLP, image->count_max_CBPLP, _jxr_wbitstream_bitpos(str));
+ if (image->count_zero_CBPLP <= 0 || image->count_max_CBPLP < 0) {
+ int cbplp_yuv;
+ if (image->count_max_CBPLP < image->count_zero_CBPLP) {
+ assert(max >= cbplp);
+ cbplp_yuv = max - cbplp;
+ } else {
+ cbplp_yuv = cbplp;
+ }
+ switch (image->use_clr_fmt) {
+ case 1:/*YUV420*/
+ case 2:/*YUV422*/
+ if (cbplp_yuv == 0) {
+ _jxr_wbitstream_uint1(str, 0); /* 0 */
+ } else if (cbplp_yuv == 1) {
+ _jxr_wbitstream_uint2(str, 2); /* 10 */
+ } else {
+ _jxr_wbitstream_uint2(str, 3);
+ if (cbplp_yuv == 2)
+ _jxr_wbitstream_uint1(str, 0); /* 110 */
+ else
+ _jxr_wbitstream_uint1(str, 1); /* 111 */
+ }
+ break;
+
+ case 3:/*YUV444*/
+ switch (cbplp_yuv) { /* YUV444 encoding */
+ case 0: /* 0 */
+ _jxr_wbitstream_uint1(str, 0);
+ break;
+ case 1: /* 100 */
+ _jxr_wbitstream_uint2(str, 2);
+ _jxr_wbitstream_uint1(str, 0);
+ break;
+ default:
+ _jxr_wbitstream_uint4(str, 0xaa + cbplp_yuv-2);
+ break;
+ }
+ break;
+ default:
+ assert(0);
+ }
+ } else {
+ int ch;
+ for (ch = 0 ; ch < full_planes ; ch += 1) {
+ if (cbplp & (1<<(full_planes-1-ch)))
+ _jxr_wbitstream_uint1(str, 1);
+ else
+ _jxr_wbitstream_uint1(str, 0);
+ }
+ }
+ _jxr_UpdateCountCBPLP(image, cbplp, max);
+
+ } else {
+ int ch;
+ cbplp = 0;
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ int chroma_flag = ch > 0? 1 : 0;
+ int model_bits = image->model_lp.bits[chroma_flag];
+ int num_non_zero;
+
+ DEBUG(" MB_LP: ch=%d, model_bits=%d\n", ch, model_bits);
+
+ num_non_zero = collect_lp_input(image, ch, tx, mx, LPInput, model_bits);
+
+ /* If there are non-zero coefficients, then CBPLP
+ for this plane is 1. Also, the CBPLP in the
+ stream is a single bit for each plane. */
+ if (num_non_zero > 0) {
+ _jxr_wbitstream_uint1(str, 1);
+ cbplp |= 1 << ch;
+ } else {
+ _jxr_wbitstream_uint1(str, 0);
+ }
+ }
+ }
+ DEBUG(" MB_LP: cbplp = 0x%x (full_planes=%u)\n", cbplp, full_planes);
+
+ for (ndx = 0 ; ndx < full_planes ; ndx += 1) {
+ const int chroma_flag = ndx>0? 1 : 0;
+ int model_bits;
+
+ DEBUG(" MB_LP: process full_plane %u, CBPLP for plane=%d, bitpos=%zu\n",
+ ndx, (cbplp>>ndx)&1, _jxr_wbitstream_bitpos(str));
+#if defined(DETAILED_DEBUG)
+ if (chroma_flag && image->use_clr_fmt == 2/*YUV422*/) {
+ int k;
+ DEBUG(" lp val[ndx=%d] refined data ==", ndx);
+ for (k = 1 ; k<8; k+=1) {
+ DEBUG(" 0x%x/0x%x", MACROBLK_CUR_LP(image,1,tx,mx,k-1), MACROBLK_CUR_LP(image,2,tx,mx,k-1));
+ }
+ DEBUG("\n");
+ DEBUG(" lp val[ndx=%d] before LPPermute ==", ndx);
+ for (k = 1 ; k<8; k+=1) {
+ DEBUG(" 0x%x/0x%x", LPInput[1][k], LPInput[2][k]);
+ }
+ DEBUG("\n");
+
+ } else if (chroma_flag && image->use_clr_fmt == 1/*YUV420*/) {
+ int k;
+ DEBUG(" lp val[ndx=%d] before LPPermute ==", ndx);
+ for (k = 1 ; k<4; k+=1) {
+ DEBUG(" 0x%x/0x%x", LPInput[1][k], LPInput[2][k]);
+ }
+ DEBUG("\n");
+
+ } else {
+ int k;
+ DEBUG(" lp val[ndx=%d] refined data ==", ndx);
+ for (k = 1 ; k<16; k+=1) {
+ DEBUG(" 0x%x", MACROBLK_CUR_LP(image,ndx,tx,mx,k-1));
+ }
+ DEBUG("\n");
+ DEBUG(" lp val[ndx=%d] before LPPermute ==", ndx);
+ for (k = 1 ; k<16; k+=1) {
+ DEBUG(" 0x%x", LPInput[ndx][k]);
+ }
+ DEBUG("\n");
+ DEBUG(" scan order ==");
+ for (k = 0 ; k<15; k+=1) {
+ DEBUG(" %2d", image->lopass_scanorder[k]);
+ }
+ DEBUG("\n");
+ DEBUG(" scan totals ==");
+ for (k = 0 ; k<15; k+=1) {
+ DEBUG(" %2d", image->lopass_scantotals[k]);
+ }
+ DEBUG("\n");
+ }
+#endif
+ /* If there are coeff bits, encode them. */
+ if ((cbplp>>ndx) & 1) {
+ int LPInput_n[16];
+ int RLCoeffs[32] = {0};
+ int num_non_zero;
+
+ if (chroma_flag && (image->use_clr_fmt==1 || image->use_clr_fmt==2)) {
+ /* LP for YUV42X components are shuffled by
+ a fixed permute. */
+ FixedLPPermuteUV(image, LPInput_n, LPInput);
+ } else {
+ /* LP for YUV444 components (and the Y of
+ all YUV) are adaptively ordered. */
+ AdaptiveLPPermute(image, LPInput_n, LPInput[ndx]);
+ }
+
+ num_non_zero = RunLengthEncode(image, RLCoeffs, LPInput_n);
+ w_DECODE_BLOCK(image, str, 1 /* LP */, chroma_flag, RLCoeffs, num_non_zero);
+ lap_mean[chroma_flag] += num_non_zero;
+ }
+
+ /* Emit REFINEMENT bits after the coeff bits are done. */
+
+ model_bits = image->model_lp.bits[chroma_flag];
+ if (model_bits) {
+ static const int transpose444[16] = { 0, 4, 8,12,
+ 1, 5, 9,13,
+ 2, 6,10,14,
+ 3, 7,11,15 };
+ DEBUG(" MB_LP: Start refine ndx=%d, model_bits=%d, bitpos=%zu\n",
+ ndx, model_bits, _jxr_wbitstream_bitpos(str));
+ if (chroma_flag == 0) {
+ int k;
+ for (k=1 ;k<16; k+=1) {
+ int k_ptr = transpose444[k];
+ w_REFINE_LP(str, MACROBLK_CUR_LP(image,ndx,tx,mx,k_ptr-1), model_bits);
+ }
+ } else {
+ int k;
+ switch (image->use_clr_fmt) {
+ case 1: /* YUV420 */
+ for (k=1 ; k<4; k+=1) {
+ int k_ptr = transpose420[k];
+ DEBUG(" MP_LP: Refine LP_Input[1/2][%d] = 0x%x/0x%x bitpos=%zu\n",
+ k_ptr, LPInput[1][k_ptr], LPInput[2][k_ptr],
+ _jxr_wbitstream_bitpos(str));
+ w_REFINE_LP(str, MACROBLK_CUR_LP(image,1,tx,mx,k_ptr-1), model_bits);
+ w_REFINE_LP(str, MACROBLK_CUR_LP(image,2,tx,mx,k_ptr-1), model_bits);
+ }
+ break;
+ case 2: /* YUV422 */
+ for (k=1 ; k<8; k+=1) {
+ int k_ptr = transpose422[k];
+ DEBUG(" MP_LP: Refine LP_Input[1/2][%d] = 0x%x/0x%x bitpos=%zu\n",
+ k_ptr, LPInput[1][k_ptr], LPInput[2][k_ptr],
+ _jxr_wbitstream_bitpos(str));
+ w_REFINE_LP(str, MACROBLK_CUR_LP(image,1,tx,mx,k_ptr-1), model_bits);
+ w_REFINE_LP(str, MACROBLK_CUR_LP(image,2,tx,mx,k_ptr-1), model_bits);
+ }
+ break;
+ default: /* All others */
+ for (k=1 ;k<16; k+=1) {
+ int k_ptr = transpose444[k];
+ w_REFINE_LP(str, MACROBLK_CUR_LP(image,ndx,tx,mx,k_ptr-1), model_bits);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ DEBUG(" MB_LP: UpdateModelMB lap_mean={%d, %d}\n", lap_mean[0], lap_mean[1]);
+ _jxr_UpdateModelMB(image, lap_mean, &image->model_lp, 1/*band=LP*/);
+ if (_jxr_ResetContext(image, tx, mx)) {
+ DEBUG(" AdaptLP at the end of mx=%d (my=%d, ndx=%u)\n", mx, my, ndx);
+ _jxr_AdaptLP(image);
+ }
+
+ DEBUG(" MB_LP DONE tile=[%u %u] mb=[%u %u]\n", tx, ty, mx, my);
+}
+
+static void encode_val_1(jxr_image_t image, struct wbitstream*str,
+struct adaptive_vlc_s*vlc, int val1, int chr_cbp)
+{
+ int tmp;
+
+ switch (image->use_clr_fmt) {
+ case 0: /* YONLY */
+ case 4: /* YUVK */
+ case 6: /* NCOMPONENT */
+ assert(val1 < 5);
+ if (vlc->table == 0) {
+ switch (val1) {
+ case 0:
+ _jxr_wbitstream_uint1(str, 1);
+ break;
+ case 1:
+ _jxr_wbitstream_uint1(str, 0);
+ _jxr_wbitstream_uint1(str, 1);
+ break;
+ case 2:
+ _jxr_wbitstream_uint1(str, 0);
+ _jxr_wbitstream_uint1(str, 0);
+ _jxr_wbitstream_uint1(str, 1);
+ break;
+ case 3:
+ _jxr_wbitstream_uint4(str, 0);
+ break;
+ case 4:
+ _jxr_wbitstream_uint4(str, 1);
+ break;
+ }
+ }
+ else {
+ switch (val1) {
+ case 0:
+ _jxr_wbitstream_uint1(str, 1);
+ break;
+ case 1:
+ _jxr_wbitstream_uint1(str, 0);
+ _jxr_wbitstream_uint2(str, 0);
+ break;
+ case 2:
+ _jxr_wbitstream_uint1(str, 0);
+ _jxr_wbitstream_uint2(str, 1);
+ break;
+ case 3:
+ _jxr_wbitstream_uint1(str, 0);
+ _jxr_wbitstream_uint2(str, 2);
+ break;
+ case 4:
+ _jxr_wbitstream_uint1(str, 0);
+ _jxr_wbitstream_uint2(str, 3);
+ break;
+ }
+ }
+ break;
+
+ case 1: /* YUV420 */
+ case 2: /* YUV422 */
+ case 3: /* YUV444 */
+ tmp = val1;
+ if (tmp > 8)
+ tmp = 8;
+
+ if (vlc->table == 0) {
+ switch (tmp) {
+ case 0: /* 010 */
+ _jxr_wbitstream_uint1(str, 0);
+ _jxr_wbitstream_uint2(str, 2);
+ break;
+ case 1: /* 00000 */
+ _jxr_wbitstream_uint1(str, 0);
+ _jxr_wbitstream_uint4(str, 0);
+ break;
+ case 2: /* 0010 */
+ _jxr_wbitstream_uint4(str, 2);
+ break;
+ case 3: /* 00001 */
+ _jxr_wbitstream_uint4(str, 0);
+ _jxr_wbitstream_uint1(str, 1);
+ break;
+ case 4: /* 00010 */
+ _jxr_wbitstream_uint4(str, 1);
+ _jxr_wbitstream_uint1(str, 0);
+ break;
+ case 5: /* 1 */
+ _jxr_wbitstream_uint1(str, 1);
+ break;
+ case 6: /* 011 */
+ _jxr_wbitstream_uint1(str, 0);
+ _jxr_wbitstream_uint2(str, 3);
+ break;
+ case 7: /* 00011 */
+ _jxr_wbitstream_uint4(str, 1);
+ _jxr_wbitstream_uint1(str, 1);
+ break;
+ case 8: /* 0011 */
+ _jxr_wbitstream_uint4(str, 3);
+ break;
+ }
+ }
+ else {
+ switch (tmp) {
+ case 0: /* 1 */
+ _jxr_wbitstream_uint1(str, 1);
+ break;
+ case 1: /* 001 */
+ _jxr_wbitstream_uint2(str, 0);
+ _jxr_wbitstream_uint1(str, 1);
+ break;
+ case 2: /* 010 */
+ _jxr_wbitstream_uint2(str, 1);
+ _jxr_wbitstream_uint1(str, 0);
+ break;
+ case 3: /* 0001 */
+ _jxr_wbitstream_uint4(str, 1);
+ break;
+ case 4: /* 0000 01 */
+ _jxr_wbitstream_uint4(str, 0);
+ _jxr_wbitstream_uint2(str, 1);
+ break;
+ case 5: /* 011 */
+ _jxr_wbitstream_uint1(str, 0);
+ _jxr_wbitstream_uint2(str, 3);
+ break;
+ case 6: /* 0000 1 */
+ _jxr_wbitstream_uint4(str, 0);
+ _jxr_wbitstream_uint1(str, 1);
+ break;
+ case 7: /* 0000 000 */
+ _jxr_wbitstream_uint4(str, 0);
+ _jxr_wbitstream_uint2(str, 0);
+ _jxr_wbitstream_uint1(str, 0);
+ break;
+ case 8: /* 0000 001 */
+ _jxr_wbitstream_uint4(str, 0);
+ _jxr_wbitstream_uint2(str, 0);
+ _jxr_wbitstream_uint1(str, 1);
+ break;
+ }
+ }
+
+ if (tmp >= 5) {
+ DEBUG(" MB_CBP: CHR_CBP=%x\n", chr_cbp);
+ assert(chr_cbp < 3);
+ switch (chr_cbp) {
+ case 0: /* 1 */
+ _jxr_wbitstream_uint1(str, 1);
+ break;
+ case 1: /* 01 */
+ _jxr_wbitstream_uint2(str, 1);
+ break;
+ case 2: /* 00 */
+ _jxr_wbitstream_uint2(str, 0);
+ break;
+ }
+ }
+
+ if (tmp == 8) {
+ int val_inc;
+ assert((val1 - tmp) <= 2);
+ val_inc = val1 - tmp;
+ DEBUG(" MB_CBP: VAL_INC=%d\n", val_inc);
+ switch (val_inc) {
+ case 0: /* 1 */
+ _jxr_wbitstream_uint1(str, 1);
+ break;
+ case 1: /* 01 */
+ _jxr_wbitstream_uint2(str, 1);
+ break;
+ case 2: /* 00 */
+ _jxr_wbitstream_uint2(str, 0);
+ break;
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+}
+
+void _jxr_w_MB_CBP(jxr_image_t image, struct wbitstream*str,
+ int alpha_flag,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my)
+{
+ int channels;
+ int diff_cbp[MAX_CHANNELS];
+ int ch;
+ int cbp;
+ int block;
+ DEBUG(" MB_CBP tile=[%u %u] mb=[%u %u] bitpos=%zu\n",
+ tx, ty, mx, my, _jxr_wbitstream_bitpos(str));
+
+ if (_jxr_InitContext(image, tx, ty, mx, my)) {
+ DEBUG(" MB_CBP: InitContext\n");
+ /* This happens only at the top left edge of the tile. */
+ _jxr_InitCBPVLC(image);
+ }
+
+ /* "Channels" is not quite the same as "planes". For the
+ purposes of CBP parsing, a color image has 1 channel. */
+ channels = 1;
+ if (image->use_clr_fmt==4/*YUVK*/ || image->use_clr_fmt==6/*NCOMPONENT*/)
+ channels = image->num_channels;
+
+ /* Get the diff_cbp values for all the channels. */
+ for (ch = 0 ; ch < image->num_channels ; ch += 1)
+ diff_cbp[ch] = MACROBLK_CUR(image,ch,tx,mx).hp_diff_cbp;
+
+ /* Now process the diff_cbp values for the channels. Note that
+ if this is a YUV image, then channels is 1 and the loop
+ knows to process three planes at once. */
+ for (ch = 0 ; ch < channels ; ch += 1) {
+
+ /* The CBP Block mask is a 4-bit mask that indicates
+ which bit-blocks of the 16bit diff_cbp has non-zero
+ bits in them. The cbp_X_block_masks are 4bit values
+ that indicate which nibbles of the 16bit diff_cbp
+ values have bits set. */
+ int cbp_Y_block_mask = 0;
+ int cbp_U_block_mask = 0;
+ int cbp_V_block_mask = 0;
+ if (diff_cbp[ch] & 0x000f)
+ cbp_Y_block_mask |= 0x001;
+ if (diff_cbp[ch] & 0x00f0)
+ cbp_Y_block_mask |= 0x002;
+ if (diff_cbp[ch] & 0x0f00)
+ cbp_Y_block_mask |= 0x004;
+ if (diff_cbp[ch] & 0xf000)
+ cbp_Y_block_mask |= 0x008;
+
+
+ switch (image->use_clr_fmt) {
+ /* If thie is a YUV420 image, then the block mask
+ includes masks for all the 3 planes. The UV
+ planes' have only 1 CBP bit per block, so this
+ is simple. */
+ case 1: /* YUV420 */
+ if (diff_cbp[1] & 0x01)
+ cbp_U_block_mask |= 0x01;
+ if (diff_cbp[1] & 0x02)
+ cbp_U_block_mask |= 0x02;
+ if (diff_cbp[1] & 0x04)
+ cbp_U_block_mask |= 0x04;
+ if (diff_cbp[1] & 0x08)
+ cbp_U_block_mask |= 0x08;
+ if (diff_cbp[2] & 0x01)
+ cbp_V_block_mask |= 0x01;
+ if (diff_cbp[2] & 0x02)
+ cbp_V_block_mask |= 0x02;
+ if (diff_cbp[2] & 0x04)
+ cbp_V_block_mask |= 0x04;
+ if (diff_cbp[2] & 0x08)
+ cbp_V_block_mask |= 0x08;
+ break;
+ /* If this is a YUV422 iamge, then the block mask
+ includes masks for all the 3 planes, with the
+ UV diff_cbp bits encoded funny. */
+ case 2: /* YUV422*/
+ if (diff_cbp[1] & 0x05)
+ cbp_U_block_mask |= 0x01;
+ if (diff_cbp[1] & 0x0a)
+ cbp_U_block_mask |= 0x02;
+ if (diff_cbp[1] & 0x50)
+ cbp_U_block_mask |= 0x04;
+ if (diff_cbp[1] & 0xa0)
+ cbp_U_block_mask |= 0x08;
+ if (diff_cbp[2] & 0x05)
+ cbp_V_block_mask |= 0x01;
+ if (diff_cbp[2] & 0x0a)
+ cbp_V_block_mask |= 0x02;
+ if (diff_cbp[2] & 0x50)
+ cbp_V_block_mask |= 0x04;
+ if (diff_cbp[2] & 0xa0)
+ cbp_V_block_mask |= 0x08;
+ break;
+ /* If this is a YUV444 image, then the block mask
+ includes masks for all 3 planes. */
+ case 3: /*YUV444*/
+ assert(ch == 0);
+ if (diff_cbp[1] & 0x000f)
+ cbp_U_block_mask |= 0x01;
+ if (diff_cbp[1] & 0x00f0)
+ cbp_U_block_mask |= 0x02;
+ if (diff_cbp[1] & 0x0f00)
+ cbp_U_block_mask |= 0x04;
+ if (diff_cbp[1] & 0xf000)
+ cbp_U_block_mask |= 0x08;
+ if (diff_cbp[2] & 0x000f)
+ cbp_V_block_mask |= 0x01;
+ if (diff_cbp[2] & 0x00f0)
+ cbp_V_block_mask |= 0x02;
+ if (diff_cbp[2] & 0x0f00)
+ cbp_V_block_mask |= 0x04;
+ if (diff_cbp[2] & 0xf000)
+ cbp_V_block_mask |= 0x08;
+ break;
+ default:
+ break;
+ }
+
+ DEBUG(" MB_CBP: diff_cbp[%d]=0x%x (HP_CBP=0x%x) cbp_block_mask=0x%x:%x:%x\n",
+ ch, diff_cbp[ch], MACROBLK_CUR_HPCBP(image,ch,tx,mx),
+ cbp_Y_block_mask, cbp_U_block_mask, cbp_V_block_mask);
+
+ /* A bit in the CBP (up to 4 bits) is true if the
+ corresponding bit of any of hte YUV planes' cbp is
+ set. That tells the decoder to look for CBP values
+ in any of the planes. */
+ cbp = cbp_Y_block_mask | cbp_U_block_mask | cbp_V_block_mask;
+ DEBUG(" MB_CBP: Refined CBP=0x%x\n", cbp);
+ w_REFINE_CBP(image, str, cbp);
+
+ for (block = 0 ; block < 4 ; block += 1) {
+ struct adaptive_vlc_s*vlc;
+ int blkcbp;
+ /* If there are no diff_cbp bits in this nibble of
+ any of the YUV planes, then skip. */
+ if ((cbp & (1<<block)) == 0)
+ continue;
+
+ vlc = image->vlc_table + DecNumBlkCBP;
+ assert(vlc->deltatable == 0);
+
+ DEBUG(" MB_CBP: block=%d Use DecNumBlkCBP table=%d, discriminant=%d, bitpos=%zu\n",
+ block, vlc->table, vlc->discriminant, _jxr_wbitstream_bitpos(str));
+
+ /* This is the block of CBP bits to encode. The
+ blkcbp is the nibble (indexed by "block") of
+ the diff_cbp for the Y plane, also also bits
+ set if the UV diff_cbp values have bits
+ set. The cbp_chr_X masks have the nibbles of
+ the UV diff_cbp. */
+ blkcbp = (diff_cbp[ch] >> 4*block) & 0x000f;
+
+ if (cbp_U_block_mask & (1<<block))
+ blkcbp |= 0x10;
+ if (cbp_V_block_mask & (1<<block))
+ blkcbp |= 0x20;
+
+ {
+ /* Map the CBP bit block to a more encodable
+ code. Note that this map doesn't look at the
+ chroma mask bits because this code is used to
+ generate only the low 4 bits by the receiver. */
+ static const int code_from_blkcbp[16] = {
+ 0, 4, 5, 2,
+ 6, 8, 9,12,
+ 7,10,11,13,
+ 3,14,15, 1 };
+ int code = code_from_blkcbp[blkcbp&0x0f];
+ /* Break the code down to a further encoded val
+ and refinement bit count. */
+ static const int val_from_code[16] = {
+ 0, 5, 2, 2,
+ 1, 1, 1, 1,
+ 3, 3, 3, 3,
+ 4, 4, 4, 4 };
+ int val = val_from_code[code];
+ int chr_cbp = (blkcbp >> 4) & 0x3;
+ int num_blkcbp;
+ if (chr_cbp > 0) {
+ chr_cbp -= 1;
+ val += 6;
+ }
+
+ assert(val > 0);
+ num_blkcbp = val-1;
+
+ DEBUG(" MB_CBP: NUM_BLKCBP=%d, iVal=%d, iCode=%d\n", num_blkcbp, val, code);
+ DEBUG(" MB_CBP: blkcbp=0x%x, code=%d for chunk blk=%d\n", blkcbp, code, block);
+
+ /* Adapt DecNumBlkCBP based on the num_blkcbp value. */
+ if (image->use_clr_fmt==0 || image->use_clr_fmt==4 || image->use_clr_fmt==6) {
+ static const int Num_BLKCBP_Delta5[5] = {0, -1, 0, 1, 1};
+ assert(num_blkcbp < 5);
+ vlc->discriminant += Num_BLKCBP_Delta5[num_blkcbp];
+ } else {
+ int tmp = val-1;
+ static const int Num_BLKCBP_Delta9[9] = {2, 2, 1, 1, -1, -2, -2, -2, -3};
+ if (tmp > 8) {
+ assert(tmp < 11);
+ tmp = 8;
+ }
+ assert(tmp < 9);
+ vlc->discriminant += Num_BLKCBP_Delta9[tmp];
+ }
+
+ DEBUG(" MB_CBP: NUM_BLKCBP=%d, discriminant becomes=%d, \n",
+ num_blkcbp, vlc->discriminant);
+
+ /* Encode VAL-1, and CHR_CBP if present. */
+ encode_val_1(image, str, vlc, val-1, chr_cbp);
+
+ {
+ /* Encode CODE_INC */
+ static const int code_inc_from_code[16] = {
+ 0, 0, 0, 1,
+ 0, 1, 2, 3,
+ 0, 1, 2, 3,
+ 0, 1, 2, 3 };
+ static const int code_inc_bits_from_code[16] = {
+ 0, 0, 1, 1,
+ 2, 2, 2, 2,
+ 2, 2, 2, 2,
+ 2, 2, 2, 2 };
+
+ int cbp_chr_U;
+ int cbp_chr_V;
+
+ assert(code < 16);
+
+ switch (code_inc_bits_from_code[code]) {
+ case 0:
+ break;
+ case 1:
+ _jxr_wbitstream_uint1(str, code_inc_from_code[code]);
+ break;
+ case 2:
+ _jxr_wbitstream_uint2(str, code_inc_from_code[code]);
+ break;
+ default:
+ assert(0);
+ }
+
+ cbp_chr_U = 0;
+ cbp_chr_V = 0;
+ switch (image->use_clr_fmt) {
+ case 0: /* YONLY */
+ case 4: /* YUVK */
+ case 6: /* NCOMPONENT */
+ break;
+ case 1:/* YUV420 */
+ /* Nothing to encode. The CHR_CBP bits are
+ sufficient to carry all the UV CBP
+ informtation for YUV420 UV planes. */
+ break;
+ case 2: /* YUV422 */
+ if (blkcbp & 0x10)
+ refine_cbp_chr422(image, str, diff_cbp[1], block);
+ if (blkcbp & 0x20)
+ refine_cbp_chr422(image, str, diff_cbp[2], block);
+ break;
+ case 3: /* YUV444 */
+ cbp_chr_U = (diff_cbp[1] >> 4*block) & 0x000f;
+ cbp_chr_V = (diff_cbp[2] >> 4*block) & 0x000f;
+ if (blkcbp & 0x10) {
+ DEBUG(" MB_CBP: Refined CBP_U=0x%x\n", cbp_chr_U);
+ w_REFINE_CBP_CHR(image, str, cbp_chr_U);
+ }
+ if (blkcbp & 0x20) {
+ DEBUG(" MB_CBP: Refined CBP_V=0x%x\n", cbp_chr_V);
+ w_REFINE_CBP_CHR(image, str, cbp_chr_V);
+ }
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ DEBUG(" MB_CBP done tile=[%u %u] mb=[%u %u]\n", tx, ty, mx, my);
+}
+
+static void refine_cbp_chr422(jxr_image_t image, struct wbitstream*str, int diff_cbp, int block)
+{
+ static const int shift_mask[4] = {0, 1, 4, 5};
+ int bits = diff_cbp >> shift_mask[block];
+ switch (bits & 5) {
+ case 0:
+ assert(0);
+ break;
+ case 1: /* 1 */
+ _jxr_wbitstream_uint1(str, 1);
+ break;
+ case 4: /* 01 */
+ _jxr_wbitstream_uint2(str, 1);
+ break;
+ case 5: /* 00 */
+ _jxr_wbitstream_uint2(str, 0);
+ break;
+ }
+}
+
+static void refine_cbp_core(jxr_image_t image, struct wbitstream*str, int cbp_mask)
+{
+ switch (cbp_mask) {
+ case 0x0:
+ /* If there are no CBP bits, then encode nothing. */
+ case 0xf:
+ break;
+ /* REF_CBP (num_cbp==1) */
+ case 0x1:
+ _jxr_wbitstream_uint2(str, 0);
+ break;
+ case 0x2:
+ _jxr_wbitstream_uint2(str, 1);
+ break;
+ case 0x4:
+ _jxr_wbitstream_uint2(str, 2);
+ break;
+ case 0x8:
+ _jxr_wbitstream_uint2(str, 3);
+ break;
+ /* REF_CBP1 (num_cbp==2) */
+ case 0x3:
+ _jxr_wbitstream_uint2(str, 0);
+ break;
+ case 0x5:
+ _jxr_wbitstream_uint2(str, 1);
+ break;
+ case 0x6:
+ _jxr_wbitstream_uint1(str, 1);
+ _jxr_wbitstream_uint2(str, 0);
+ break;
+ case 0x9:
+ _jxr_wbitstream_uint1(str, 1);
+ _jxr_wbitstream_uint2(str, 1);
+ break;
+ case 0xa:
+ _jxr_wbitstream_uint1(str, 1);
+ _jxr_wbitstream_uint2(str, 2);
+ break;
+ case 0xc:
+ _jxr_wbitstream_uint1(str, 1);
+ _jxr_wbitstream_uint2(str, 3);
+ break;
+ /* REF_CBP (num_cbp==3) */
+ case 0xe:
+ _jxr_wbitstream_uint2(str, 0);
+ break;
+ case 0xd:
+ _jxr_wbitstream_uint2(str, 1);
+ break;
+ case 0xb:
+ _jxr_wbitstream_uint2(str, 2);
+ break;
+ case 0x7:
+ _jxr_wbitstream_uint2(str, 3);
+ break;
+ }
+}
+
+static void w_REFINE_CBP(jxr_image_t image, struct wbitstream*str, int cbp_block_mask)
+{
+ int num_cbp = 0;
+ int idx;
+ static const int Num_CBP_Delta[5] = {0, -1, 0, 1, 1};
+ struct adaptive_vlc_s*vlc;
+ int vlc_table;
+
+ DEBUG(" REFINE_CBP: input CBP=%d (0x%x)\n", cbp_block_mask, cbp_block_mask);
+
+ for (idx = 0 ; idx < 4 ; idx += 1) {
+ if (cbp_block_mask & (1<<idx))
+ num_cbp += 1;
+ }
+
+ vlc = image->vlc_table + DecNumCBP;
+
+ assert(vlc->deltatable == 0 && num_cbp < 5);
+ vlc->discriminant += Num_CBP_Delta[num_cbp];
+
+
+ /* First encode the NUM_CBP. (The REFINE_CBP in the spec does
+ not include this step, but we include it here because it is
+ part of the cbp_block_mask encoding.) */
+ vlc_table = vlc->table;
+ assert(vlc_table < 2);
+
+ DEBUG(" REFINE_CBP: num_cbp=%d, vlc table=%d\n", num_cbp, vlc_table);
+
+ if (vlc_table == 0) {
+ switch (num_cbp) {
+ case 4:
+ _jxr_wbitstream_uint1(str, 0);
+ case 2:
+ _jxr_wbitstream_uint1(str, 0);
+ case 1:
+ _jxr_wbitstream_uint1(str, 0);
+ case 0:
+ _jxr_wbitstream_uint1(str, 1);
+ break;
+ case 3:
+ _jxr_wbitstream_uint1(str, 0);
+ _jxr_wbitstream_uint1(str, 0);
+ _jxr_wbitstream_uint1(str, 0);
+ _jxr_wbitstream_uint1(str, 0);
+ break;
+ }
+ }
+ else {
+ switch (num_cbp) {
+ case 0:
+ _jxr_wbitstream_uint1(str, 1);
+ break;
+ default:
+ _jxr_wbitstream_uint1(str, 0);
+ _jxr_wbitstream_uint2(str, num_cbp-1);
+ break;
+ }
+ }
+
+ /* Now encode the CBP itself. Note that many encodings look
+ the same. The decoder uses the NUM_CBP encoded above to
+ distinguish between the different possible values. */
+ refine_cbp_core(image, str, cbp_block_mask);
+}
+
+static void w_REFINE_CBP_CHR(jxr_image_t image, struct wbitstream*str, int cbp_block_mask)
+{
+ int num_cbp = 0;
+ int idx;
+
+ DEBUG(" REFINE_CBP: input CBP(CHR)= 0x%x)\n", cbp_block_mask);
+
+ for (idx = 0 ; idx < 4 ; idx += 1) {
+ if (cbp_block_mask & (1<<idx))
+ num_cbp += 1;
+ }
+
+ /* If refining a CBP block mask for a chroma plane, then we
+ know that there must be at least one block bit set, so we
+ can encode num_cbp-1 instead, and possibly save space. */
+ assert(num_cbp > 0);
+ num_cbp -= 1;
+
+ /* First encode the NUM_CBP. (The REFINE_CBP in the spec does
+ not include this step, but we include it here because it is
+ part of the cbp_block_mask encoding.) */
+ DEBUG(" REFINE_CBP(CHR): num_ch_blk=%d\n", num_cbp);
+
+ assert(num_cbp < 4);
+ switch (num_cbp) {
+ case 0: /* 1 */
+ _jxr_wbitstream_uint1(str,1);
+ break;
+ case 1: /* 01 */
+ _jxr_wbitstream_uint2(str, 1);
+ break;
+ case 2: /* 000 */
+ _jxr_wbitstream_uint2(str, 0);
+ _jxr_wbitstream_uint1(str, 0);
+ break;
+ case 3: /* 001 */
+ _jxr_wbitstream_uint2(str, 0);
+ _jxr_wbitstream_uint1(str, 1);
+ break;
+ }
+
+ /* Now encode the CBP itself. Note that many encodings look
+ the same. The decoder uses the NUM_CBP encoded above to
+ distinguish between the different possible values. */
+ refine_cbp_core(image, str, cbp_block_mask);
+}
+
+
+int _jxr_w_MB_HP(jxr_image_t image, struct wbitstream*str,
+ int alpha_flag,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my,
+ struct wbitstream*strFB)
+{
+ int flex_flag;
+ int mbhp_pred_mode;
+ int idx;
+
+ /* This function can act either as MB_HP() or MB_HP_FLEX() */
+ DEBUG(" MB_HP tile=[%u %u] mb=[%u %u] bitpos=%zu\n",
+ tx, ty, mx, my, _jxr_wbitstream_bitpos(str));
+
+ if (_jxr_InitContext(image, tx, ty, mx, my)) {
+ DEBUG(" MB_HP: InitContext\n");
+ /* This happens only at the top left edge of the tile. */
+ _jxr_InitHPVLC(image);
+ _jxr_InitializeAdaptiveScanHP(image);
+ }
+
+ if (_jxr_ResetTotals(image, mx)) {
+ _jxr_ResetTotalsAdaptiveScanHP(image);
+ }
+
+ /* FLEXBITS are embedded in the HP data if there are FLEXBITS
+ present in the bitstream AND we are in SPATIAL (not
+ FREQUENCY) mode. */
+ flex_flag = 1;
+ if (image->bands_present == 1) /* NOFLEXBITS */
+ flex_flag = 0;
+ if (FREQUENCY_MODE_CODESTREAM_FLAG(image) != 0) /* FREQUENCY_MODE */
+ flex_flag = 0;
+
+ mbhp_pred_mode = MACROBLK_CUR(image,0,tx,mx).mbhp_pred_mode;
+
+ for (idx = 0 ; idx < image->num_channels; idx += 1) {
+ int chroma_flag = idx>0? 1 : 0;
+ int nblocks = 4;
+ unsigned model_bits;
+ int cbp;
+ int block;
+ if (chroma_flag && image->use_clr_fmt==1/*YUV420*/)
+ nblocks = 1;
+ else if (chroma_flag && image->use_clr_fmt==2/*YUV422*/)
+ nblocks = 2;
+
+ model_bits = MACROBLK_CUR(image,0,tx,mx).hp_model_bits[chroma_flag];
+ cbp = MACROBLK_CUR_HPCBP(image, idx, tx, mx);
+
+ DEBUG(" MB_HP channel=%d, cbp=0x%x, model_bits=%u MBHPMode=%d\n",
+ idx, cbp, model_bits, mbhp_pred_mode);
+ for (block=0 ; block<(nblocks*4) ; block += 1, cbp >>= 1) {
+ int bpos = block;
+ int num_nonzero;
+ /* Only remap the Y plane of YUV42X data. */
+ if (nblocks == 4)
+ bpos = _jxr_hp_scan_map[block];
+ num_nonzero = w_DECODE_BLOCK_ADAPTIVE(image, str, tx, mx,
+ cbp&1, chroma_flag,
+ idx, bpos, mbhp_pred_mode,
+ model_bits);
+ if (num_nonzero < 0) {
+ DEBUG("ERROR: r_DECODE_BLOCK_ADAPTIVE returned rc=%d\n", num_nonzero);
+ return JXR_EC_ERROR;
+ }
+ if (strFB)
+ w_BLOCK_FLEXBITS(image, strFB, tx, ty, mx, my,
+ idx, bpos, model_bits);
+ else if (flex_flag)
+ w_BLOCK_FLEXBITS(image, str, tx, ty, mx, my,
+ idx, bpos, model_bits);
+ }
+
+ }
+
+ if (_jxr_ResetContext(image, tx, mx)) {
+ DEBUG(" MB_HP: Run AdaptHP\n");
+ _jxr_AdaptHP(image);
+ }
+
+ DEBUG(" MB_HP DONE tile=[%u %u] mb=[%u %u]\n", tx, ty, mx, my);
+ return 0;
+}
+
+static void w_DECODE_FLEX(jxr_image_t image, struct wbitstream*str,
+ unsigned tx, unsigned mx,
+ int ch, unsigned block, unsigned k,
+ unsigned flexbits)
+{
+ int coeff = MACROBLK_CUR_HP(image, ch, tx, mx, block, k);
+ int sign = 0;
+ int mask;
+ int flex_ref;
+
+ if (coeff < 0) {
+ sign = 1;
+ coeff = -coeff;
+ }
+
+ coeff >>= image->trim_flexbits;
+ mask = (1 << flexbits) - 1;
+
+ flex_ref = coeff & mask;
+ coeff &= ~mask;
+ DEBUG(" DECODE_FLEX: coeff=0x%08x, flex_ref=0x%08x\n", coeff, flex_ref);
+
+ _jxr_wbitstream_uintN(str, flex_ref, flexbits);
+
+ if (coeff == 0 && flex_ref != 0)
+ _jxr_wbitstream_uint1(str, sign);
+}
+
+static void w_BLOCK_FLEXBITS(jxr_image_t image, struct wbitstream*str,
+ unsigned tx, unsigned ty,
+ unsigned mx, unsigned my,
+ unsigned ch, unsigned bl, unsigned model_bits)
+{
+ const int transpose444 [16] = {0, 4, 8,12,
+ 1, 5, 9,13,
+ 2, 6,10,14,
+ 3, 7,11,15 };
+ unsigned flexbits_left = model_bits;
+ if (image->trim_flexbits > flexbits_left)
+ flexbits_left = 0;
+ else
+ flexbits_left -= image->trim_flexbits;
+
+ DEBUG(" BLOCK_FLEXBITS: flexbits_left=%u (model=%u, trim=%u) block=%u bitpos=%zu\n",
+ flexbits_left, model_bits, image->trim_flexbits, bl, _jxr_wbitstream_bitpos(str));
+
+ if (flexbits_left > 0) {
+ int idx;
+ for (idx = 1 ; idx < 16 ; idx += 1) {
+ int idx_trans = transpose444[idx];
+ w_DECODE_FLEX(image, str, tx, mx, ch, bl, idx_trans-1, flexbits_left);
+ }
+ }
+
+ DEBUG(" BLOCK_FLEXBITS done\n");
+}
+
+static void w_DEC_DC(jxr_image_t image, struct wbitstream*str,
+ int model_bits, int chroma_flag, int is_dc_ch,
+ int32_t dc_val)
+{
+ int idx;
+ int sign_flag = 0;
+ int zero_flag = dc_val==0;
+ uint32_t dc_ref_stack;
+
+ DEBUG(" DEC_DC: DC value is %d (0x%08x)\n", dc_val, dc_val);
+
+ /* Values are encoded as magnitude/sign, and *not* the 2s
+ complement value. So here we get the sign of the value and
+ convert it to a magnitude for encoding. */
+ if (dc_val < 0) {
+ sign_flag = 1;
+ dc_val = -dc_val;
+ }
+
+ /* Pull the LSB bits from the value and save them in a stack
+ of DC_REF values. This reduces the number of bits in the dc
+ val that will be encoded. */
+ dc_ref_stack = 0;
+ for (idx = 0 ; idx < model_bits ; idx += 1) {
+ dc_ref_stack <<= 1;
+ dc_ref_stack |= dc_val&1;
+ dc_val >>= 1;
+ }
+
+ /* The is_dc_ch flag only gates the encoding of the high bits
+ of the absolute level. If the level is non-zero, then
+ presumably the is_dc_ch flag is true and we go ahead and
+ encode the level. The model_bits are encoded in any case. */
+ if (dc_val != 0) {
+ assert( is_dc_ch );
+ DEBUG(" DEC_DC: DECODE_ABS_LEVEL = %d (0x%08x)\n", dc_val, dc_val);
+ w_DECODE_ABS_LEVEL(image, str, 0/*DC*/, chroma_flag, dc_val + 1);
+ }
+
+ /* Play back the bits in the dc_ref stack. This causes them to
+ appear MSB first in the DC_REF field. These are the
+ model_bits, the LSB of the level. */
+ for (idx = 0 ; idx < model_bits ; idx += 1) {
+ _jxr_wbitstream_uint1(str, dc_ref_stack&1);
+ dc_ref_stack >>= 1;
+ }
+
+ /* The sign bit is last. Include it only if the value is nonzero*/
+ if (!zero_flag) {
+ DEBUG(" DEC_DC: sign_flag=%s\n", sign_flag? "true":"false");
+ _jxr_wbitstream_uint1(str, sign_flag);
+ }
+}
+
+static void encode_abslevel_index(jxr_image_t image, struct wbitstream*str,
+ int abslevel_index, int vlc_select);
+
+/*
+* This function actually *ENCODES* the ABS_LEVEL.
+*/
+static void w_DECODE_ABS_LEVEL(jxr_image_t image, struct wbitstream*str,
+ int band, int chroma_flag, uint32_t level)
+{
+ int vlc_select = _jxr_vlc_select(band, chroma_flag);
+ const uint32_t abslevel_limit[6] = { 2, 3, 5, 9, 13, 17 };
+ const uint32_t abslevel_remap[6] = {2, 3, 4, 6, 10, 14};
+ const int abslevel_fixedlen[6] = {0, 0, 1, 2, 2, 2};
+ int abslevel_index;
+
+ DEBUG(" Use vlc_select = %s (table=%d) to encode level index, bitpos=%zu\n",
+ _jxr_vlc_index_name(vlc_select), image->vlc_table[vlc_select].table,
+ _jxr_wbitstream_bitpos(str));
+
+ /* choose the smallest level index that can carry "level". the
+ abslevel_limit array holds the maximim value that each
+ index can encode. */
+ abslevel_index = 0;
+ while (abslevel_index < 6 && abslevel_limit[abslevel_index] < level) {
+ abslevel_index += 1;
+ }
+
+ DEBUG(" ABSLEVEL_INDEX = %d\n", abslevel_index);
+ encode_abslevel_index(image, str, abslevel_index, vlc_select);
+
+ image->vlc_table[vlc_select].discriminant += _jxr_abslevel_index_delta[abslevel_index];
+
+ if (abslevel_index < 6) {
+ /* The level index encodes most of the level value. The
+ abslevel_remap is the actual value that the index
+ encodes. The fixedlen array then gives the number of
+ extra bits available to encode the last bit of
+ value. This *must* be enough. */
+
+ int idx;
+ int fixedlen = abslevel_fixedlen[abslevel_index];
+ uint32_t level_ref = level - abslevel_remap[abslevel_index];
+ uint32_t level_ref_stack = 0;
+
+ DEBUG(" ABS_LEVEL = 0x%x (fixed = %d, level_ref = %d)\n",
+ level, fixedlen, level_ref);
+
+ /* Stack the residual bits... */
+ for (idx = 0 ; idx < fixedlen ; idx += 1) {
+ level_ref_stack <<= 1;
+ level_ref_stack |= level_ref & 1;
+ level_ref >>= 1;
+ }
+
+ assert(level_ref == 0);
+
+ /* Emit the residual bits in MSB order. */
+ for (idx = 0 ; idx < fixedlen ; idx += 1) {
+ _jxr_wbitstream_uint1(str, level_ref_stack&1);
+ level_ref_stack >>= 1;
+ }
+
+ } else {
+ uint32_t level_ref = level - 2;
+ unsigned fixed = 0;
+ unsigned fixed_tmp;
+ assert(level_ref > 1);
+ while (level_ref > 1) {
+ level_ref >>= 1;
+ fixed += 1;
+ }
+
+ assert(level >= ((1U<<fixed) + 2));
+ level_ref = level - (1<<fixed) - 2;
+ DEBUG(" ABS_LEVEL = 0x%x (fixed = %d, level_ref = %u\n", level, fixed, level_ref);
+
+ fixed_tmp = fixed - 4;
+ if (fixed_tmp < 15) {
+ _jxr_wbitstream_uint4(str, fixed_tmp);
+
+ } else {
+ _jxr_wbitstream_uint4(str, 0xf);
+ fixed_tmp -= 15;
+ if (fixed_tmp < 3) {
+ _jxr_wbitstream_uint2(str, fixed_tmp);
+ } else {
+ _jxr_wbitstream_uint2(str, 0x3);
+ fixed_tmp -= 3;
+ assert(fixed_tmp < 8);
+ _jxr_wbitstream_uint3(str, fixed_tmp);
+ }
+ }
+ _jxr_wbitstream_uintN(str, level_ref, fixed);
+ }
+}
+
+static void encode_abslevel_index(jxr_image_t image, struct wbitstream*str,
+ int abslevel_index, int vlc_select)
+{
+ int table = image->vlc_table[vlc_select].table;
+ assert(table==0 || table==1);
+
+ if (table==0) {
+ switch (abslevel_index) {
+ case 0:
+ _jxr_wbitstream_uint2(str, 0x1);
+ break;
+ case 1:
+ _jxr_wbitstream_uint2(str, 0x2);
+ break;
+ case 2:
+ _jxr_wbitstream_uint2(str, 0x3);
+ break;
+ case 3:
+ _jxr_wbitstream_uint2(str, 0x0);
+ _jxr_wbitstream_uint1(str, 0x1);
+ break;
+ case 4:
+ _jxr_wbitstream_uint4(str, 0x1);
+ break;
+ case 5:
+ _jxr_wbitstream_uint4(str, 0x0);
+ _jxr_wbitstream_uint1(str, 0x0);
+ break;
+ case 6:
+ _jxr_wbitstream_uint4(str, 0x0);
+ _jxr_wbitstream_uint1(str, 0x1);
+ break;
+ }
+ }
+ else {
+ switch (abslevel_index) {
+ case 0:
+ _jxr_wbitstream_uint1(str, 0x1);
+ break;
+ case 1:
+ _jxr_wbitstream_uint2(str, 0x1);
+ break;
+ case 2:
+ _jxr_wbitstream_uint2(str, 0x0);
+ _jxr_wbitstream_uint1(str, 0x1);
+ break;
+ case 3:
+ _jxr_wbitstream_uint4(str, 0x1);
+ break;
+ case 4:
+ _jxr_wbitstream_uint4(str, 0x0);
+ _jxr_wbitstream_uint1(str, 0x1);
+ break;
+ case 5:
+ _jxr_wbitstream_uint4(str, 0x0);
+ _jxr_wbitstream_uint2(str, 0x0);
+ break;
+ case 6:
+ _jxr_wbitstream_uint4(str, 0x0);
+ _jxr_wbitstream_uint2(str, 0x1);
+ break;
+ }
+ }
+}
+
+static void w_DECODE_BLOCK(jxr_image_t image, struct wbitstream*str, int band, int chroma_flag,
+ const int RLCoeffs[32], int num_non_zero)
+{
+ int location = 1;
+ int index_code = 0;
+ int sign_flag = 0;
+ int value = RLCoeffs[1];
+ int context;
+ int nz_index;
+
+ /* if CLR_FMT is YUV420 or YUV422 */
+ if (image->use_clr_fmt==1/*YUV420*/ && chroma_flag && band==1)
+ location = 10;
+ if (image->use_clr_fmt==2/*YUV422*/ && chroma_flag && band==1)
+ location = 2;
+
+ if (value < 0) {
+ sign_flag = 1;
+ value = -value;
+ }
+
+ /* FIRST_INDEX */
+ if (RLCoeffs[0] == 0)
+ index_code |= 1;
+ if (value != 1)
+ index_code |= 2;
+
+ if (num_non_zero == 1)
+ index_code |= 0<<2;
+ else if (RLCoeffs[2] == 0)
+ index_code |= 1<<2;
+ else
+ index_code |= 2<<2;
+
+ DEBUG(" DECODE_BLOCK: chroma_flag=%d, band=%d value=%s%d num_non_zero=%d index_code=0x%x bitpos=%zu\n",
+ chroma_flag, band, sign_flag?"-":"+", value, num_non_zero, index_code, _jxr_wbitstream_bitpos(str));
+
+ DEBUG(" coeff[0] = %d (run)\n", RLCoeffs[0]);
+ DEBUG(" coeff[1] = 0x%x\n", RLCoeffs[1]);
+ DEBUG(" coeff[1*2+0] = %d (run)\n", RLCoeffs[2]);
+
+ context = (index_code&1) & (index_code>>2);
+
+ /* Encode FIRST_INDEX */
+ w_DECODE_FIRST_INDEX(image, str, chroma_flag, band, index_code);
+ /* SIGN_FLAG */
+ _jxr_wbitstream_uint1(str, sign_flag);
+ if (index_code&2) {
+ DEBUG(" DECODE_BLOCK: DECODE_ABS_LEVEL = %d (0x%08x)\n", value, value);
+ w_DECODE_ABS_LEVEL(image, str, band, context, value);
+ }
+ if ((index_code&1) == 0) {
+ w_DECODE_RUN(image, str, 15-location, RLCoeffs[0]);
+ }
+ location += 1 + RLCoeffs[0];
+
+ nz_index = 1;
+ while (nz_index < num_non_zero) {
+ /* If the previous index didn't already flag this as a
+ zero run, then encode the run now. */
+ if (RLCoeffs[2*nz_index+0] > 0)
+ w_DECODE_RUN(image, str, 15-location, RLCoeffs[2*nz_index+0]);
+
+ location += 1 + RLCoeffs[2*nz_index+0];
+
+ value = RLCoeffs[2*nz_index+1];
+ sign_flag = 0;
+ if (value < 0) {
+ sign_flag = 1;
+ value = -value;
+ }
+
+ /* index_code */
+ index_code = 0;
+ if (value != 1)
+ index_code |= 1;
+ if (nz_index+1 == num_non_zero)
+ index_code |= 0<<1;
+ else if (RLCoeffs[2*nz_index+2] == 0)
+ index_code |= 1<<1;
+ else
+ index_code |= 2<<1;
+
+ DEBUG(" DECODE_BLOCK: nz_index=%u, index_code=%x\n", nz_index, index_code);
+ w_DECODE_INDEX(image, str, location, chroma_flag, band, context, index_code);
+ context &= index_code >> 1;
+
+ _jxr_wbitstream_uint1(str, sign_flag);
+ if (value != 1) {
+ w_DECODE_ABS_LEVEL(image, str, band, context, value);
+ }
+
+ nz_index += 1;
+ }
+}
+
+static void w_DECODE_FIRST_INDEX(jxr_image_t image, struct wbitstream*str,
+ int chroma_flag, int band, int first_index)
+{
+ struct encode_table_s{
+ unsigned char bits;
+ unsigned char len;
+ };
+
+ typedef struct encode_table_s first_index_table_t[12];
+ static const first_index_table_t first_index_vlc[5] = {
+ { /* VLC0 */
+ { 0x08, 5 }, /* 0 == 0000 1... */
+ { 0x04, 6 }, /* 1 == 0000 01.. */
+ { 0x00, 7 }, /* 2 == 0000 000. */
+ { 0x02, 7 }, /* 3 == 0000 001. */
+ { 0x20, 5 }, /* 4 == 0010 0... */
+ { 0x40, 3 }, /* 5 == 010. .... */
+ { 0x28, 5 }, /* 6 == 0010 1... */
+ { 0x80, 1 }, /* 7 == 1... .... */
+ { 0x30, 5 }, /* 8 == 0011 0... */
+ { 0x10, 4 }, /* 9 == 0001 .... */
+ { 0x38, 5 }, /* 10 == 0011 1... */
+ { 0x60, 3 } /* 11 == 011. .... */
+ },
+ { /* VLC1 */
+ { 0x20, 4 }, /* 0 == 0010 .... */
+ { 0x10, 5 }, /* 1 == 0001 0... */
+ { 0x00, 6 }, /* 2 == 0000 00.. */
+ { 0x04, 6 }, /* 3 == 0000 01.. */
+ { 0x30, 4 }, /* 4 == 0011 .... */
+ { 0x40, 3 }, /* 5 == 010. .... */
+ { 0x18, 5 }, /* 6 == 0001 1... */
+ { 0xc0, 2 }, /* 7 == 11.. .... */
+ { 0x60, 3 }, /* 8 == 011. .... */
+ { 0x80, 3 }, /* 9 == 100. .... */
+ { 0x08, 5 }, /* 10 == 0000 1... */
+ { 0xa0, 3 } /* 11 == 101. .... */
+ },
+ { /* VLC2 */
+ { 0xc0, 2 }, /* 0 == 11.. .... */
+ { 0x20, 3 }, /* 1 == 001. .... */
+ { 0x00, 7 }, /* 2 == 0000 000. */
+ { 0x02, 7 }, /* 3 == 0000 001. */
+ { 0x08, 5 }, /* 4 == 0000 1... */
+ { 0x40, 3 }, /* 5 == 010. .... */
+ { 0x04, 7 }, /* 6 == 0000 010. */
+ { 0x60, 3 }, /* 7 == 011. .... */
+ { 0x80, 3 }, /* 8 == 100. .... */
+ { 0xa0, 3 }, /* 9 == 101. .... */
+ { 0x06, 7 }, /* 10 == 0000 011. */
+ { 0x10, 4 }, /* 11 == 0001 .... */
+ },
+ { /* VLC3 */
+ { 0x20, 3 }, /* 0 == 001. .... */
+ { 0xc0, 2 }, /* 1 == 11.. .... */
+ { 0x00, 7 }, /* 2 == 0000 000. */
+ { 0x08, 5 }, /* 3 == 0000 1... */
+ { 0x10, 5 }, /* 4 == 0001 0... */
+ { 0x40, 3 }, /* 5 == 010. .... */
+ { 0x02, 7 }, /* 6 == 0000 001. */
+ { 0x60, 3 }, /* 7 == 011. .... */
+ { 0x18, 5 }, /* 8 == 0001 1... */
+ { 0x80, 3 }, /* 9 == 100. .... */
+ { 0x04, 6 }, /* 10 == 0000 01.. */
+ { 0xa0, 3 } /* 11 == 101. .... */
+ },
+ { /* VLC4 */
+ { 0x40, 3 }, /* 0 == 010. .... */
+ { 0x80, 1 }, /* 1 == 1... .... */
+ { 0x02, 7 }, /* 2 == 0000 001. */
+ { 0x10, 4 }, /* 3 == 0001 .... */
+ { 0x04, 7 }, /* 4 == 0000 010. */
+ { 0x60, 3 }, /* 5 == 011. .... */
+ { 0x00, 8 }, /* 6 == 0000 0000 */
+ { 0x20, 4 }, /* 7 == 0010 .... */
+ { 0x06, 7 }, /* 8 == 0000 011. */
+ { 0x30, 4 }, /* 9 == 0011 .... */
+ { 0x01, 8 }, /* 10 == 0000 0001 */
+ { 0x08, 5 } /* 11 == 0000 1... */
+ }
+ };
+ int vlc_table;
+ unsigned char bits;
+ unsigned char len;
+
+ int delta_table;
+ int delta2table;
+
+ typedef int deltatable_t[12];
+ const deltatable_t FirstIndexDelta[4] = {
+ { 1, 1, 1, 1, 1, 0, 0,-1, 2, 1, 0, 0 },
+ { 2, 2,-1,-1,-1, 0,-2,-1, 0, 0,-2,-1 },
+ {-1, 1, 0, 2, 0, 0, 0, 0,-2, 0, 1, 1 },
+ { 0, 1, 0, 1,-2, 0,-1,-1,-2,-1,-2,-2 }
+ };
+
+ abs_level_vlc_index_t vlc_select = (abs_level_vlc_index_t)0;
+
+ switch (band) {
+ case 1: /* LP */
+ if (chroma_flag)
+ vlc_select = DecFirstIndLPChr;
+ else
+ vlc_select = DecFirstIndLPLum;
+ break;
+ case 2: /* HP */
+ if (chroma_flag)
+ vlc_select = DecFirstIndHPChr;
+ else
+ vlc_select = DecFirstIndHPLum;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ vlc_table = image->vlc_table[vlc_select].table;
+ DEBUG(" DECODE_FIRST_INDEX: vlc_select = %s, vlc_table = %d, encode 0x%x\n",
+ _jxr_vlc_index_name(vlc_select), vlc_table, first_index);
+
+ bits = first_index_vlc[vlc_table][first_index].bits;
+ len = first_index_vlc[vlc_table][first_index].len;
+
+ DEBUG(" bits/len = 0x%02x/%u\n", bits, len);
+
+ while (len > 0) {
+ _jxr_wbitstream_uint1(str, (bits&0x80)? 1 : 0);
+ bits <<= 1;
+ len -= 1;
+ }
+
+ delta_table = image->vlc_table[vlc_select].deltatable;
+ delta2table = image->vlc_table[vlc_select].delta2table;
+
+ assert(delta_table < 4);
+ assert(delta2table < 4);
+ assert(first_index < 12);
+ image->vlc_table[vlc_select].discriminant += FirstIndexDelta[delta_table][first_index];
+ image->vlc_table[vlc_select].discriminant2 += FirstIndexDelta[delta2table][first_index];
+}
+
+static void w_DECODE_INDEX(jxr_image_t image, struct wbitstream*str,
+ int location, int chroma_flag, int band, int context,
+ int index_code)
+{
+ int vlc_select = 0;
+ int vlc_table;
+ struct encode_table_s{
+ unsigned char bits;
+ unsigned char len;
+ };
+
+ typedef struct encode_table_s index1_table_t[6];
+ static const index1_table_t index1_vlc[5] = {
+ { /* VLC0 */
+ { 0x80, 1 }, /* 0 == 1... .... */
+ { 0x00, 5 }, /* 1 == 0000 0... */
+ { 0x20, 3 }, /* 2 == 001. .... */
+ { 0x08, 5 }, /* 3 == 0000 1... */
+ { 0x40, 2 }, /* 4 == 01.. .... */
+ { 0x10, 4 } /* 5 == 0001 .... */
+ },
+ { /* VLC1 */
+ { 0x40, 2 }, /* 0 == 01.. .... */
+ { 0x00, 4 }, /* 1 == 0000 .... */
+ { 0x80, 2 }, /* 2 == 10.. .... */
+ { 0x10, 4 }, /* 3 == 0001 .... */
+ { 0xc0, 2 }, /* 4 == 11.. .... */
+ { 0x20, 3 } /* 5 == 001. .... */
+ },
+ { /* VLC2 */
+ { 0x00, 4 }, /* 0 == 0000 .... */
+ { 0x10, 4 }, /* 1 == 0001 .... */
+ { 0x40, 2 }, /* 2 == 01.. .... */
+ { 0x80, 2 }, /* 3 == 10.. .... */
+ { 0xc0, 2 }, /* 4 == 11.. .... */
+ { 0x20, 3 } /* 5 == 001. .... */
+ },
+ { /* VLC3 */
+ { 0x00, 5 }, /* 0 == 0000 0... */
+ { 0x08, 5 }, /* 1 == 0000 1... */
+ { 0x40, 2 }, /* 2 == 01.. .... */
+ { 0x80, 1 }, /* 3 == 1... .... */
+ { 0x10, 4 }, /* 4 == 0001 .... */
+ { 0x20, 3 } /* 5 == 001. .... */
+ }
+ };
+ unsigned char bits;
+ unsigned char len;
+ int vlc_delta;
+ int vlc_delta2;
+
+ typedef int deltatable_t[6];
+ const deltatable_t Index1Delta[3] = {
+ {-1, 1, 1, 1, 0, 1 },
+ {-2, 0, 0, 2, 0, 0 },
+ {-1,-1, 0, 1,-2, 0 }
+ };
+
+
+ switch (band) {
+ case 1: /* LP */
+ if (chroma_flag)
+ vlc_select = context? DecIndLPChr1 : DecIndLPChr0;
+ else
+ vlc_select = context? DecIndLPLum1 : DecIndLPLum0;
+ break;
+ case 2: /* HP */
+ if (chroma_flag)
+ vlc_select = context? DecIndHPChr1 : DecIndHPChr0;
+ else
+ vlc_select = context? DecIndHPLum1 : DecIndHPLum0;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ /* If location>15, then there can't possibly be coefficients
+ after the next, so only the low bit need be encoded. */
+ if (location > 15) {
+ DEBUG(" DECODE_INDEX: location=%d, index_code=%d\n", location, index_code);
+ assert(index_code <= 1);
+ _jxr_wbitstream_uint1(str, index_code);
+ return;
+ }
+
+ if (location == 15) {
+ DEBUG(" DECODE_INDEX: location=%d, index_code=%d\n", location, index_code);
+ /* Table 61
+ * INDEX2 table
+ * 0 0
+ * 2 10
+ * 1 110
+ * 3 111
+ */
+ switch (index_code) {
+ case 0:
+ _jxr_wbitstream_uint1(str, 0);
+ break;
+ case 2:
+ _jxr_wbitstream_uint2(str, 2);
+ break;
+ case 1:
+ _jxr_wbitstream_uint1(str, 1);
+ _jxr_wbitstream_uint2(str, 2);
+ break;
+ case 3:
+ _jxr_wbitstream_uint1(str, 1);
+ _jxr_wbitstream_uint2(str, 3);
+ break;
+ default:
+ assert(0);
+ }
+ return;
+ }
+
+ vlc_table = image->vlc_table[vlc_select].table;
+ DEBUG(" DECODE_INDEX: vlc_select = %s, vlc_table = %d chroma_flag=%d, index_code=%d\n",
+ _jxr_vlc_index_name(vlc_select), vlc_table, chroma_flag, index_code);
+
+ bits = index1_vlc[vlc_table][index_code].bits;
+ len = index1_vlc[vlc_table][index_code].len;
+
+ DEBUG(" bits/len = 0x%02x/%u\n", bits, len);
+
+ while (len > 0) {
+ _jxr_wbitstream_uint1(str, (bits&0x80)? 1 : 0);
+ bits <<= 1;
+ len -= 1;
+ }
+
+ vlc_delta = image->vlc_table[vlc_select].deltatable;
+ vlc_delta2 = image->vlc_table[vlc_select].delta2table;
+
+ image->vlc_table[vlc_select].discriminant += Index1Delta[vlc_delta][index_code];
+ image->vlc_table[vlc_select].discriminant2+= Index1Delta[vlc_delta2][index_code];
+
+ DEBUG(" DECODE_INDEX: deltatable/2 = %d/%d, discriminant/2 becomes %d/%d\n",
+ vlc_delta, vlc_delta2,
+ image->vlc_table[vlc_select].discriminant,
+ image->vlc_table[vlc_select].discriminant2);
+
+}
+
+static void w_DECODE_RUN(jxr_image_t image, struct wbitstream*str, int max_run, int run)
+{
+ static const int remap[15] = {1,2,3,5,7,1,2,3,5,7,1,2,3,4,5};
+ static const int run_bin[15] = {-1,-1,-1,-1,2,2,2,1,1,1,1,0,0,0,0};
+ static const int run_fixed_len[15] = {0,0,1,1,3,0,0,1,1,2,0,0,0,0,1};
+ int index_run_bin;
+ int run_index;
+
+ assert(run > 0);
+ if (max_run < 5) {
+ DEBUG(" DECODE_RUN max_run=%d (<5) run=%d, bitpos=%zu\n",
+ max_run, run, _jxr_wbitstream_bitpos(str));
+
+ switch (max_run) {
+ case 1:
+ assert(run == 1);
+ break;
+ case 2:
+ assert(run <= 2);
+ if (run == 2)
+ _jxr_wbitstream_uint1(str, 0);
+ else
+ _jxr_wbitstream_uint1(str, 1);
+ break;
+ case 3:
+ if (run == 1)
+ _jxr_wbitstream_uint1(str, 1);
+ else if (run == 2) {
+ _jxr_wbitstream_uint1(str, 0);
+ _jxr_wbitstream_uint1(str, 1);
+ } else {
+ assert(run == 3);
+ _jxr_wbitstream_uint1(str, 0);
+ _jxr_wbitstream_uint1(str, 0);
+ }
+ break;
+ case 4:
+ if (run == 1) {
+ _jxr_wbitstream_uint1(str, 1);
+ } else if (run == 2) {
+ _jxr_wbitstream_uint1(str, 0);
+ _jxr_wbitstream_uint1(str, 1);
+ } else if (run == 3) {
+ _jxr_wbitstream_uint1(str, 0);
+ _jxr_wbitstream_uint1(str, 0);
+ _jxr_wbitstream_uint1(str, 1);
+ } else {
+ assert(run == 4);
+ _jxr_wbitstream_uint1(str, 0);
+ _jxr_wbitstream_uint1(str, 0);
+ _jxr_wbitstream_uint1(str, 0);
+ }
+ }
+ return;
+ }
+
+ assert(max_run < 15);
+ index_run_bin = 5*run_bin[max_run];
+
+ run_index = 0;
+ for (run_index = 0; run_index < 5; run_index += 1) {
+ int index = run_index + index_run_bin;
+ int use_run;
+ int fixed;
+ int range;
+ int run_fixed;
+
+ if (index < 0)
+ continue;
+
+ use_run = remap[index];
+ if (use_run > run)
+ continue;
+
+ fixed = run_fixed_len[index];
+ range = 1 << fixed;
+ if (run >= (use_run + range))
+ continue;
+
+ /* RUN_INDEX */
+ switch(run_index) {
+ case 0:
+ _jxr_wbitstream_uint1(str, 1);
+ break;
+ case 1:
+ _jxr_wbitstream_uint2(str, 1);
+ break;
+ case 2:
+ _jxr_wbitstream_uint1(str, 0);
+ _jxr_wbitstream_uint2(str, 1);
+ break;
+ case 3:
+ _jxr_wbitstream_uint4(str, 0);
+ break;
+ case 4:
+ _jxr_wbitstream_uint4(str, 1);
+ break;
+ }
+
+ run_fixed = 0;
+ if (fixed > 0) {
+ run_fixed = run - use_run;
+ assert(run_fixed >= 0 && run_fixed < (1<<fixed));
+ _jxr_wbitstream_uintN(str, run_fixed, fixed);
+ }
+
+ DEBUG(" DECODE_RUN max_run=%d run=%d+%d = %d, bitpos=%zu\n",
+ max_run, use_run, run_fixed, run, _jxr_wbitstream_bitpos(str));
+
+ return;
+ }
+ assert(0);
+}
+
+static int w_DECODE_BLOCK_ADAPTIVE(jxr_image_t image, struct wbitstream*str,
+ unsigned tx, unsigned mx,
+ int cbp_flag, int chroma_flag,
+ int channel, int block, int mbhp_pred_mode,
+ unsigned model_bits)
+{
+ int values[16];
+ int values2[16];
+ int idx;
+ int coeffs[32];
+ int num_nonzero;
+
+ /* If the CBP flag is off, then there isn't really anything to
+ encode here. */
+ if (cbp_flag == 0)
+ return 0;
+
+ values[0] = 0;
+ DEBUG(" HP val[tx=%d, mx=%d, block=%d] ==", tx, mx, block);
+ for (idx = 0 ; idx < 15 ; idx += 1) {
+ values[1+idx] = MACROBLK_CUR_HP(image,channel,tx,mx,block,idx);
+ /* Shift out the model bits. Be careful to note that the
+ value is processed as sign/magnitude, so do the
+ shifting to the abs of the value and invert it back
+ if nesessary. */
+ if (values[1+idx] >= 0)
+ values[1+idx] >>= model_bits;
+ else
+ values[1+idx] = - ( (-values[1+idx]) >> model_bits );
+ DEBUG(" 0x%x", values[1+idx]);
+ }
+ DEBUG("\n");
+
+ values2[0] = 0;
+ AdaptiveHPPermute(image, values2, values, mbhp_pred_mode);
+#if defined(DETAILED_DEBUG)
+ {
+ int k;
+ DEBUG(" adapted hor scan order (MBHPMode=%d) ==", mbhp_pred_mode);
+ for (k = 0 ; k<15; k+=1) {
+ DEBUG(" %2d", image->hipass_hor_scanorder[k]);
+ }
+ DEBUG("\n");
+ DEBUG(" adapted hor scan totals ==");
+ for (k = 0 ; k<15; k+=1) {
+ DEBUG(" %2d", image->hipass_hor_scantotals[k]);
+ }
+ DEBUG("\n");
+ DEBUG(" adapted ver scan order (MBHPMode=%d) ==", mbhp_pred_mode);
+ for (k = 0 ; k<15; k+=1) {
+ DEBUG(" %2d", image->hipass_ver_scanorder[k]);
+ }
+ DEBUG("\n");
+ DEBUG(" adapted ver scan totals ==");
+ for (k = 0 ; k<15; k+=1) {
+ DEBUG(" %2d", image->hipass_ver_scantotals[k]);
+ }
+ DEBUG("\n");
+ }
+#endif
+
+ num_nonzero = RunLengthEncode(image, coeffs, values2);
+
+ w_DECODE_BLOCK(image, str, 2, chroma_flag, coeffs, num_nonzero);
+
+ return num_nonzero;;
+}
+
+/*
+* $Log: w_emit.c,v $
+* Revision 1.28 2009/09/16 12:00:00 microsoft
+* Reference Software v1.8 updates.
+*
+* Revision 1.27 2009/05/29 12:00:00 microsoft
+* Reference Software v1.6 updates.
+*
+* Revision 1.26 2009/04/13 12:00:00 microsoft
+* Reference Software v1.5 updates.
+*
+* Revision 1.25 2008/03/24 18:06:56 steve
+* Imrpove DEBUG messages around quantization.
+*
+* Revision 1.24 2008/03/21 18:05:53 steve
+* Proper CMYK formatting on input.
+*
+* Revision 1.23 2008/03/13 21:23:27 steve
+* Add pipeline step for YUV420.
+*
+* Revision 1.22 2008/03/13 00:30:56 steve
+* Force SCALING on if using a subsampled color format.
+*
+* Revision 1.21 2008/03/11 22:12:49 steve
+* Encode YUV422 through DC.
+*
+* Revision 1.20 2008/03/05 06:58:10 gus
+* *** empty log message ***
+*
+* Revision 1.19 2008/03/05 04:04:30 steve
+* Clarify constraints on USE_DC_QP in image plane header.
+*
+* Revision 1.18 2008/03/05 00:31:18 steve
+* Handle UNIFORM/IMAGEPLANE_UNIFORM compression.
+*
+* Revision 1.17 2008/03/02 19:56:27 steve
+* Infrastructure to read write BD16 files.
+*
+* Revision 1.16 2008/02/28 18:50:31 steve
+* Portability fixes.
+*
+* Revision 1.15 2008/02/26 23:52:44 steve
+* Remove ident for MS compilers.
+*
+* Revision 1.14 2008/02/22 23:01:33 steve
+* Compress macroblock HP CBP packets.
+*
+* Revision 1.13 2008/02/01 22:49:53 steve
+* Handle compress of YUV444 color DCONLY
+*
+* Revision 1.12 2008/01/08 01:06:20 steve
+* Add first pass overlap filtering.
+*
+* Revision 1.11 2008/01/07 16:19:10 steve
+* Properly configure TRIM_FLEXBITS_FLAG bit.
+*
+* Revision 1.10 2008/01/04 17:07:36 steve
+* API interface for setting QP values.
+*
+* Revision 1.9 2007/12/13 18:01:09 steve
+* Stubs for HP encoding.
+*
+* Revision 1.8 2007/12/07 01:20:34 steve
+* Fix adapt not adapting on line ends.
+*
+* Revision 1.7 2007/12/05 18:14:19 steve
+* hard-code LOG_WORD_FLAG true.
+*
+* Revision 1.6 2007/12/04 22:06:10 steve
+* Infrastructure for encoding LP.
+*
+* Revision 1.5 2007/11/30 01:50:58 steve
+* Compression of DCONLY GRAY.
+*
+* Revision 1.4 2007/11/26 01:47:16 steve
+* Add copyright notices per MS request.
+*
+* Revision 1.3 2007/11/08 19:38:38 steve
+* Get stub DCONLY compression to work.
+*
+* Revision 1.2 2007/11/08 02:52:33 steve
+* Some progress in some encoding infrastructure.
+*
+* Revision 1.1 2007/06/06 17:19:13 steve
+* Introduce to CVS.
+*
+*/
+
diff --git a/jpegxr/w_strip.c b/jpegxr/w_strip.c
new file mode 100644
index 000000000..abd8ca5ba
--- /dev/null
+++ b/jpegxr/w_strip.c
@@ -0,0 +1,3348 @@
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+**********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: w_strip.c,v 1.47 2008/03/24 18:06:56 steve Exp $")
+#else
+#ident "$Id: w_strip.c,v 1.47 2008/03/24 18:06:56 steve Exp $"
+#endif
+
+# include "jxr_priv.h"
+# include <stdlib.h>
+# include <limits.h>
+# include <assert.h>
+
+# define FILTERED_YUV_SAMPLE 1
+
+static void w_rotate_mb_strip(jxr_image_t image);
+static void collect_and_scale_up4(jxr_image_t image, int ty);
+static void scale_and_shuffle_up3(jxr_image_t image);
+static void first_prefilter_up2(jxr_image_t image, int ty);
+static void PCT_stage2_up1(jxr_image_t image, int ch, int ty);
+static void second_prefilter_up1(jxr_image_t image, int ty);
+static void PCT_stage1_up2(jxr_image_t image, int ch, int ty);
+static void w_predict_up1_dclp(jxr_image_t image, int tx, int ty, int mx);
+static int w_calculate_mbhp_mode_up1(jxr_image_t image, int tx, int mx);
+static void w_predict_lp444(jxr_image_t image, int tx, int mx, int my, int ch, int mblp_mode);
+static void w_predict_lp422(jxr_image_t image, int tx, int mx, int my, int ch, int mblp_mode, int mbdc_mode);
+static void w_predict_lp420(jxr_image_t image, int tx, int mx, int my, int ch, int mblp_mode);
+static void calculate_hpcbp_up1(jxr_image_t image, int tx, int ty, int mx);
+static void w_predict_up1_hp(jxr_image_t image, int ch, int tx, int mx, int mbhp_pred_mode);
+static void w_PredCBP(jxr_image_t image, unsigned tx, unsigned ty, unsigned mx);
+static void wflush_to_tile_buffer(jxr_image_t image, int my);
+static void wflush_collect_mb_strip_data(jxr_image_t image, int my);
+static void _jxr_w_store_hpcbp_state(jxr_image_t image, int tx);
+static void _jxr_w_load_hpcbp_state(jxr_image_t image, int tx);
+
+static unsigned char w_guess_dc_quant(jxr_image_t image, int ch,
+ unsigned tx, unsigned ty)
+{
+ struct jxr_tile_qp*cur;
+
+ if (image->dc_frame_uniform)
+ return image->dc_quant_ch[ch];
+
+ cur = GET_TILE_QUANT(image,tx,ty);
+
+ if (ch == 0)
+ return cur->channel[0].dc_qp;
+
+ switch (cur->component_mode) {
+ case JXR_CM_UNIFORM:
+ return cur->channel[0].dc_qp;
+ case JXR_CM_SEPARATE:
+ return cur->channel[1].dc_qp;
+ case JXR_CM_INDEPENDENT:
+ return cur->channel[ch].dc_qp;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+unsigned char _jxr_select_lp_index(jxr_image_t image, unsigned tx, unsigned ty,
+ unsigned mx, unsigned my)
+{
+ struct jxr_tile_qp*cur;
+ unsigned mxy;
+ unsigned lp_index;
+ /* If this is frame uniform LP QP, then implicitly the QP
+ index is always zero. */
+ if (image->lp_frame_uniform)
+ return 0;
+
+ /* Otherwise we have the more complicated case that the LP QP
+ index may vary per MB. */
+ cur = GET_TILE_QUANT(image,tx,ty);
+ if (cur->lp_map == 0)
+ return 0;
+
+ mxy = my*jxr_get_TILE_WIDTH(image, tx) + mx;
+
+ lp_index = cur->lp_map[mxy];
+ assert(lp_index < cur->channel[0].num_lp || lp_index==0);
+
+ return lp_index;
+}
+
+static unsigned char w_guess_lp_quant(jxr_image_t image, int ch,
+ unsigned tx, unsigned ty, unsigned mx, unsigned my)
+{
+ unsigned idx;
+ struct jxr_tile_qp*cur;
+
+ if (image->lp_frame_uniform)
+ return image->lp_quant_ch[ch][0];
+
+ idx = _jxr_select_lp_index(image, tx, ty, mx, my);
+ cur = GET_TILE_QUANT(image,tx,ty);
+
+ if (ch == 0)
+ return cur->channel[0].lp_qp[idx];
+
+ switch (cur->component_mode) {
+ case JXR_CM_UNIFORM:
+ return cur->channel[0].lp_qp[idx];
+ case JXR_CM_SEPARATE:
+ return cur->channel[1].lp_qp[idx];
+ case JXR_CM_INDEPENDENT:
+ return cur->channel[ch].lp_qp[idx];
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+unsigned char _jxr_select_hp_index(jxr_image_t image, unsigned tx, unsigned ty,
+ unsigned mx, unsigned my)
+{
+ unsigned mxy;
+ unsigned hp_index;
+ struct jxr_tile_qp*cur;
+
+ if (image->hp_frame_uniform)
+ return 0;
+
+ cur = GET_TILE_QUANT(image,tx,ty);
+ /* If there is no actual map, then assume all indices in the
+ tile are zero. */
+ if (cur->hp_map == 0)
+ return 0;
+
+ mxy = my*jxr_get_TILE_WIDTH(image, tx) + mx;
+
+ hp_index = cur->hp_map[mxy];
+ assert(hp_index < cur->channel[0].num_hp || hp_index == 0);
+
+ return hp_index;
+}
+
+static unsigned char w_guess_hp_quant(jxr_image_t image, int ch,
+ unsigned tx, unsigned ty,
+ int mx, int my)
+{
+ unsigned idx;
+ struct jxr_tile_qp*cur;
+
+ if (image->hp_frame_uniform)
+ return image->hp_quant_ch[ch][0];
+
+ idx = _jxr_select_hp_index(image, tx, ty, mx, my);
+ cur = GET_TILE_QUANT(image,tx,ty);
+
+ if (ch == 0)
+ return cur->channel[0].hp_qp[idx];
+
+ switch (cur->component_mode) {
+ case JXR_CM_UNIFORM:
+ return cur->channel[0].hp_qp[idx];
+ case JXR_CM_SEPARATE:
+ return cur->channel[1].hp_qp[idx];
+ case JXR_CM_INDEPENDENT:
+ return cur->channel[ch].hp_qp[idx];
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+static int quantize_dc(int value, int quant)
+{
+ int sign = 1;
+ int offset;
+ if (value < 0) {
+ sign = -1;
+ value = -value;
+ }
+
+ offset = quant >> 1;
+
+ return sign * (value + offset)/quant;
+}
+
+static int quantize_lphp(int value, int quant)
+{
+ int sign = 1;
+ int offset;
+ if (value < 0) {
+ sign = -1;
+ value = -value;
+ }
+
+ offset = (quant*3 + 1) >> 3;
+
+ return sign * (value + offset)/quant;
+}
+
+static void dump_all_strips(jxr_image_t image)
+{
+#if defined(DETAILED_DEBUG) && 0
+ int mx;
+ int ch;
+#if 1
+ for (mx = 0 ; mx < EXTENDED_WIDTH_BLOCKS(image) ; mx += 1) {
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ int jdx;
+ DEBUG("up3: mx=%3d ch=%d:", mx, ch);
+ for (jdx = 0 ; jdx < 256 ; jdx += 1) {
+ if (jdx%8 == 0 && jdx != 0)
+ DEBUG("\n%*s", 17, "");
+ DEBUG(" %08x", image->strip[ch].up3[mx].data[jdx]);
+ }
+ DEBUG("\n");
+ }
+ }
+#endif
+#if 0
+ for (mx = 0 ; mx < EXTENDED_WIDTH_BLOCKS(image) ; mx += 1) {
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ int jdx;
+ DEBUG("up2: mx=%3d ch=%d:", mx, ch);
+ for (jdx = 0 ; jdx < 256 ; jdx += 1) {
+ if (jdx%8 == 0 && jdx != 0)
+ DEBUG("\n%*s", 17, "");
+ DEBUG(" %08x", image->strip[ch].up2[mx].data[jdx]);
+ }
+ DEBUG("\n");
+ }
+ }
+#endif
+#if 0
+ for (mx = 0 ; mx < EXTENDED_WIDTH_BLOCKS(image) ; mx += 1) {
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ int jdx;
+ DEBUG("up1: mx=%3d ch=%d:", mx, ch);
+ for (jdx = 0 ; jdx < 256 ; jdx += 1) {
+ if (jdx%8 == 0 && jdx != 0)
+ DEBUG("\n%*s", 17, "");
+ DEBUG(" %08x", image->strip[ch].up1[mx].data[jdx]);
+ }
+ DEBUG("\n");
+ }
+ }
+#endif
+#endif
+}
+
+/*
+* This function is use to prepare a strip of MB data for use by the
+* encoder. After this call is complete, the "my" strip with tx/ty is
+* ready in the CUR strip. The data is filled into the pipeline
+* starting with UP3, where it is processed and worked down to
+* CUR. The CUR strip is then processed and formatted.
+*
+* On entry to this function, the CUR strip is no longer needed, so
+* may immediately be tossed.
+*/
+static void wflush_process_strip(jxr_image_t image, int ty)
+{
+ int ch;
+ const int height = EXTENDED_HEIGHT_BLOCKS(image);
+ int cur_row;
+
+ DEBUG("wflush_process_strip: image->cur_my = %d\n", image->cur_my);
+ dump_all_strips(image);
+
+ cur_row = image->tile_row_position[ty] + image->cur_my;
+
+ /* Finish up scaling of the image data, and shuffle it to the
+ internal sub-block format. */
+ if (cur_row >= -3 && cur_row < (height-3)) {
+ scale_and_shuffle_up3(image);
+ }
+
+ /* Transform on up2 data. At this point, the up2 and up3
+ strips are lines N (up2) and N+1 (up3) of scaled image
+ data. After this section is done, the image data in up2
+ becomes DC-HP data. */
+ if (cur_row >= -2 && cur_row < (height-2)) {
+
+
+ /* If overlap filtering is enabled, then do it. The
+ filter assumes that this strip (up2) and the next
+ (up3) are collected and scaled. The filter looks
+ ahead to up3 for bottom context. */
+ if (OVERLAP_INFO(image) != 0)
+ first_prefilter_up2(image,ty);
+
+ /* Transform up2 data to DC-HP coefficients. */
+ for (ch = 0; ch < image->num_channels ; ch += 1)
+ PCT_stage1_up2(image, ch, ty);
+
+ /* read lwf test flag into image container */
+ if (image->lwf_test == 0)
+ image->lwf_test = _jxr_read_lwf_test_flag();
+ }
+
+ /* Second tranform on up1 data. The DC-HP data becomes DC-LP-HP. */
+ if (cur_row >= -1 && cur_row < (height-1)) {
+
+ /* If intermediate overlap filtering is enabled, then do
+ it. The filter assumes that this strip (up1) and the
+ next (up2) have already been PCT processed. */
+ if (OVERLAP_INFO(image) == 2)
+ second_prefilter_up1(image,ty);
+
+ /* PCT_level1_cur */
+ for (ch = 0; ch < image->num_channels ; ch += 1)
+ PCT_stage2_up1(image, ch, ty);
+
+ /* read lwf test flag into image container */
+ if (image->lwf_test == 0)
+ image->lwf_test = _jxr_read_lwf_test_flag();
+ }
+
+ if (cur_row >= -1 && cur_row < (height-1)) {
+ /* DC-LP prediction on the CURUP1strip. At this point CUR an UP1
+ are PCT transformed, and CUR is predicted. After this, UP1
+ will also be predicted with pred_dclp members filled in
+ with saved PCT coefficients. */
+ int tx;
+ for (tx = 0; tx < (int) image->tile_columns ; tx += 1) {
+ int mx;
+ for (mx = 0 ; mx < (int) image->tile_column_width[tx] ; mx += 1) {
+ /* Calculate the MB HP prediction mode. This uses
+ only local information, namely the LP values. */
+ int mbhp_pred_mode = w_calculate_mbhp_mode_up1(image, tx, mx);
+ assert(mbhp_pred_mode < 4);
+
+ MACROBLK_UP1(image,0,tx,mx).mbhp_pred_mode = mbhp_pred_mode;
+
+ /* Run DCLP prediction. This assumes that the
+ previous (CUR) strip has already been
+ predicted, and uses some predict values from
+ that strip. */
+ w_predict_up1_dclp(image, tx, ty, mx);
+ }
+ }
+ }
+
+ if (cur_row >= -1 && cur_row < (height-1)) {
+ int use_num_channels;
+ int tx;
+ DEBUG("wflush_process_string: Calculate HP CBP for my=%d\n", cur_row+1);
+
+ /* Perform HP prediction. */
+ use_num_channels = image->num_channels;
+ if (image->use_clr_fmt == 1/*YUV420*/ || image->use_clr_fmt == 2/*YUV422*/)
+ use_num_channels = 1;
+
+ image->model_hp;
+ for (tx = 0; tx < (int) image->tile_columns ; tx += 1) {
+ int mx;
+ if (image->tile_columns > 1)
+ _jxr_w_load_hpcbp_state(image, tx);
+ for (mx = 0 ; mx < (int) image->tile_column_width[tx] ; mx += 1) {
+ int mbhp_pred_mode = MACROBLK_UP1(image,0,tx,mx).mbhp_pred_mode;
+ int idx;
+ for (idx = 0 ; idx < use_num_channels ; idx += 1)
+ w_predict_up1_hp(image, idx, tx, mx, mbhp_pred_mode);
+
+ /* Also calculate and predict HPCBP in up1. */
+ calculate_hpcbp_up1(image, tx, ty, mx);
+ w_PredCBP(image, tx, ty, mx);
+ }
+ if (image->tile_columns > 1)
+ _jxr_w_store_hpcbp_state(image, tx);
+ }
+ }
+
+ DEBUG("wflush_process_strip done: cur_row = %d\n", cur_row);
+}
+
+/* since hpcbp is processed at each row, need to save context for each tile column */
+void _jxr_w_load_hpcbp_state(jxr_image_t image, int tx)
+{
+ unsigned idx;
+ for (idx = 0 ; idx < 2 ; idx += 1) {
+ image->model_hp.bits[idx] = image->model_hp_buffer[tx].bits[idx];
+ image->model_hp.state[idx] = image->model_hp_buffer[tx].state[idx];
+
+ image->hp_cbp_model.state[idx] = image->hp_cbp_model_buffer[tx].state[idx];
+ image->hp_cbp_model.count0[idx] = image->hp_cbp_model_buffer[tx].count0[idx];
+ image->hp_cbp_model.count1[idx] = image->hp_cbp_model_buffer[tx].count1[idx];
+ }
+}
+
+void _jxr_w_store_hpcbp_state(jxr_image_t image, int tx)
+{
+ unsigned idx;
+ for (idx = 0 ; idx < 2 ; idx += 1) {
+ image->model_hp_buffer[tx].bits[idx] = image->model_hp.bits[idx];
+ image->model_hp_buffer[tx].state[idx] = image->model_hp.state[idx];
+
+ image->hp_cbp_model_buffer[tx].state[idx] = image->hp_cbp_model.state[idx];
+ image->hp_cbp_model_buffer[tx].count0[idx] = image->hp_cbp_model.count0[idx];
+ image->hp_cbp_model_buffer[tx].count1[idx] = image->hp_cbp_model.count1[idx];
+ }
+}
+
+void _jxr_wflush_mb_strip(jxr_image_t image, int tx, int ty, int my, int read_new)
+{
+ unsigned ty_offset = 0;
+ DEBUG("wflush_mb_strip: cur_my=%d, tile-x/y=%d/%d, my=%d\n", image->cur_my, tx, ty, my);
+
+ if (FREQUENCY_MODE_CODESTREAM_FLAG(image))
+ ty_offset = image->tile_row_position[ty];
+
+ if (my == 0 && (image->cur_my >= 0)) {
+ /* reset the current row value for a new tile */
+ image->cur_my = my - 1;
+
+ if (ALPHACHANNEL_FLAG(image))
+ image->alpha->cur_my = my - 1;
+ }
+
+ if ((tx == 0) && (read_new == 1)) {
+ /* Process entire strip, then store it */
+ while (image->cur_my < my) {
+ const int height = EXTENDED_HEIGHT_BLOCKS(image);
+ int cur_row;
+
+ w_rotate_mb_strip(image);
+ image->cur_my += 1;
+ cur_row = image->tile_row_position[ty] + image->cur_my;
+ if (ALPHACHANNEL_FLAG(image)) {
+ w_rotate_mb_strip(image->alpha);
+ image->alpha->cur_my += 1;
+ }
+
+ /* Load up4 with new image data. */
+ if (cur_row >= -4 && cur_row < (height-4)) {
+ collect_and_scale_up4(image, ty);
+ }
+
+ wflush_process_strip(image, ty);
+ if ((INDEXTABLE_PRESENT_FLAG(image)) && (image->cur_my >= 0)) {
+ /* save processed row */
+ wflush_to_tile_buffer(image, image->cur_my + ty_offset);
+ }
+ if (ALPHACHANNEL_FLAG(image)) {
+ wflush_process_strip(image->alpha, ty);
+ if ((INDEXTABLE_PRESENT_FLAG(image->alpha)) && (image->alpha->cur_my >= 0)) {
+ /* save processed row */
+ wflush_to_tile_buffer(image->alpha, image->alpha->cur_my + ty_offset);
+ }
+ }
+ }
+ }
+ else {
+ /* load a row of mb data as appropriate */
+ image->cur_my += 1;
+ wflush_collect_mb_strip_data(image, image->cur_my + ty_offset);
+
+ if (ALPHACHANNEL_FLAG(image)) {
+ image->alpha->cur_my += 1;
+ wflush_collect_mb_strip_data(image->alpha, image->alpha->cur_my + ty_offset);
+ }
+ }
+}
+
+/*
+* The tile_row_buffer holds flushed mb data in image raster order,
+* along with other per-mb data. This is in support of tiled SPATIAL processing.
+* This function saves mb row information for all rows of the the current tile row
+*/
+static void wflush_to_tile_buffer(jxr_image_t image, int my)
+{
+ int format_scale = 256;
+ int tx;
+ DEBUG("wflush_mb_strip: wflush_to_tile_buffer my=%d\n", my);
+
+ if (image->use_clr_fmt == 2 /* YUV422 */) {
+ format_scale = 16 + 8*15;
+ } else if (image->use_clr_fmt == 1 /* YUV420 */) {
+ format_scale = 16 + 4*15;
+ }
+
+
+ for (tx = 0; tx < (int) image->tile_columns ; tx += 1) {
+ int mx;
+ for (mx = 0 ; mx < (int) image->tile_column_width[tx] ; mx += 1) {
+ int off;
+ int ch;
+ DEBUG("wflush_mb_strip: wflush_to_tile_buffer tx=%d, mx=%d, CUR=0x%08x UP1=0x%08x, UP2=0x%08x, UP3=0x%08x, LP_QUANT=%d\n",
+ tx, mx, MACROBLK_CUR(image,0,tx,mx).data[0],
+ MACROBLK_UP1(image,0,tx,mx).data[0],
+ MACROBLK_UP2(image,0,tx,mx).data[0],
+ MACROBLK_UP3(image,0,tx,mx).data[0],
+ MACROBLK_CUR_LP_QUANT(image,0,tx,mx));
+
+ off = my * EXTENDED_WIDTH_BLOCKS(image) + image->tile_column_position[tx] + mx;
+ for (ch = 0; ch < image->num_channels; ch += 1) {
+ int count;
+ int idx;
+ struct macroblock_s*mb = image->mb_row_buffer[ch] + off;
+ mb->lp_quant = MACROBLK_CUR_LP_QUANT(image,ch,tx,mx);
+ mb->hp_quant = MACROBLK_CUR(image,ch,tx,mx).hp_quant;
+ mb->hp_cbp = MACROBLK_CUR(image,ch,tx,mx).hp_cbp;
+ mb->hp_diff_cbp = MACROBLK_CUR(image,ch,tx,mx).hp_diff_cbp;
+ mb->mbhp_pred_mode = MACROBLK_CUR(image,ch,tx,mx).mbhp_pred_mode;
+ mb->hp_model_bits[0] = MACROBLK_CUR(image,ch,tx,mx).hp_model_bits[0];
+ mb->hp_model_bits[1] = MACROBLK_CUR(image,ch,tx,mx).hp_model_bits[1];
+ count = (ch==0)? 256 : format_scale;
+ for (idx = 0 ; idx < count ; idx += 1)
+ mb->data[idx] = MACROBLK_CUR(image,ch,tx,mx).data[idx];
+ for (idx = 0 ; idx < 7 ; idx += 1)
+ mb->pred_dclp[idx] = MACROBLK_CUR(image,ch,tx,mx).pred_dclp[idx];
+ }
+ }
+ }
+}
+
+/*
+* Recover a strip of data from all but the last column of data. Skip
+* the last column because this function is called while the last
+* column is being processed.
+* This function loads mb row information for all rows of the the current tile row
+*/
+static void wflush_collect_mb_strip_data(jxr_image_t image, int my)
+{
+ int format_scale = 256;
+ int tx;
+ DEBUG("wflush_mb_strip: wflush_collect_mb_strip_data my=%d\n", my);
+
+ if (image->use_clr_fmt == 2 /* YUV422 */) {
+ format_scale = 16 + 8*15;
+ } else if (image->use_clr_fmt == 1 /* YUV420 */) {
+ format_scale = 16 + 4*15;
+ }
+
+ for (tx = 0; tx < (int) image->tile_columns ; tx += 1) {
+ int mx;
+ for (mx = 0; mx < (int) image->tile_column_width[tx]; mx += 1) {
+ int off = my * EXTENDED_WIDTH_BLOCKS(image) + image->tile_column_position[tx] + mx;
+ int ch;
+ for (ch = 0; ch < image->num_channels; ch += 1) {
+ struct macroblock_s*mb = image->mb_row_buffer[ch] + off;
+ int count;
+ int idx;
+ MACROBLK_CUR_LP_QUANT(image,ch,tx,mx) = mb->lp_quant;
+ MACROBLK_CUR(image,ch,tx,mx).hp_quant = mb->hp_quant;
+ MACROBLK_CUR(image,ch,tx,mx).hp_cbp = mb->hp_cbp;
+ MACROBLK_CUR(image,ch,tx,mx).hp_diff_cbp = mb->hp_diff_cbp;
+ MACROBLK_CUR(image,ch,tx,mx).mbhp_pred_mode = mb->mbhp_pred_mode;
+ MACROBLK_CUR(image,ch,tx,mx).hp_model_bits[0] = mb->hp_model_bits[0];
+ MACROBLK_CUR(image,ch,tx,mx).hp_model_bits[1] = mb->hp_model_bits[1];
+ count = (ch==0)? 256 : format_scale;
+ for (idx = 0 ; idx < count; idx += 1)
+ MACROBLK_CUR(image,ch,tx,mx).data[idx] = mb->data[idx];
+ for (idx = 0 ; idx < 7 ; idx += 1)
+ MACROBLK_CUR(image,ch,tx,mx).pred_dclp[idx] = mb->pred_dclp[idx];
+ }
+ DEBUG("wflush_mb_strip: wflush_collect_mb_strip_data tx=%d, mx=%d, CUR=0x%08x UP1=0x%08x, UP2=0x%08x, UP3=0x%08x lp_quant=%d\n",
+ tx, mx, MACROBLK_CUR(image,0,tx,mx).data[0],
+ MACROBLK_UP1(image,0,tx,mx).data[0],
+ MACROBLK_UP2(image,0,tx,mx).data[0],
+ MACROBLK_UP3(image,0,tx,mx).data[0],
+ MACROBLK_CUR_LP_QUANT(image,0,tx,mx));
+ }
+ }
+}
+
+static void w_rotate_mb_strip(jxr_image_t image)
+{
+ int ch;
+
+ _jxr_clear_strip_cur(image);
+
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ struct macroblock_s*tmp = image->strip[ch].cur;
+ image->strip[ch].cur = image->strip[ch].up1;
+ image->strip[ch].up1 = image->strip[ch].up2;
+ image->strip[ch].up2 = image->strip[ch].up3;
+ image->strip[ch].up3 = image->strip[ch].up4;
+ image->strip[ch].up4 = tmp;
+ }
+}
+
+/*
+* Transform RGB input data to YUV444 data. Do the transform in place,
+* assuming the input channels are R, G and B in order.
+*/
+static void rgb_to_yuv444_up4(jxr_image_t image)
+{
+ unsigned mx;
+ for (mx = 0 ; mx < EXTENDED_WIDTH_BLOCKS(image) ; mx += 1) {
+ int*dataR = MACROBLK_UP4(image,0,0,mx).data;
+ int*dataG = MACROBLK_UP4(image,1,0,mx).data;
+ int*dataB = MACROBLK_UP4(image,2,0,mx).data;
+ int idx;
+ for (idx = 0 ; idx < 16*16 ; idx += 1) {
+ const int R = dataR[idx];
+ const int G = dataG[idx];
+ const int B = dataB[idx];
+ const int V = B - R;
+ const int tmp = R - G + _jxr_ceil_div2(V);
+ const int Y = G + _jxr_floor_div2(tmp);
+ const int U = -tmp;
+ dataR[idx] = Y;
+ dataG[idx] = U;
+ dataB[idx] = V;
+ }
+ }
+}
+
+static void cmyk_to_yuvk_up4(jxr_image_t image)
+{
+ unsigned mx;
+ for (mx = 0 ; mx < EXTENDED_WIDTH_BLOCKS(image) ; mx += 1) {
+ int*datac = MACROBLK_UP4(image,0,0,mx).data;
+ int*datam = MACROBLK_UP4(image,1,0,mx).data;
+ int*datay = MACROBLK_UP4(image,2,0,mx).data;
+ int*datak = MACROBLK_UP4(image,3,0,mx).data;
+ int idx;
+ for (idx = 0 ; idx < 16*16 ; idx += 1) {
+ const int c = datac[idx];
+ const int m = datam[idx];
+ const int y = datay[idx];
+ const int k = datak[idx];
+ const int V = c - y;
+ const int U = c - m - _jxr_floor_div2(V);
+ const int Y = k - m - _jxr_floor_div2(U);
+ const int K = k - _jxr_floor_div2(Y);
+ datac[idx] = Y;
+ datam[idx] = U;
+ datay[idx] = V;
+ datak[idx] = K;
+ }
+ }
+}
+
+/*
+* Transform YUV444 input data to YUV422 by subsampling the UV planes
+* horizontally.
+*/
+#if defined(FILTERED_YUV_SAMPLE)
+static void yuv444_to_yuv422_up4(jxr_image_t image)
+{
+ int ch;
+ int px, py;
+
+ int*buf[16];
+ for (py = 0 ; py < 16 ; py += 1)
+ buf[py] = (int*)calloc(8*EXTENDED_WIDTH_BLOCKS(image), sizeof(int));
+
+ for (ch = 1 ; ch < 3 ; ch += 1) {
+ unsigned mx;
+ for (mx = 0 ; mx < EXTENDED_WIDTH_BLOCKS(image) ; mx += 1) {
+ int*prev = mx>0? MACROBLK_UP4(image,ch,0,mx-1).data : 0;
+ int*data = MACROBLK_UP4(image,ch,0,mx).data;
+ int*next = (mx+1)<EXTENDED_WIDTH_BLOCKS(image)? MACROBLK_UP4(image,ch,0,mx+1).data : 0;
+
+ for (py = 0 ; py < 16 ; py += 1) {
+ int*bp = buf[py]+8*mx;
+ int*src = data + 16*py;
+ if (prev == 0) {
+ bp[0] = 2*src[2] + 8*src[1] + 6*src[0] + 8;
+ } else {
+ int*tmp = prev + 16*py;
+ bp[0] = 1*tmp[14] + 4*tmp[15] + 6*src[0] + 4*src[1] + 1*src[2] + 8;
+ }
+
+ for (px = 2 ; px < 14 ; px += 2) {
+ bp[px/2] = 1*src[px-2] + 4*src[px-1] + 6*src[px] + 4*src[px+1] + 1*src[px+2] + 8;
+ }
+
+ if (next==0) {
+ bp[7] = 1*src[12] + 4*src[13] + 6*src[14] + 4*src[15] + 1*src[14] + 8;
+ } else {
+ int*tmp = next + 16*py;
+ bp[7] = 1*src[12] + 4*src[13] + 6*src[14] + 4*src[15] + 1*tmp[0] + 8;
+ }
+ }
+ }
+
+ for (mx = 0 ; mx < EXTENDED_WIDTH_BLOCKS(image) ; mx += 1) {
+ int*data = MACROBLK_UP4(image,ch,0,mx).data;
+ for (py = 0 ; py < 16 ; py += 1) {
+ int*bp = buf[py] + 8*mx;
+ int*dst = data+8*py;
+ for (px = 0 ; px < 8 ; px += 1)
+ dst[px] = bp[px] >> 4;
+ }
+ }
+ }
+
+ for (py = 0 ; py < 16 ; py += 1)
+ free(buf[py]);
+}
+
+static void yuv422_to_yuv420_up3(jxr_image_t image)
+{
+ int my = image->cur_my + 3;
+
+ int ch;
+ assert(my >= 0);
+ for (ch = 1 ; ch < 3 ; ch += 1) {
+ unsigned mx;
+ for (mx = 0 ; mx < EXTENDED_WIDTH_BLOCKS(image); mx += 1) {
+ int*data = MACROBLK_UP3(image,ch,0,mx).data;
+ /* Save the unreduced data to allow for overlapping */
+ int*dataX = data + 128;
+ int idx;
+ int px, py;
+ for (idx = 0 ; idx < 128 ; idx += 1)
+ dataX[idx] = data[idx];
+
+
+ /* First, handle py==0 */
+ if (my == 0) {
+ int*next1 = data+1*8;
+ int*next2 = data+2*8;
+ for (px = 0 ; px < 8 ; px += 1) {
+ int val = 2*next2[px] + 8*next1[px] + 6*data[px] + 8;
+ data[px] = val >> 4;
+ }
+ } else {
+ int*prev2 = MACROBLK_UP2(image,ch,0,mx).data + 128 + 14*8;
+ int*prev1 = MACROBLK_UP2(image,ch,0,mx).data + 128 + 15*8;
+ int*cur = dataX+0*8;
+ int*next1 = dataX+1*8;
+ int*next2 = dataX+2*8;
+ for (px = 0 ; px < 8 ; px += 1) {
+ int val = 1*next2[px] + 4*next1[px] + 6*cur[px] + 4*prev1[px] + 1*prev2[px] +8;
+ data[px] = val >> 4;
+ }
+ }
+
+ /* py = 1-6 */
+ for (py = 2 ; py < 14 ; py += 2) {
+ int*prev2 = dataX + 8*(py-2);
+ int*prev1 = dataX + 8*(py-1);
+ int*cur = dataX + 8*(py+0);
+ int*next1 = dataX + 8*(py+1);
+ int*next2 = dataX + 8*(py+2);
+ for (px = 0 ; px < 8 ; px += 1) {
+ int val = 1*next2[px] + 4*next1[px] + 6*cur[px] + 4*prev1[px] + 1*prev2[px] +8;
+ data[px + 8*(py/2)] = val >> 4;
+ }
+ }
+
+ /* py == 7 */
+ if ((my+1) < (int) EXTENDED_HEIGHT_BLOCKS(image)) {
+ int*prev2 = dataX + 8*(14-2);
+ int*prev1 = dataX + 8*(14-1);
+ int*cur = dataX + 8*(14+0);
+ int*next1 = dataX + 8*(14+1);
+ int*next2 = MACROBLK_UP4(image,ch,0,mx).data + 0*8;
+ for (px = 0 ; px < 8 ; px += 1) {
+ int val = 1*next2[px] + 4*next1[px] + 6*cur[px] + 4*prev1[px] + 1*prev2[px] +8;
+ data[px + 8*(py/2)] = val >> 4;
+ }
+ } else {
+ int*prev2 = dataX + 8*(14-2);
+ int*prev1 = dataX + 8*(14-1);
+ int*cur = dataX + 8*(14+0);
+ int*next1 = dataX + 8*(14+1);
+ int*next2 = dataX + 8*(14+0);
+ for (px = 0 ; px < 8 ; px += 1) {
+ int val = 1*next2[px] + 4*next1[px] + 6*cur[px] + 4*prev1[px] + 1*prev2[px] +8;
+ data[px + 8*(py/2)] = val >> 4;
+ }
+ }
+ }
+ }
+}
+
+#else
+
+/*
+* These are simple-minded subsamples for convertion YUV444 to YUV42x.
+*/
+static void yuv444_to_yuv422_up4(jxr_image_t image)
+{
+ int mx;
+ for (mx = 0 ; mx < EXTENDED_WIDTH_BLOCKS(image); mx += 1) {
+ int ch;
+ for (ch = 1 ; ch < 3 ; ch += 1) {
+ int*data = MACROBLK_UP4(image,ch,0,mx).data;
+ int px, py;
+ for (py = 0 ; py < 16 ; py += 1) {
+ int*src = data + 16*py;
+ int*dst = data + 8*py;
+ for (px = 0 ; px < 16 ; px += 2) {
+ dst[px/2] = src[px+0];
+ }
+ }
+ }
+ }
+}
+
+static void yuv422_to_yuv420_up3(jxr_image_t image)
+{
+ int mx;
+ for (mx = 0 ; mx < EXTENDED_WIDTH_BLOCKS(image); mx += 1) {
+ int ch;
+ for (ch = 1 ; ch < 3 ; ch += 1) {
+ int*data = MACROBLK_UP3(image,ch,0,mx).data;
+ int px, py;
+ for (py = 0 ; py < 16 ; py += 2) {
+ int*src = data + 8*py;
+ int*dst = data + 8*py/2;
+ for (px = 0 ; px < 8 ; px += 1) {
+ dst[px] = src[px];
+ }
+ }
+ }
+ }
+}
+#endif
+
+/*
+* Shuffle a set of values that are in a single 16x16 raster block to
+* 16 4x4 blocks. The 4x4 blocks are the units that the PCT works on.
+*/
+static void block_shuffle444(int*data)
+{
+ int tmp[256];
+
+ int idx;
+ for (idx = 0 ; idx < 256 ; idx += 4) {
+ int blk = idx/16;
+ int mbx = blk%4;
+ int mby = blk/4;
+ int pix = idx%16;
+ int py = pix/4;
+
+ int ptr = 16*4*mby + 4*mbx + 16*py;
+ tmp[idx+0] = data[ptr+0];
+ tmp[idx+1] = data[ptr+1];
+ tmp[idx+2] = data[ptr+2];
+ tmp[idx+3] = data[ptr+3];
+ }
+
+ for (idx = 0 ; idx < 256 ; idx += 1)
+ data[idx] = tmp[idx];
+}
+
+static void block_shuffle422(int*data)
+{
+ int tmp[128];
+
+ int idx;
+ for (idx = 0 ; idx < 128 ; idx += 4) {
+ int blk = idx/16;
+ int mbx = blk%2;
+ int mby = blk/2;
+ int pix = idx%16;
+ int py = pix/4;
+
+ int ptr = 16*2*mby + 4*mbx + 8*py;
+ tmp[idx+0] = data[ptr+0];
+ tmp[idx+1] = data[ptr+1];
+ tmp[idx+2] = data[ptr+2];
+ tmp[idx+3] = data[ptr+3];
+ }
+
+ for (idx = 0 ; idx < 128 ; idx += 1)
+ data[idx] = tmp[idx];
+}
+
+static void block_shuffle420(int*data)
+{
+ int tmp[64];
+
+ int idx;
+ for (idx = 0 ; idx < 64 ; idx += 4) {
+ int blk = idx/16;
+ int mbx = blk%2;
+ int mby = blk/2;
+ int pix = idx%16;
+ int py = pix/4;
+
+ int ptr = 16*2*mby + 4*mbx + 8*py;
+ tmp[idx+0] = data[ptr+0];
+ tmp[idx+1] = data[ptr+1];
+ tmp[idx+2] = data[ptr+2];
+ tmp[idx+3] = data[ptr+3];
+ }
+
+ for (idx = 0 ; idx < 64 ; idx += 1)
+ data[idx] = tmp[idx];
+}
+
+static void collect_and_scale_up4(jxr_image_t image, int ty)
+{
+ int scale = image->scaled_flag? 3 : 0;
+ int bias;
+ int round;
+ int shift_bits = image->shift_bits;
+ int my;
+ int mx;
+ int ch;
+ int num_channels;
+
+ if (image->output_clr_fmt == JXR_OCF_RGBE) {
+ bias = 0;
+ round = image->scaled_flag? 3 : 0;
+ }
+ else {
+ switch (SOURCE_BITDEPTH(image)) {
+ case 0: /* BD1WHITE1 */
+ case 15: /* BD1BLACK1 */
+ bias = 0;
+ round = image->scaled_flag? 4 : 0;
+ break;
+ case 1: /* BD8 */
+ bias = 1 << 7;
+ round = image->scaled_flag? 3 : 0;
+ break;
+ case 2: /* BD16 */
+ bias = 1 << 15;
+ round = image->scaled_flag? 4 : 0;
+ break;
+ case 3: /* BD16S */
+ bias = 0;
+ round = image->scaled_flag? 3 : 0;
+ break;
+ case 4: /* BD16F */
+ bias = 0;
+ round = image->scaled_flag? 3 : 0;
+ break;
+ case 6: /* BD32S */
+ bias = 0;
+ round = image->scaled_flag? 3 : 0;
+ break;
+ case 7: /* BD32F */
+ bias = 0;
+ round = image->scaled_flag? 3 : 0;
+ break;
+ case 8: /* BD5 */
+ bias = 1 << 4;
+ round = image->scaled_flag? 3 : 0;
+ break;
+ case 9: /* BD10 */
+ bias = 1 << 9;
+ round = image->scaled_flag? 3 : 0;
+ break;
+ case 10: /* BD565 */
+ bias = 1 << 5;
+ round = image->scaled_flag? 3 : 0;
+ break;
+ default: /* RESERVED */
+ fprintf(stderr, "XXXX Don't know how to scale bit depth %d?\n", SOURCE_BITDEPTH(image));
+ bias = 0;
+ round = image->scaled_flag? 3 : 0;
+ break;
+ }
+ }
+
+ DEBUG("scale_and_emit_top: scale=%d, bias=%d, round=%d, shift_bits=%d\n",
+ scale, bias, round, shift_bits);
+
+ assert(image->num_channels > 0);
+
+ /* This function operates on a whole image (not tile) basis */
+ my = image->cur_my + image->tile_row_position[ty] + 4;
+ DEBUG("collect_and_scale_up4: Collect strip %d\n", my);
+
+ num_channels = image->num_channels;
+
+ if (ALPHACHANNEL_FLAG(image)) {
+ num_channels ++;
+ image->strip[image->num_channels].up4 = image->alpha->strip[0].up4;
+ }
+
+ for (mx = 0 ; mx < (int) EXTENDED_WIDTH_BLOCKS(image) ; mx += 1) {
+
+ /* Collect the data from the application. */
+ int buffer[17*256];
+ int jdx;
+ assert(image->num_channels <= 16);
+ image->inp_fun(image, mx, my, buffer);
+
+ /* Pad to the bottom by repeating the last pixel */
+ if ((my+1) == EXTENDED_HEIGHT_BLOCKS(image) && ((image->height1+image->window_extra_top+1) % 16 != 0)) {
+ int last_y = (image->height1 + image->window_extra_top) % 16;
+ int ydx;
+ for (ydx = last_y+1 ; ydx < 16 ; ydx += 1) {
+ int xdx;
+ for (xdx = 0 ; xdx < 16 ; xdx += 1) {
+ for (ch = 0 ; ch < num_channels ; ch += 1) {
+ int pad = buffer[(16*last_y + xdx)*num_channels + ch];
+ if ((16*mx + xdx) > (int) image->width1) {
+ int use_x = (image->width1 + image->window_extra_left) % 16;
+ pad = buffer[(16*last_y + use_x)*num_channels + ch];
+ }
+
+ buffer[(16*ydx + xdx)*num_channels + ch] = pad;
+ }
+ }
+ }
+ }
+
+ /* Pad to the right by repeating the last pixel */
+ if ((mx+1) == EXTENDED_WIDTH_BLOCKS(image) && ((image->width1+image->window_extra_left+1) % 16 != 0)) {
+ int last_x = (image->width1 + image->window_extra_left) % 16;
+ int ydx ;
+ for (ydx = 0; ydx < 16 ; ydx += 1) {
+ int xdx;
+ for (xdx = last_x+1 ; xdx < 16 ; xdx += 1) {
+ for (ch = 0 ; ch < num_channels ; ch += 1) {
+ int pad = buffer[(16*ydx + last_x)*num_channels + ch];
+ buffer[(16*ydx + xdx)*num_channels + ch] = pad;
+ }
+ }
+ }
+ }
+
+ /* And finally collect the strip data. */
+ /* image->alpha->strip[0].up4 == image->strip[image->num_channels].up4 !!! */
+ for (jdx = 0 ; jdx < 256 ; jdx += 1) {
+ int ch;
+ for (ch = 0 ; ch < num_channels ; ch += 1)
+ image->strip[ch].up4[mx].data[jdx] = buffer[jdx*num_channels + ch];
+ }
+
+#if defined(DETAILED_DEBUG) && 0
+ for (ch = 0 ; ch < num_channels ; ch += 1) {
+ DEBUG("image data mx=%3d my=%3d ch=%d:", mx, my, ch);
+ for (jdx = 0 ; jdx < 256 ; jdx += 1) {
+ if (jdx%16 == 0 && jdx != 0)
+ DEBUG("\n%*s", 30, "");
+ DEBUG(" %02x", image->strip[ch].up4[mx].data[jdx]);
+ }
+ DEBUG("\n");
+ }
+#endif
+
+ /* AddBias and ComputeScaling */
+ if (image->use_clr_fmt == 4 /*YUVK*/ && image->output_clr_fmt == JXR_OCF_CMYK) {
+ int*dp;
+ assert(image->num_channels == 4);
+ for (ch = 0 ; ch < 3 ; ch += 1) {
+ int jdx;
+ dp = image->strip[ch].up4[mx].data;
+ for (jdx = 0 ; jdx < 256 ; jdx += 1)
+ dp[jdx] = (dp[jdx] - (bias>>1)) << scale;
+ }
+ dp = image->strip[3].up4[mx].data;
+ for (jdx = 0 ; jdx < 256 ; jdx += 1)
+ dp[jdx] = (dp[jdx] + (bias>>1)) << scale;
+
+ if (num_channels == 5) { // for interleaved CMYKA, num_channels = 5 and image->num_channels = 4
+ dp = image->strip[4].up4[mx].data;
+ for (jdx = 0 ; jdx < 256 ; jdx += 1)
+ dp[jdx] = (dp[jdx] - bias) << scale;
+ }
+ } else {
+ for (ch = 0 ; ch < num_channels ; ch += 1) {
+ int*dp = image->strip[ch].up4[mx].data;
+ int jdx;
+ for (jdx = 0 ; jdx < 256 ; jdx += 1) {
+ dp[jdx] = (dp[jdx] - bias) << scale;
+ }
+ }
+ }
+ }
+
+ /* Transform the color space. */
+ switch (image->use_clr_fmt) {
+ case 0: /* YONLY */
+ break;
+ case 1: /* YUV420 */
+ if (image->output_clr_fmt == JXR_OCF_RGB) {
+ rgb_to_yuv444_up4(image);
+ yuv444_to_yuv422_up4(image);
+ /* Do yuv422_to_yuv420_up3 after further processing */
+ }
+ break;
+ case 2: /* YUV422 */
+ if (image->output_clr_fmt == JXR_OCF_RGB) {
+ rgb_to_yuv444_up4(image);
+ yuv444_to_yuv422_up4(image);
+ }
+ break;
+ case 3: /* YUV444 */
+ if (image->output_clr_fmt == JXR_OCF_RGB)
+ rgb_to_yuv444_up4(image);
+ break;
+ case 4: /* YUVK */
+ if (image->output_clr_fmt == JXR_OCF_CMYK)
+ cmyk_to_yuvk_up4(image);
+ break;
+ case 6: /* NCOMPONENT */
+ break;
+ }
+
+}
+
+static void scale_and_shuffle_up3(jxr_image_t image)
+{
+ int mx;
+ int my = image->cur_my + 3;
+ int ch;
+
+ /* Finish transform of the color space. */
+ switch (image->use_clr_fmt) {
+ case 0: /* YONLY */
+ break;
+ case 1: /* YUV420 */
+ if (image->output_clr_fmt == JXR_OCF_RGB)
+ yuv422_to_yuv420_up3(image);
+ break;
+ case 2: /* YUV422 */
+ break;
+ case 3: /* YUV444 */
+ break;
+ case 6: /* NCOMPONENT */
+ break;
+ }
+ for (mx = 0 ; mx < (int) EXTENDED_WIDTH_BLOCKS(image) ; mx += 1) {
+
+#if defined(DETAILED_DEBUG) && 1
+ int jdx;
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ int count = 256;
+ if (ch > 0 && image->use_clr_fmt==2/*YUV422*/)
+ count = 128;
+ if (ch > 0 && image->use_clr_fmt==1/*YUV420*/)
+ count = 64;
+
+ DEBUG("image yuv mx=%3d my=%3d ch=%d:", mx, my, ch);
+ for (jdx = 0 ; jdx < count ; jdx += 1) {
+ if (jdx%8 == 0 && jdx != 0)
+ DEBUG("\n%*s", 29, "");
+ DEBUG(" %08x", image->strip[ch].up3[mx].data[jdx]);
+ }
+ DEBUG("\n");
+ }
+#endif
+
+ /* shuffle the data into the internal format. */
+ block_shuffle444(image->strip[0].up3[mx].data);
+ for (ch = 1 ; ch < image->num_channels ; ch += 1) {
+ switch (image->use_clr_fmt) {
+ case 1: /* YUV420 */
+ block_shuffle420(image->strip[ch].up3[mx].data);
+ break;
+ case 2: /* YUV422 */
+ block_shuffle422(image->strip[ch].up3[mx].data);
+ break;
+ default:
+ block_shuffle444(image->strip[ch].up3[mx].data);
+ break;
+ }
+ }
+ }
+}
+
+static int*R2B(int*data, int x, int y)
+{
+ int bx = x/4;
+ int by = y/4;
+ int bl = by*4 + bx;
+ return data + bl*16 + 4*(y%4) + x%4;
+}
+
+static int*R2B42(int*data, int x, int y)
+{
+ int bx = x/4;
+ int by = y/4;
+ int bl = by*2 + bx;
+ return data + bl*16 + 4*(y%4) + x%4;
+}
+#define TOP_Y(y) ( y == image->tile_row_position[ty])
+#define BOTTOM_Y(y) ( y == image->tile_row_position[ty] + image->tile_row_height[ty] - 1)
+#define LEFT_X(idx) ( idx == 0)
+#define RIGHT_X(idx) ( idx == image->tile_column_width[tx] -1 )
+
+
+static void first_prefilter444_up2(jxr_image_t image, int ch, int ty)
+{
+ int tx = 0; /* XXXX */
+ int top_my = image->cur_my + 2;
+ int idx;
+ assert(ch == 0 || (image->use_clr_fmt != 2/*YUV422*/ && image->use_clr_fmt !=1/* YUV420*/));
+
+ if (top_my >= image->tile_row_height[ty])
+ top_my -= image->tile_row_height[ty++];
+ if (top_my >= image->tile_row_height[ty])
+ top_my -= image->tile_row_height[ty++];
+ top_my += image->tile_row_position[ty];
+
+ DEBUG("Pre Level2 for row %d\n", top_my);
+
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ int jdx;
+ /* Left edge */
+ if (tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*dp = MACROBLK_UP2(image,ch,tx,0).data;
+ for (jdx = 2 ; jdx < 14 ; jdx += 4) {
+ _jxr_4PreFilter(R2B(dp,0,jdx+0),R2B(dp,0,jdx+1),R2B(dp,0,jdx+2),R2B(dp,0,jdx+3));
+ _jxr_4PreFilter(R2B(dp,1,jdx+0),R2B(dp,1,jdx+1),R2B(dp,1,jdx+2),R2B(dp,1,jdx+3));
+ }
+ }
+
+ /* Right edge */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag){
+ int*dp = MACROBLK_UP2(image,ch,tx,image->tile_column_width[tx]-1).data;
+ for (jdx = 2 ; jdx < 14 ; jdx += 4) {
+ _jxr_4PreFilter(R2B(dp,14,jdx+0),R2B(dp,14,jdx+1),R2B(dp,14,jdx+2),R2B(dp,14,jdx+3));
+ _jxr_4PreFilter(R2B(dp,15,jdx+0),R2B(dp,15,jdx+1),R2B(dp,15,jdx+2),R2B(dp,15,jdx+3));
+ }
+ }
+
+ /* Top edge */
+ if(top_my == 0 || (image->disableTileOverlapFlag && TOP_Y(top_my) ))
+ {
+ /* If this is the very first strip of blocks, then process the
+ first two scan lines with the smaller 4Pre filter. */
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ int*dp = MACROBLK_UP2(image,ch,tx,idx).data;
+ _jxr_4PreFilter(R2B(dp, 2,0),R2B(dp, 3,0),R2B(dp, 4,0),R2B(dp, 5,0));
+ _jxr_4PreFilter(R2B(dp, 6,0),R2B(dp, 7,0),R2B(dp, 8,0),R2B(dp, 9,0));
+ _jxr_4PreFilter(R2B(dp,10,0),R2B(dp,11,0),R2B(dp,12,0),R2B(dp,13,0));
+
+ _jxr_4PreFilter(R2B(dp, 2,1),R2B(dp, 3,1),R2B(dp, 4,1),R2B(dp, 5,1));
+ _jxr_4PreFilter(R2B(dp, 6,1),R2B(dp, 7,1),R2B(dp, 8,1),R2B(dp, 9,1));
+ _jxr_4PreFilter(R2B(dp,10,1),R2B(dp,11,1),R2B(dp,12,1),R2B(dp,13,1));
+
+ /* Top edge across */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag) || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+ int*pp = MACROBLK_UP2(image,ch,tx,idx-1).data;
+ _jxr_4PreFilter(R2B(pp,14,0),R2B(pp,15,0),R2B(dp,0,0),R2B(dp,1,0));
+ _jxr_4PreFilter(R2B(pp,14,1),R2B(pp,15,1),R2B(dp,0,1),R2B(dp,1,1));
+ }
+ }
+
+ /* Top left corner */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP2(image,ch, tx, 0).data;
+ _jxr_4PreFilter(R2B(dp, 0,0),R2B(dp, 1,0),R2B(dp, 0,1),R2B(dp, 1,1));
+ }
+ /* Top right corner */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP2(image,ch,tx, image->tile_column_width[tx] - 1 ).data;
+ _jxr_4PreFilter(R2B(dp, 14,0),R2B(dp, 15,0),R2B(dp, 14,1),R2B(dp, 15,1));
+ }
+
+ }
+
+ /* Bottom edge */
+ if ((top_my+1) == (int) EXTENDED_HEIGHT_BLOCKS(image) || (image->disableTileOverlapFlag && BOTTOM_Y(top_my))) {
+
+ /* This is the last row, so there is no UP below
+ TOP. finish up with 4Pre filters. */
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ int*tp = MACROBLK_UP2(image,ch,tx,idx).data;
+
+ _jxr_4PreFilter(R2B(tp, 2,14),R2B(tp, 3,14),R2B(tp, 4,14),R2B(tp, 5,14));
+ _jxr_4PreFilter(R2B(tp, 6,14),R2B(tp, 7,14),R2B(tp, 8,14),R2B(tp, 9,14));
+ _jxr_4PreFilter(R2B(tp,10,14),R2B(tp,11,14),R2B(tp,12,14),R2B(tp,13,14));
+
+ _jxr_4PreFilter(R2B(tp, 2,15),R2B(tp, 3,15),R2B(tp, 4,15),R2B(tp, 5,15));
+ _jxr_4PreFilter(R2B(tp, 6,15),R2B(tp, 7,15),R2B(tp, 8,15),R2B(tp, 9,15));
+ _jxr_4PreFilter(R2B(tp,10,15),R2B(tp,11,15),R2B(tp,12,15),R2B(tp,13,15));
+
+ /* Bottom edge across */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag)
+ || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+ int*tn = MACROBLK_UP2(image,ch,tx,idx-1).data;
+ _jxr_4PreFilter(R2B(tn,14,14),R2B(tn,15,14),R2B(tp, 0,14),R2B(tp, 1,14));
+ _jxr_4PreFilter(R2B(tn,14,15),R2B(tn,15,15),R2B(tp, 0,15),R2B(tp, 1,15));
+ }
+ }
+
+ /* Bottom left corner */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP2(image,ch,tx,0).data;
+ _jxr_4PreFilter(R2B(dp, 0,14),R2B(dp, 1, 14),R2B(dp, 0,15),R2B(dp, 1, 15));
+ }
+ /* Bottom right corner */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP2(image,ch,tx, image->tile_column_width[tx] - 1 ).data;
+ _jxr_4PreFilter(R2B(dp, 14, 14),R2B(dp, 15, 14),R2B(dp, 14,15),R2B(dp, 15, 15));
+ }
+
+ }
+
+ for (idx = 0 ; idx < image->tile_column_width[tx] ; idx += 1) {
+ int jdx;
+
+ for (jdx = 2 ; jdx < 14 ; jdx += 4) {
+
+ int*dp = MACROBLK_UP2(image,ch,tx,idx).data;
+ /* Fully interior 4x4 filter blocks... */
+ _jxr_4x4PreFilter(R2B(dp, 2,jdx+0),R2B(dp, 3,jdx+0),R2B(dp, 4,jdx+0),R2B(dp, 5,jdx+0),
+ R2B(dp, 2,jdx+1),R2B(dp, 3,jdx+1),R2B(dp, 4,jdx+1),R2B(dp, 5,jdx+1),
+ R2B(dp, 2,jdx+2),R2B(dp, 3,jdx+2),R2B(dp, 4,jdx+2),R2B(dp, 5,jdx+2),
+ R2B(dp, 2,jdx+3),R2B(dp, 3,jdx+3),R2B(dp, 4,jdx+3),R2B(dp, 5,jdx+3));
+ _jxr_4x4PreFilter(R2B(dp, 6,jdx+0),R2B(dp, 7,jdx+0),R2B(dp, 8,jdx+0),R2B(dp, 9,jdx+0),
+ R2B(dp, 6,jdx+1),R2B(dp, 7,jdx+1),R2B(dp, 8,jdx+1),R2B(dp, 9,jdx+1),
+ R2B(dp, 6,jdx+2),R2B(dp, 7,jdx+2),R2B(dp, 8,jdx+2),R2B(dp, 9,jdx+2),
+ R2B(dp, 6,jdx+3),R2B(dp, 7,jdx+3),R2B(dp, 8,jdx+3),R2B(dp, 9,jdx+3));
+ _jxr_4x4PreFilter(R2B(dp,10,jdx+0),R2B(dp,11,jdx+0),R2B(dp,12,jdx+0),R2B(dp,13,jdx+0),
+ R2B(dp,10,jdx+1),R2B(dp,11,jdx+1),R2B(dp,12,jdx+1),R2B(dp,13,jdx+1),
+ R2B(dp,10,jdx+2),R2B(dp,11,jdx+2),R2B(dp,12,jdx+2),R2B(dp,13,jdx+2),
+ R2B(dp,10,jdx+3),R2B(dp,11,jdx+3),R2B(dp,12,jdx+3),R2B(dp,13,jdx+3));
+
+ if ( (image->tile_column_position[tx] + idx < EXTENDED_WIDTH_BLOCKS(image)-1 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && !RIGHT_X(idx))) {
+ /* 4x4 at the right */
+ int*np = MACROBLK_UP2(image,ch,tx,idx+1).data;
+
+ _jxr_4x4PreFilter(R2B(dp,14,jdx+0),R2B(dp,15,jdx+0),R2B(np, 0,jdx+0),R2B(np, 1,jdx+0),
+ R2B(dp,14,jdx+1),R2B(dp,15,jdx+1),R2B(np, 0,jdx+1),R2B(np, 1,jdx+1),
+ R2B(dp,14,jdx+2),R2B(dp,15,jdx+2),R2B(np, 0,jdx+2),R2B(np, 1,jdx+2),
+ R2B(dp,14,jdx+3),R2B(dp,15,jdx+3),R2B(np, 0,jdx+3),R2B(np, 1,jdx+3));
+ }
+ }
+
+ if ((top_my+1) < (int) EXTENDED_HEIGHT_BLOCKS(image)) {
+
+ int*dp = MACROBLK_UP2(image,ch,tx,idx).data;
+ int*up = MACROBLK_UP3(image,ch,tx,idx).data;
+
+ if ((tx == 0 && idx==0 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && LEFT_X(idx) && !BOTTOM_Y(top_my))) {
+ /* Across vertical blocks, left edge */
+ _jxr_4PreFilter(R2B(dp,0,14),R2B(dp,0,15),R2B(up,0,0),R2B(up,0,1));
+ _jxr_4PreFilter(R2B(dp,1,14),R2B(dp,1,15),R2B(up,1,0),R2B(up,1,1));
+ }
+ if((!image->disableTileOverlapFlag) || (image->disableTileOverlapFlag && !BOTTOM_Y(top_my)))
+ {
+ /* 4x4 bottom */
+ _jxr_4x4PreFilter(R2B(dp, 2,14),R2B(dp, 3,14),R2B(dp, 4,14),R2B(dp, 5,14),
+ R2B(dp, 2,15),R2B(dp, 3,15),R2B(dp, 4,15),R2B(dp, 5,15),
+ R2B(up, 2, 0),R2B(up, 3, 0),R2B(up, 4, 0),R2B(up, 5, 0),
+ R2B(up, 2, 1),R2B(up, 3, 1),R2B(up, 4, 1),R2B(up, 5, 1));
+ _jxr_4x4PreFilter(R2B(dp, 6,14),R2B(dp, 7,14),R2B(dp, 8,14),R2B(dp, 9,14),
+ R2B(dp, 6,15),R2B(dp, 7,15),R2B(dp, 8,15),R2B(dp, 9,15),
+ R2B(up, 6, 0),R2B(up, 7, 0),R2B(up, 8, 0),R2B(up, 9, 0),
+ R2B(up, 6, 1),R2B(up, 7, 1),R2B(up, 8, 1),R2B(up, 9, 1));
+ _jxr_4x4PreFilter(R2B(dp,10,14),R2B(dp,11,14),R2B(dp,12,14),R2B(dp,13,14),
+ R2B(dp,10,15),R2B(dp,11,15),R2B(dp,12,15),R2B(dp,13,15),
+ R2B(up,10, 0),R2B(up,11, 0),R2B(up,12, 0),R2B(up,13, 0),
+ R2B(up,10, 1),R2B(up,11, 1),R2B(up,12, 1),R2B(up,13, 1));
+ }
+
+ if (((image->tile_column_position[tx] + idx < EXTENDED_WIDTH_BLOCKS(image)-1) && !image->disableTileOverlapFlag ) ||
+ ( image->disableTileOverlapFlag && !RIGHT_X(idx) && !BOTTOM_Y(top_my) )
+ ) {
+ /* Blocks that span the MB to the right */
+ int*dn = MACROBLK_UP2(image,ch,tx,idx+1).data;
+ int*un = MACROBLK_UP3(image,ch,tx,idx+1).data;
+
+ /* 4x4 on right, below, below-right */
+ _jxr_4x4PreFilter(R2B(dp,14,14),R2B(dp,15,14),R2B(dn, 0,14),R2B(dn, 1,14),
+ R2B(dp,14,15),R2B(dp,15,15),R2B(dn, 0,15),R2B(dn, 1,15),
+ R2B(up,14, 0),R2B(up,15, 0),R2B(un, 0, 0),R2B(un, 1, 0),
+ R2B(up,14, 1),R2B(up,15, 1),R2B(un, 0, 1),R2B(un, 1, 1));
+ }
+ if((image->tile_column_position[tx] + idx == (int) EXTENDED_WIDTH_BLOCKS(image)-1 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && RIGHT_X(idx) && !BOTTOM_Y(top_my)))
+ {
+ /* Across vertical blocks, right edge */
+ _jxr_4PreFilter(R2B(dp,14,14),R2B(dp,14,15),R2B(up,14,0),R2B(up,14,1));
+ _jxr_4PreFilter(R2B(dp,15,14),R2B(dp,15,15),R2B(up,15,0),R2B(up,15,1));
+ }
+ }
+ }
+ }
+}
+
+static void first_prefilter422_up2(jxr_image_t image, int ch, int ty)
+{
+ int tx = 0; /* XXXX */
+
+ int top_my = image->cur_my + 2;
+ int idx;
+ assert(ch > 0 && image->use_clr_fmt == 2/*YUV422*/);
+ assert(top_my >= 0 );
+
+ if (top_my >= image->tile_row_height[ty])
+ top_my -= image->tile_row_height[ty++];
+ if (top_my >= image->tile_row_height[ty])
+ top_my -= image->tile_row_height[ty++];
+ top_my += image->tile_row_position[ty];
+
+ DEBUG("Pre Level2 for row %d\n", top_my);
+
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ /* Left edge */
+ if (tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*dp = MACROBLK_UP2(image,ch,tx,0).data;
+ _jxr_4PreFilter(R2B42(dp,0, 2),R2B42(dp,0, 3),R2B42(dp,0, 4),R2B42(dp,0, 5));
+ _jxr_4PreFilter(R2B42(dp,0, 6),R2B42(dp,0, 7),R2B42(dp,0, 8),R2B42(dp,0, 9));
+ _jxr_4PreFilter(R2B42(dp,0,10),R2B42(dp,0,11),R2B42(dp,0,12),R2B42(dp,0,13));
+
+ _jxr_4PreFilter(R2B42(dp,1, 2),R2B42(dp,1, 3),R2B42(dp,1, 4),R2B42(dp,1, 5));
+ _jxr_4PreFilter(R2B42(dp,1, 6),R2B42(dp,1, 7),R2B42(dp,1, 8),R2B42(dp,1, 9));
+ _jxr_4PreFilter(R2B42(dp,1,10),R2B42(dp,1,11),R2B42(dp,1,12),R2B42(dp,1,13));
+ }
+
+ /* Right edge */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag){
+
+ int*dp = MACROBLK_UP2(image,ch,tx,image->tile_column_width[tx]-1).data;
+ _jxr_4PreFilter(R2B42(dp,6,2),R2B42(dp,6,3),R2B42(dp,6,4),R2B42(dp,6,5));
+ _jxr_4PreFilter(R2B42(dp,7,2),R2B42(dp,7,3),R2B42(dp,7,4),R2B42(dp,7,5));
+
+ _jxr_4PreFilter(R2B42(dp,6,6),R2B42(dp,6,7),R2B42(dp,6,8),R2B42(dp,6,9));
+ _jxr_4PreFilter(R2B42(dp,7,6),R2B42(dp,7,7),R2B42(dp,7,8),R2B42(dp,7,9));
+
+ _jxr_4PreFilter(R2B42(dp,6,10),R2B42(dp,6,11),R2B42(dp,6,12),R2B42(dp,6,13));
+ _jxr_4PreFilter(R2B42(dp,7,10),R2B42(dp,7,11),R2B42(dp,7,12),R2B42(dp,7,13));
+ }
+
+ /* Top edge */
+ if(top_my == 0 || (image->disableTileOverlapFlag && TOP_Y(top_my) ))
+ {
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ int*dp = MACROBLK_UP2(image,ch,tx,idx).data;
+
+ _jxr_4PreFilter(R2B42(dp, 2,0),R2B42(dp, 3,0),R2B42(dp, 4,0),R2B42(dp, 5,0));
+ _jxr_4PreFilter(R2B42(dp, 2,1),R2B42(dp, 3,1),R2B42(dp, 4,1),R2B42(dp, 5,1));
+
+ /* Top across for soft tiles */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag) || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+ int*pp = MACROBLK_UP2(image,ch,tx,idx-1).data;
+ _jxr_4PreFilter(R2B42(pp,6,0),R2B42(pp,7,0),R2B(dp,0,0),R2B42(dp,1,0));
+ _jxr_4PreFilter(R2B42(pp,6,1),R2B42(pp,7,1),R2B(dp,0,1),R2B42(dp,1,1));
+ }
+ }
+
+ /* Top left corner */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP2(image,ch, tx, 0).data;
+ _jxr_4PreFilter(R2B42(dp,0,0),R2B42(dp,1,0),R2B42(dp,0,1),R2B42(dp,1,1));
+ }
+ /* Top right corner */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP2(image,ch,tx, image->tile_column_width[tx] - 1 ).data;
+ _jxr_4PreFilter(R2B42(dp,6,0),R2B42(dp,7,0),R2B42(dp,6,1),R2B42(dp,7,1));
+ }
+ }
+
+ /* Bottom edge */
+ if ((top_my+1) == (int) EXTENDED_HEIGHT_BLOCKS(image) || (image->disableTileOverlapFlag && BOTTOM_Y(top_my))) {
+
+ /* This is the last row, so there is no UP below
+ TOP. finish up with 4Pre filters. */
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ int*tp = MACROBLK_UP2(image,ch,tx,idx).data;
+
+ _jxr_4PreFilter(R2B42(tp,2,14),R2B42(tp,3,14),R2B42(tp,4,14),R2B42(tp,5,14));
+ _jxr_4PreFilter(R2B42(tp,2,15),R2B42(tp,3,15),R2B42(tp,4,15),R2B42(tp,5,15));
+
+ /* Bottom across for soft tiles */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag)
+ || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+ /* Blocks that span the MB to the right */
+ int*tn = MACROBLK_UP2(image,ch,tx,idx-1).data;
+ _jxr_4PreFilter(R2B42(tn,6,14),R2B42(tn,7,14),R2B42(tp,0,14),R2B42(tp,1,14));
+ _jxr_4PreFilter(R2B42(tn,6,15),R2B42(tn,7,15),R2B42(tp,0,15),R2B42(tp,1,15));
+ }
+ }
+
+ /* Bottom left corner */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP2(image,ch,tx,0).data;
+ _jxr_4PreFilter(R2B42(dp,0,14),R2B42(dp,1,14),R2B42(dp,0,15),R2B42(dp,1,15));
+ }
+ /* Bottom right corner */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP2(image,ch,tx, image->tile_column_width[tx] - 1 ).data;
+ _jxr_4PreFilter(R2B42(dp,6,14),R2B42(dp,7,14),R2B42(dp,6,15),R2B42(dp,7,15));
+ }
+ }
+
+ for (idx = 0 ; idx < image->tile_column_width[tx] ; idx += 1) {
+
+ int*dp = MACROBLK_UP2(image,ch,tx,idx).data;
+
+ /* Fully interior 4x4 filter blocks... */
+ _jxr_4x4PreFilter(R2B42(dp,2,2),R2B42(dp,3,2),R2B42(dp,4,2),R2B42(dp,5,2),
+ R2B42(dp,2,3),R2B42(dp,3,3),R2B42(dp,4,3),R2B42(dp,5,3),
+ R2B42(dp,2,4),R2B42(dp,3,4),R2B42(dp,4,4),R2B42(dp,5,4),
+ R2B42(dp,2,5),R2B42(dp,3,5),R2B42(dp,4,5),R2B42(dp,5,5));
+
+ _jxr_4x4PreFilter(R2B42(dp,2,6),R2B42(dp,3,6),R2B42(dp,4,6),R2B42(dp,5,6),
+ R2B42(dp,2,7),R2B42(dp,3,7),R2B42(dp,4,7),R2B42(dp,5,7),
+ R2B42(dp,2,8),R2B42(dp,3,8),R2B42(dp,4,8),R2B42(dp,5,8),
+ R2B42(dp,2,9),R2B42(dp,3,9),R2B42(dp,4,9),R2B42(dp,5,9));
+
+ _jxr_4x4PreFilter(R2B42(dp,2,10),R2B42(dp,3,10),R2B42(dp,4,10),R2B42(dp,5,10),
+ R2B42(dp,2,11),R2B42(dp,3,11),R2B42(dp,4,11),R2B42(dp,5,11),
+ R2B42(dp,2,12),R2B42(dp,3,12),R2B42(dp,4,12),R2B42(dp,5,12),
+ R2B42(dp,2,13),R2B42(dp,3,13),R2B42(dp,4,13),R2B42(dp,5,13));
+
+ if ( (image->tile_column_position[tx] + idx < EXTENDED_WIDTH_BLOCKS(image)-1 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && !RIGHT_X(idx))) {
+ /* Blocks that span the MB to the right */
+ int*np = MACROBLK_UP2(image,ch,tx,idx+1).data;
+ _jxr_4x4PreFilter(R2B42(dp,6,2),R2B42(dp,7,2),R2B42(np,0,2),R2B42(np,1,2),
+ R2B42(dp,6,3),R2B42(dp,7,3),R2B42(np,0,3),R2B42(np,1,3),
+ R2B42(dp,6,4),R2B42(dp,7,4),R2B42(np,0,4),R2B42(np,1,4),
+ R2B42(dp,6,5),R2B42(dp,7,5),R2B42(np,0,5),R2B42(np,1,5));
+
+ _jxr_4x4PreFilter(R2B42(dp,6,6),R2B42(dp,7,6),R2B42(np,0,6),R2B42(np,1,6),
+ R2B42(dp,6,7),R2B42(dp,7,7),R2B42(np,0,7),R2B42(np,1,7),
+ R2B42(dp,6,8),R2B42(dp,7,8),R2B42(np,0,8),R2B42(np,1,8),
+ R2B42(dp,6,9),R2B42(dp,7,9),R2B42(np,0,9),R2B42(np,1,9));
+
+ _jxr_4x4PreFilter(R2B42(dp,6,10),R2B42(dp,7,10),R2B42(np,0,10),R2B42(np,1,10),
+ R2B42(dp,6,11),R2B42(dp,7,11),R2B42(np,0,11),R2B42(np,1,11),
+ R2B42(dp,6,12),R2B42(dp,7,12),R2B42(np,0,12),R2B42(np,1,12),
+ R2B42(dp,6,13),R2B42(dp,7,13),R2B42(np,0,13),R2B42(np,1,13));
+ }
+
+ if ((top_my+1) < (int) EXTENDED_HEIGHT_BLOCKS(image)) {
+
+ /* Blocks that MB below */
+ int*dp = MACROBLK_UP2(image,ch,tx,idx).data;
+ int*up = MACROBLK_UP3(image,ch,tx,idx).data;
+
+ if ((tx == 0 && idx==0 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && LEFT_X(idx) && !BOTTOM_Y(top_my))) {
+ _jxr_4PreFilter(R2B42(dp,0,14),R2B42(dp,0,15),R2B42(up,0,0),R2B42(up,0,1));
+ _jxr_4PreFilter(R2B42(dp,1,14),R2B42(dp,1,15),R2B42(up,1,0),R2B42(up,1,1));
+ }
+ if((!image->disableTileOverlapFlag) || (image->disableTileOverlapFlag && !BOTTOM_Y(top_my)))
+ {
+ _jxr_4x4PreFilter(R2B42(dp,2,14),R2B42(dp,3,14),R2B42(dp,4,14),R2B42(dp,5,14),
+ R2B42(dp,2,15),R2B42(dp,3,15),R2B42(dp,4,15),R2B42(dp,5,15),
+ R2B42(up,2, 0),R2B42(up,3, 0),R2B42(up,4, 0),R2B42(up,5, 0),
+ R2B42(up,2, 1),R2B42(up,3, 1),R2B42(up,4, 1),R2B42(up,5, 1));
+
+ }
+
+ if (((image->tile_column_position[tx] + idx < EXTENDED_WIDTH_BLOCKS(image)-1) && !image->disableTileOverlapFlag ) ||
+ ( image->disableTileOverlapFlag && !RIGHT_X(idx) && !BOTTOM_Y(top_my) )
+ ) {
+ /* Blocks that span the MB to the right, below, below-right */
+ int*dn = MACROBLK_UP2(image,ch,tx,idx+1).data;
+ int*un = MACROBLK_UP3(image,ch,tx,idx+1).data;
+
+ _jxr_4x4PreFilter(R2B42(dp,6,14),R2B42(dp,7,14),R2B42(dn,0,14),R2B42(dn,1,14),
+ R2B42(dp,6,15),R2B42(dp,7,15),R2B42(dn,0,15),R2B42(dn,1,15),
+ R2B42(up,6, 0),R2B42(up,7, 0),R2B42(un,0, 0),R2B42(un,1, 0),
+ R2B42(up,6, 1),R2B42(up,7, 1),R2B42(un,0, 1),R2B42(un,1, 1));
+ }
+ if((image->tile_column_position[tx] + idx == (int) EXTENDED_WIDTH_BLOCKS(image)-1 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && RIGHT_X(idx) && !BOTTOM_Y(top_my)))
+ {
+ _jxr_4PreFilter(R2B42(dp,6,14),R2B42(dp,6,15),R2B42(up,6,0),R2B42(up,6,1));
+ _jxr_4PreFilter(R2B42(dp,7,14),R2B42(dp,7,15),R2B42(up,7,0),R2B42(up,7,1));
+ }
+ }
+ }
+ }
+}
+
+static void first_prefilter420_up2(jxr_image_t image, int ch, int ty)
+{
+ int tx = 0; /* XXXX */
+ int top_my = image->cur_my + 2;
+ int idx;
+ assert(ch > 0 && image->use_clr_fmt == 1/*YUV420*/);
+
+ if (top_my >= image->tile_row_height[ty])
+ top_my -= image->tile_row_height[ty++];
+ if (top_my >= image->tile_row_height[ty])
+ top_my -= image->tile_row_height[ty++];
+ top_my += image->tile_row_position[ty];
+
+ DEBUG("Pre Level2 (YUV420) for row %d\n", top_my);
+
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+
+ /* Left edge */
+ if (tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*dp = MACROBLK_UP2(image,ch,tx,0).data;
+ _jxr_4PreFilter(R2B42(dp,0,2),R2B42(dp,0,3),R2B42(dp,0,4),R2B42(dp,0,5));
+ _jxr_4PreFilter(R2B42(dp,1,2),R2B42(dp,1,3),R2B42(dp,1,4),R2B42(dp,1,5));
+ }
+
+ /* Right edge */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag){
+ int*dp = MACROBLK_UP2(image,ch,tx,image->tile_column_width[tx]-1).data;
+ _jxr_4PreFilter(R2B42(dp,6,2),R2B42(dp,6,3),R2B42(dp,6,4),R2B42(dp,6,5));
+ _jxr_4PreFilter(R2B42(dp,7,2),R2B42(dp,7,3),R2B42(dp,7,4),R2B42(dp,7,5));
+ }
+
+ /* Top edge */
+ if(top_my == 0 || (image->disableTileOverlapFlag && TOP_Y(top_my) ))
+ {
+ /* If this is the very first strip of blocks, then process the
+ first two scan lines with the smaller 4Pre filter. */
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ int*dp = MACROBLK_UP2(image,ch,tx,idx).data;
+ _jxr_4PreFilter(R2B42(dp, 2,0),R2B42(dp, 3,0),R2B42(dp, 4,0),R2B42(dp, 5,0));
+ _jxr_4PreFilter(R2B42(dp, 2,1),R2B42(dp, 3,1),R2B42(dp, 4,1),R2B42(dp, 5,1));
+ /* Top edge across */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag) || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+ int*pp = MACROBLK_UP2(image,ch,tx,idx-1).data;
+ _jxr_4PreFilter(R2B42(pp,6,0),R2B42(pp,7,0),R2B(dp,0,0),R2B42(dp,1,0));
+ _jxr_4PreFilter(R2B42(pp,6,1),R2B42(pp,7,1),R2B(dp,0,1),R2B42(dp,1,1));
+ }
+ }
+
+ /* Top left corner */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP2(image,ch,tx,0).data;
+ _jxr_4PreFilter(R2B42(dp, 0,0),R2B42(dp, 1, 0),R2B42(dp, 0 ,1),R2B42(dp, 1,1));
+ }
+ /* Top right corner */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP2(image,ch,tx, image->tile_column_width[tx] - 1 ).data;
+ _jxr_4PreFilter(R2B42(dp, 6,0),R2B42(dp, 7,0),R2B42(dp, 6,1),R2B42(dp, 7,1));;
+ }
+
+ }
+
+ /* Bottom edge */
+ if ((top_my+1) == (int) EXTENDED_HEIGHT_BLOCKS(image) || (image->disableTileOverlapFlag && BOTTOM_Y(top_my))) {
+
+ /* This is the last row, so there is no UP below
+ TOP. finish up with 4Pre filters. */
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ int*tp = MACROBLK_UP2(image,ch,tx,idx).data;
+
+ _jxr_4PreFilter(R2B42(tp,2,6),R2B42(tp,3,6),R2B42(tp,4,6),R2B42(tp,5,6));
+ _jxr_4PreFilter(R2B42(tp,2,7),R2B42(tp,3,7),R2B42(tp,4,7),R2B42(tp,5,7));
+
+
+ /* Bottom edge across */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag)
+ || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+ int*tn = MACROBLK_UP2(image,ch,tx,idx-1).data;
+ _jxr_4PreFilter(R2B42(tn,6,6),R2B42(tn,7,6),R2B42(tp,0,6),R2B42(tp,1,6));
+ _jxr_4PreFilter(R2B42(tn,6,7),R2B42(tn,7,7),R2B42(tp,0,7),R2B42(tp,1,7));
+ }
+ }
+
+ /* Bottom left corner */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP2(image,ch,tx,0).data;
+ _jxr_4PreFilter(R2B42(dp, 0,6),R2B42(dp, 1, 6),R2B42(dp, 0,7),R2B42(dp, 1, 7));
+ }
+
+ /* Bottom right corner */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *dp = MACROBLK_UP2(image,ch,tx, image->tile_column_width[tx] - 1 ).data;
+ _jxr_4PreFilter(R2B42(dp, 6, 6),R2B42(dp, 7, 6),R2B42(dp, 6, 7),R2B42(dp, 7, 7));
+ }
+ }
+
+ for (idx = 0 ; idx < image->tile_column_width[tx] ; idx += 1) {
+
+ int*dp = MACROBLK_UP2(image,ch,tx,idx).data;
+ int*up = MACROBLK_UP3(image,ch,tx,idx).data;
+
+ /* Fully interior 4x4 filter blocks... */
+ _jxr_4x4PreFilter(R2B42(dp,2,2),R2B42(dp,3,2),R2B42(dp,4,2),R2B42(dp,5,2),
+ R2B42(dp,2,3),R2B42(dp,3,3),R2B42(dp,4,3),R2B42(dp,5,3),
+ R2B42(dp,2,4),R2B42(dp,3,4),R2B42(dp,4,4),R2B42(dp,5,4),
+ R2B42(dp,2,5),R2B42(dp,3,5),R2B42(dp,4,5),R2B42(dp,5,5));
+
+ if ( (image->tile_column_position[tx] + idx < EXTENDED_WIDTH_BLOCKS(image)-1 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && !RIGHT_X(idx)))
+ {
+ /* 4x4 at the right */
+ int*np = MACROBLK_UP2(image,ch,tx,idx+1).data;
+
+ _jxr_4x4PreFilter(R2B42(dp,6,2),R2B42(dp,7,2),R2B42(np,0,2),R2B42(np,1,2),
+ R2B42(dp,6,3),R2B42(dp,7,3),R2B42(np,0,3),R2B42(np,1,3),
+ R2B42(dp,6,4),R2B42(dp,7,4),R2B42(np,0,4),R2B42(np,1,4),
+ R2B42(dp,6,5),R2B42(dp,7,5),R2B42(np,0,5),R2B42(np,1,5));
+ }
+
+ if ((top_my+1) < (int) EXTENDED_HEIGHT_BLOCKS(image)) {
+
+ int*dp = MACROBLK_UP2(image,ch,tx,idx).data;
+ int*up = MACROBLK_UP3(image,ch,tx,idx).data;
+
+ if ((tx == 0 && idx==0 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && LEFT_X(idx) && !BOTTOM_Y(top_my))) {
+ /* Across vertical blocks, left edge */
+ _jxr_4PreFilter(R2B42(dp,0,6),R2B42(dp,0,7),R2B42(up,0,0),R2B42(up,0,1));
+ _jxr_4PreFilter(R2B42(dp,1,6),R2B42(dp,1,7),R2B42(up,1,0),R2B42(up,1,1));
+ }
+ if((!image->disableTileOverlapFlag) || (image->disableTileOverlapFlag && !BOTTOM_Y(top_my)))
+ {
+ /* 4x4 straddling lower MB */
+ _jxr_4x4PreFilter(R2B42(dp,2,6),R2B42(dp,3,6),R2B42(dp,4,6),R2B42(dp,5,6),
+ R2B42(dp,2,7),R2B42(dp,3,7),R2B42(dp,4,7),R2B42(dp,5,7),
+ R2B42(up,2,0),R2B42(up,3,0),R2B42(up,4,0),R2B42(up,5,0),
+ R2B42(up,2,1),R2B42(up,3,1),R2B42(up,4,1),R2B42(up,5,1));
+ }
+
+ if (((image->tile_column_position[tx] + idx < EXTENDED_WIDTH_BLOCKS(image)-1) && !image->disableTileOverlapFlag ) ||
+ ( image->disableTileOverlapFlag && !RIGHT_X(idx) && !BOTTOM_Y(top_my) )
+ ) {
+ /* Blocks that span the MB to the right */
+ int*dn = MACROBLK_UP2(image,ch,tx,idx+1).data;
+ int*un = MACROBLK_UP3(image,ch,tx,idx+1).data;
+
+ /* 4x4 right, below, below-right */
+ _jxr_4x4PreFilter(R2B42(dp,6,6),R2B42(dp,7,6),R2B42(dn,0,6),R2B42(dn,1,6),
+ R2B42(dp,6,7),R2B42(dp,7,7),R2B42(dn,0,7),R2B42(dn,1,7),
+ R2B42(up,6,0),R2B42(up,7,0),R2B42(un,0,0),R2B42(un,1,0),
+ R2B42(up,6,1),R2B42(up,7,1),R2B42(un,0,1),R2B42(un,1,1));
+ }
+ if((image->tile_column_position[tx] + idx == (int) EXTENDED_WIDTH_BLOCKS(image)-1 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && RIGHT_X(idx) && !BOTTOM_Y(top_my)))
+ {
+ /* Across vertical blocks, right edge */
+ _jxr_4PreFilter(R2B42(dp,6,6),R2B42(dp,6,7),R2B42(up,6,0),R2B42(up,6,1));
+ _jxr_4PreFilter(R2B42(dp,7,6),R2B42(dp,7,7),R2B42(up,7,0),R2B42(up,7,1));
+ }
+ }
+ }
+ }
+}
+
+static void first_prefilter_up2(jxr_image_t image, int ty)
+{
+ int ch;
+ first_prefilter444_up2(image, 0, ty);
+ switch (image->use_clr_fmt) {
+ case 0:
+ assert(image->num_channels == 1);
+ break;
+ case 1:/*YUV420*/
+ first_prefilter420_up2(image, 1, ty);
+ first_prefilter420_up2(image, 2, ty);
+ break;
+ case 2:/*YUV422*/
+ first_prefilter422_up2(image, 1, ty);
+ first_prefilter422_up2(image, 2, ty);
+ break;
+ default:
+ for (ch = 1 ; ch < image->num_channels ; ch += 1)
+ first_prefilter444_up2(image, ch, ty);
+ break;
+ }
+}
+
+static void PCT_stage2_up1(jxr_image_t image, int ch, int ty)
+{
+ int tx = 0;
+ int use_my = image->cur_my + 1;
+ int mx;
+ int dc_quant;
+ int dclp_count;
+
+ /* make adjustments based on tiling */
+ if (use_my == image->tile_row_height[ty]) {
+ ty += 1;
+ use_my = 0;
+ }
+
+ dclp_count = 16;
+ if (ch>0 && image->use_clr_fmt == 2/*YUV422*/)
+ dclp_count = 8;
+ else if (ch>0 && image->use_clr_fmt == 1/*YUV420*/)
+ dclp_count = 4;
+
+ dc_quant = w_guess_dc_quant(image, ch, tx, ty);
+ dc_quant = _jxr_quant_map(image, dc_quant, ch==0? 1 : 0/* iShift for YONLY */);
+ assert(dc_quant > 0);
+
+ for (mx = 0 ; mx < (int) EXTENDED_WIDTH_BLOCKS(image) ; mx += 1) {
+ int jdx;
+ int lp_quant;
+
+ if (ch > 0 && image->use_clr_fmt == 1/*YUV420*/) {
+
+ /* Scale up the chroma channel */
+ if (image->scaled_flag) {
+ for (jdx = 0 ; jdx < 4 ; jdx += 1) {
+ int val = image->strip[ch].up1[mx].data[jdx];
+ val = _jxr_floor_div2(val);
+ image->strip[ch].up1[mx].data[jdx] = val;
+ }
+ }
+
+ _jxr_InvPermute2pt(image->strip[ch].up1[mx].data+1,
+ image->strip[ch].up1[mx].data+2);
+ _jxr_2x2IPCT(image->strip[ch].up1[mx].data+0);
+
+ } else if (ch > 0 && image->use_clr_fmt == 2/*YUV422*/) {
+
+#if defined(DETAILED_DEBUG) && 1
+ DEBUG(" DC/LP scaled_flag=%d\n", image->scaled_flag);
+ {
+ DEBUG(" DC/LP (strip=%3d, mbx=%4d, ch=%d) Pre-PCT:", use_my, mx, ch);
+ DEBUG(" 0x%08x", MACROBLK_UP_DC(image,ch,tx,mx));
+ for (jdx = 0; jdx < 7 ; jdx += 1) {
+ DEBUG(" 0x%08x", MACROBLK_UP_LP(image,ch,tx,mx,jdx));
+ if ((jdx+1)%4 == 3 && jdx != 6)
+ DEBUG("\n%*s:", 43, "");
+ }
+ DEBUG("\n");
+ }
+#endif
+ /* Scale up the chroma channel */
+ if (image->scaled_flag) {
+ for (jdx = 0 ; jdx < 8 ; jdx += 1) {
+ int val = image->strip[ch].up1[mx].data[jdx];
+ val = _jxr_floor_div2(val);
+ image->strip[ch].up1[mx].data[jdx] = val;
+ }
+ }
+#if defined(DETAILED_DEBUG) && 1
+ {
+ DEBUG(" DC/LP (strip=%3d, mbx=%4d, ch=%d) scaled :", use_my, mx, ch);
+ DEBUG(" 0x%08x", MACROBLK_UP_DC(image,ch,tx,mx));
+ for (jdx = 0; jdx < 7 ; jdx += 1) {
+ DEBUG(" 0x%08x", MACROBLK_UP_LP(image,ch,tx,mx,jdx));
+ if ((jdx+1)%4 == 3 && jdx != 6)
+ DEBUG("\n%*s:", 43, "");
+ }
+ DEBUG("\n");
+ }
+#endif
+
+ /* The InvPermute2pt and FwdPermute2pt are identical */
+ _jxr_InvPermute2pt(image->strip[ch].up1[mx].data+1,
+ image->strip[ch].up1[mx].data+2);
+ _jxr_InvPermute2pt(image->strip[ch].up1[mx].data+5,
+ image->strip[ch].up1[mx].data+6);
+ /* The 2x2PCT and 2x2IPCT are identical */
+ _jxr_2x2IPCT(image->strip[ch].up1[mx].data+0);
+ _jxr_2x2IPCT(image->strip[ch].up1[mx].data+4);
+
+ _jxr_2ptFwdT(image->strip[ch].up1[mx].data+0,
+ image->strip[ch].up1[mx].data+4);
+
+#if defined(DETAILED_DEBUG) && 1
+ DEBUG(" DC/LP scaled_flag=%d\n", image->scaled_flag);
+ {
+ DEBUG(" DC/LP (strip=%3d, mbx=%4d, ch=%d) Post-PCT:", use_my, mx, ch);
+ DEBUG(" 0x%08x", MACROBLK_UP_DC(image,ch,tx,mx));
+ for (jdx = 0; jdx < 7 ; jdx += 1) {
+ DEBUG(" 0x%08x", MACROBLK_UP_LP(image,ch,tx,mx,jdx));
+ if ((jdx+1)%4 == 3 && jdx != 6)
+ DEBUG("\n%*s:", 44, "");
+ }
+ DEBUG("\n");
+ }
+#endif
+
+ } else {
+#if defined(DETAILED_DEBUG) && 1
+ {
+ DEBUG(" DC/LP (strip=%3d, mbx=%4d, ch=%d) Pre-PCT:", use_my, mx, ch);
+ DEBUG(" 0x%08x", MACROBLK_UP_DC(image,ch,tx,mx));
+ for (jdx = 0; jdx < 15 ; jdx += 1) {
+ DEBUG(" 0x%08x", MACROBLK_UP_LP(image,ch,tx,mx,jdx));
+ if ((jdx+1)%4 == 3 && jdx != 14)
+ DEBUG("\n%*s:", 43, "");
+ }
+ DEBUG("\n");
+ }
+#endif
+ /* Scale up the chroma channel */
+ if (ch > 0 && image->scaled_flag) {
+ for (jdx = 0 ; jdx < 16 ; jdx += 1) {
+ int val = image->strip[ch].up1[mx].data[jdx];
+ val = _jxr_floor_div2(val);
+ image->strip[ch].up1[mx].data[jdx] = val;
+ }
+ }
+
+ _jxr_4x4PCT(image->strip[ch].up1[mx].data);
+
+#if defined(DETAILED_DEBUG)
+ {
+ DEBUG(" DC/LP (strip=%3d, mbx=%4d, ch=%d) post-PCT:", use_my, mx, ch);
+ DEBUG(" 0x%08x", MACROBLK_UP_DC(image,ch,0,mx));
+ for (jdx = 0; jdx < 15 ; jdx += 1) {
+ DEBUG(" 0x%08x", MACROBLK_UP_LP(image,ch,tx,mx,jdx));
+ if ((jdx+1)%4 == 3 && jdx != 14)
+ DEBUG("\n%*s:", 44, "");
+ }
+ DEBUG("\n");
+ }
+#endif
+ }
+
+ /* Quantize */
+ lp_quant = w_guess_lp_quant(image, ch, tx, ty, mx, use_my);
+ MACROBLK_UP1_LP_QUANT(image,ch,tx,mx) = lp_quant;
+ lp_quant = _jxr_quant_map(image, lp_quant, ch==0? 1 : 0/* iShift for YONLY */);
+ assert(lp_quant > 0);
+
+ DEBUG(" DC-LP (mx=%d ch=%d) use_dc_quant=%d, use_lp_quant=%d\n",
+ mx, ch, dc_quant, lp_quant);
+
+ CHECK1(image->lwf_test, MACROBLK_CUR_DC(image,ch,tx,mx));
+ MACROBLK_UP_DC(image,ch,tx,mx) = quantize_dc(MACROBLK_UP_DC(image,ch,tx,mx), dc_quant);
+ for (jdx = 1 ; jdx < dclp_count ; jdx += 1) {
+ int value;
+ CHECK1(image->lwf_test, MACROBLK_UP_LP(image,ch,tx,mx,jdx-1));
+ value = MACROBLK_UP_LP(image,ch,tx,mx,jdx-1);
+ MACROBLK_UP_LP(image,ch,tx,mx,jdx-1) = quantize_lphp(value, lp_quant);
+ }
+#if defined(DETAILED_DEBUG)
+ { int jdx;
+ DEBUG(" DC/LP (strip=%3d, mbx=%4d, ch=%d) post-QP:", use_my, mx, ch);
+ DEBUG(" 0x%08x", MACROBLK_UP_DC(image,ch,tx,mx));
+ for (jdx = 0; jdx < dclp_count-1 ; jdx += 1) {
+ DEBUG(" 0x%08x", MACROBLK_UP_LP(image,ch,tx,mx,jdx));
+ if ((jdx+1)%4 == 3 && jdx != 14)
+ DEBUG("\n%*s:", 43, "");
+ }
+ DEBUG("\n");
+ }
+#endif
+ }
+}
+
+static void second_prefilter444_up1(jxr_image_t image, int ch, int ty)
+{
+ int tx = 0; /* XXXX */
+ int top_my = image->cur_my + 1;
+ int idx;
+
+ assert(ch == 0 || (image->use_clr_fmt != 2/*YUV422*/ && image->use_clr_fmt !=1/* YUV420*/));
+ if (top_my >= image->tile_row_height[ty])
+ top_my -= image->tile_row_height[ty++];
+ top_my += image->tile_row_position[ty];
+
+ DEBUG("Pre Level1 (YUV444) for row %d\n", top_my);
+
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ /* Top edge */
+ if(top_my == 0 || (image->disableTileOverlapFlag && TOP_Y(top_my) ))
+ {
+ /* If this is the very first strip of blocks, then process the
+ first two scan lines with the smaller 4Pre filter. */
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ /* Top edge across */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag) || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+ int*tp0 = MACROBLK_UP1(image,ch,tx,idx+0).data;
+ int*tp1 = MACROBLK_UP1(image,ch,tx,idx-1).data; /* Macroblock to the right */
+
+ _jxr_4PreFilter(tp1+2, tp1+3, tp0+0, tp0+1);
+ _jxr_4PreFilter(tp1+6, tp1+7, tp0+4, tp0+5);
+ }
+ }
+ /* Top left corner */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP1(image,ch,tx,0).data;
+ _jxr_4PreFilter(tp0+0, tp0+1, tp0+4, tp0+5);
+ }
+ /* Top right corner */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP1(image,ch,tx,image->tile_column_width[tx]-1).data;
+ _jxr_4PreFilter(tp0+2, tp0+3, tp0+6, tp0+7);
+ }
+ }
+
+ /* Bottom edge */
+ if ((top_my+1) == (int) EXTENDED_HEIGHT_BLOCKS(image) || (image->disableTileOverlapFlag && BOTTOM_Y(top_my))) {
+
+ /* This is the last row, so there is no UP below
+ TOP. finish up with 4Pre filters. */
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ /* Bottom edge across */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag)
+ || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+
+ int*tp0 = MACROBLK_UP1(image,ch,tx,idx+0).data;
+ int*tp1 = MACROBLK_UP1(image,ch,tx,idx-1).data;
+ _jxr_4PreFilter(tp1+10, tp1+11, tp0+8, tp0+9);
+ _jxr_4PreFilter(tp1+14, tp1+15, tp0+12, tp0+13);
+ }
+ }
+
+ /* Bottom left corner */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP1(image,ch,tx,0).data;
+ _jxr_4PreFilter(tp0+8, tp0+9, tp0+12, tp0+13);
+ }
+ /* Bottom right corner */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP1(image,ch,tx,image->tile_column_width[tx]-1).data;
+ _jxr_4PreFilter(tp0+10, tp0+11, tp0+14, tp0+15);
+ }
+ }
+
+ for (idx = 0 ; idx < image->tile_column_width[tx] ; idx += 1) {
+ if ((top_my+1) < (int) EXTENDED_HEIGHT_BLOCKS(image)) {
+
+ if ((tx == 0 && idx==0 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && LEFT_X(idx) && !BOTTOM_Y(top_my))) {
+ int*tp0 = MACROBLK_UP1(image,ch,tx,0).data;
+ int*up0 = MACROBLK_UP2(image,ch,tx,0).data;
+
+ /* Left edge Across Vertical MBs */
+ _jxr_4PreFilter(tp0+8, tp0+12, up0+0, up0+4);
+ _jxr_4PreFilter(tp0+9, tp0+13, up0+1, up0+5);
+ }
+
+ if (((image->tile_column_position[tx] + idx < EXTENDED_WIDTH_BLOCKS(image)-1) && !image->disableTileOverlapFlag ) ||
+ ( image->disableTileOverlapFlag && !RIGHT_X(idx) && !BOTTOM_Y(top_my) )
+ ) {
+ /* This assumes that the DCLP coefficients are the first
+ 16 values in the array, and ordered properly. */
+ int*tp0 = MACROBLK_UP1(image,ch,tx,idx+0).data;
+ int*tp1 = MACROBLK_UP1(image,ch,tx,idx+1).data;
+ int*up0 = MACROBLK_UP2(image,ch,tx,idx+0).data;
+ int*up1 = MACROBLK_UP2(image,ch,tx,idx+1).data;
+
+ /* MB below, right, right-below */
+ _jxr_4x4PreFilter(tp0+10, tp0+11, tp1+ 8, tp1+ 9,
+ tp0+14, tp0+15, tp1+12, tp1+13,
+ up0+ 2, up0+ 3, up1+ 0, up1+ 1,
+ up0+ 6, up0+ 7, up1+ 4, up1+ 5);
+ }
+ if((image->tile_column_position[tx] + idx == (int) EXTENDED_WIDTH_BLOCKS(image)-1 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && RIGHT_X(idx) && !BOTTOM_Y(top_my)))
+ {
+ int*tp0 = MACROBLK_UP1(image,ch,tx,image->tile_column_width[tx]-1).data;
+ int*up0 = MACROBLK_UP2(image,ch,tx,image->tile_column_width[tx]-1).data;
+
+ /* Right edge Across Vertical MBs */
+ _jxr_4PreFilter(tp0+10, tp0+14, up0+2, up0+6);
+ _jxr_4PreFilter(tp0+11, tp0+15, up0+3, up0+7);
+ }
+ }
+ }
+ }
+}
+
+
+static void second_prefilter422_up1(jxr_image_t image, int ch, int ty)
+{
+ int tx = 0; /* XXXX */
+ int top_my = image->cur_my + 1;
+ int idx;
+
+ assert(ch > 0);
+ if (top_my >= image->tile_row_height[ty])
+ top_my -= image->tile_row_height[ty++];
+ top_my += image->tile_row_position[ty];
+
+ DEBUG("Pre Level2 (YUV422) for row %d\n", top_my);
+
+ /* Top edge */
+ if(top_my == 0 || (image->disableTileOverlapFlag && TOP_Y(top_my)))
+ {
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ /* Top Left Corner Difference */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP1(image,ch,tx,0).data;
+ tp0[0] = tp0[0] - tp0[1];
+ CHECK1(image->lwf_test, tp0[0]);
+ }
+ /* Top Right Corner Difference */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *tp0 = MACROBLK_UP1(image,ch,tx,image->tile_column_width[tx]-1).data;
+ tp0[1] = tp0[1] - tp0[0];
+ CHECK1(image->lwf_test, tp0[1]);
+ }
+ }
+ }
+
+
+ /* Bottom edge */
+ if ((top_my+1) == (int) EXTENDED_HEIGHT_BLOCKS(image) || (image->disableTileOverlapFlag && BOTTOM_Y(top_my)))
+ {
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ /* Bottom Left Corner Difference */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP1(image,ch,tx,0).data;
+ tp0[6] = tp0[6] - tp0[7];
+ CHECK1(image->lwf_test, tp0[6]);
+ }
+ /* Bottom Right Corner Difference */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *tp0 = MACROBLK_UP1(image,ch,tx,image->tile_column_width[tx]-1).data;
+ tp0[7] = tp0[7] - tp0[6];
+ CHECK1(image->lwf_test, tp0[7]);
+ }
+ }
+ }
+
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ /* Left edge */
+ if (tx == 0 || image->disableTileOverlapFlag)
+ {
+ /* Interior left edge */
+ int*tp0 = MACROBLK_UP1(image,ch,tx,0).data;
+ _jxr_2PreFilter(tp0+2, tp0+4);
+ }
+
+ /* Right edge */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP1(image,ch,tx,image->tile_column_width[tx]-1).data;
+ /* Interior Right edge */
+ _jxr_2PreFilter(tp0+3, tp0+5);
+ }
+
+
+ /* Top edge */
+ if(top_my == 0 || (image->disableTileOverlapFlag && TOP_Y(top_my) ))
+ {
+ /* If this is the very first strip of blocks, then process the
+ first two scan lines with the smaller 4Pre filter. */
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ /* Top edge across */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag) || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+ int*tp0 = MACROBLK_UP1(image,ch,tx,idx+0).data;
+ int*tp1 = MACROBLK_UP1(image,ch,tx,idx-1).data; /* The macroblock to the right */
+
+ _jxr_2PreFilter(tp1+1, tp0+0);
+ }
+ }
+ }
+
+ /* Bottom edge */
+ if ((top_my+1) == (int) EXTENDED_HEIGHT_BLOCKS(image) || (image->disableTileOverlapFlag && BOTTOM_Y(top_my))) {
+
+ /* This is the last row, so there is no UP below
+ TOP. finish up with 4Pre filters. */
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ /* Bottom edge across */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag)
+ || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+ int*tp0 = MACROBLK_UP1(image,ch,tx,idx+0).data;
+ int*tp1 = MACROBLK_UP1(image,ch,tx,idx - 1).data;
+ _jxr_2PreFilter(tp1+7, tp0+6);
+ }
+ }
+ }
+
+ for (idx = 0 ; idx < image->tile_column_width[tx] ; idx += 1) {
+ if(top_my< EXTENDED_HEIGHT_BLOCKS(image) -1)
+ {
+ if ((tx == 0 && idx==0 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && LEFT_X(idx) && !BOTTOM_Y(top_my))) {
+ /* Across vertical blocks, left edge */
+ int*tp0 = MACROBLK_UP1(image,ch,tx,0).data;
+ int*up0 = MACROBLK_UP2(image,ch,tx,0).data;
+
+ /* Left edge across vertical MBs */
+ _jxr_2PreFilter(tp0+6, up0+0);
+ }
+
+ if((image->tile_column_position[tx] + idx == (int) EXTENDED_WIDTH_BLOCKS(image)-1 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && RIGHT_X(idx) && !BOTTOM_Y(top_my)))
+ {
+ int*tp0 = MACROBLK_UP1(image,ch,tx,image->tile_column_width[tx]-1).data;
+ int*up0 = MACROBLK_UP2(image,ch,tx,image->tile_column_width[tx]-1).data;
+
+ /* Right edge across MBs */
+ _jxr_2PreFilter(tp0+7, up0+1);
+ }
+
+ if (((image->tile_column_position[tx] + idx < EXTENDED_WIDTH_BLOCKS(image)-1) && !image->disableTileOverlapFlag ) ||
+ ( image->disableTileOverlapFlag && !RIGHT_X(idx) && !BOTTOM_Y(top_my) )
+ )
+ {
+ /* This assumes that the DCLP coefficients are the first
+ 16 values in the array, and ordered properly. */
+ int*tp0 = MACROBLK_UP1(image,ch,tx,idx+0).data;
+ int*tp1 = MACROBLK_UP1(image,ch,tx,idx+1).data;
+ int*up0 = MACROBLK_UP2(image,ch,tx,idx+0).data;
+ int*up2 = MACROBLK_UP2(image,ch,tx,idx+1).data;
+
+ /* MB below, right, right-below */
+ _jxr_2x2PreFilter(tp0+7, tp1+6, up0+1, up2+0);
+ }
+ }
+
+ if (((image->tile_column_position[tx] + idx < EXTENDED_WIDTH_BLOCKS(image)-1) && !image->disableTileOverlapFlag ) ||
+ ( image->disableTileOverlapFlag && !RIGHT_X(idx) )
+ )
+ {
+ /* This assumes that the DCLP coefficients are the first
+ 16 values in the array, and ordered properly. */
+ int*tp0 = MACROBLK_UP1(image,ch,tx,idx+0).data;
+ int*tp1 = MACROBLK_UP1(image,ch,tx,idx+1).data;
+
+ /* MB to the right */
+ _jxr_2x2PreFilter(tp0+3, tp1+2, tp0+5, tp1+4);
+ }
+ }
+ }
+
+ /* Top edge */
+ if(top_my == 0 || (image->disableTileOverlapFlag && TOP_Y(top_my)))
+ {
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ /* Top Left Corner Addition */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP1(image,ch,tx,0).data;
+ tp0[0] = tp0[0] + tp0[1];
+ CHECK1(image->lwf_test, tp0[0]);
+ }
+ /* Top Right Corner Addition */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *tp0 = MACROBLK_UP1(image,ch,tx,image->tile_column_width[tx]-1).data;
+ tp0[1] = tp0[1] + tp0[0];
+ CHECK1(image->lwf_test, tp0[1]);
+ }
+ }
+ }
+
+ /* Bottom edge */
+ if ((top_my+1) == (int) EXTENDED_HEIGHT_BLOCKS(image) || (image->disableTileOverlapFlag && BOTTOM_Y(top_my)))
+ {
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ /* Bottom Left Corner Addition */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP1(image,ch,tx,0).data;
+ tp0[6] = tp0[6] + tp0[7];
+ CHECK1(image->lwf_test, tp0[6]);
+ }
+ /* Bottom Right Corner Addition */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *tp0 = MACROBLK_UP1(image,ch,tx,image->tile_column_width[tx]-1).data;
+ tp0[7] = tp0[7] + tp0[6];
+ CHECK1(image->lwf_test, tp0[7]);
+ }
+ }
+ }
+}
+
+static void second_prefilter420_up1(jxr_image_t image, int ch, int ty)
+{
+ int tx = 0; /* XXXX */
+ int top_my = image->cur_my + 1;
+ int idx;
+ assert(ch > 0);
+
+ if (top_my >= image->tile_row_height[ty])
+ top_my -= image->tile_row_height[ty++];
+ top_my += image->tile_row_position[ty];
+
+ DEBUG("Pre Level2 (YUV420) for row %d\n", top_my);
+
+ if(top_my == 0 || (image->disableTileOverlapFlag && TOP_Y(top_my)))
+ {
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ /* Top Left Corner Difference*/
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP1(image,ch,tx,0).data;
+ tp0[0] = tp0[0] - tp0[1];
+ CHECK1(image->lwf_test, tp0[0]);
+ }
+ /* Top Right Corner Difference*/
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *tp0 = MACROBLK_UP1(image,ch,tx,image->tile_column_width[tx]-1).data;
+ tp0[1] = tp0[1] - tp0[0];
+ CHECK1(image->lwf_test, tp0[1]);
+ }
+ }
+ }
+
+ /* Bottom edge */
+ if ((top_my+1) == (int) EXTENDED_HEIGHT_BLOCKS(image) || (image->disableTileOverlapFlag && BOTTOM_Y(top_my)))
+ {
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ /* Bottom Left Corner Difference*/
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP1(image,ch,tx,0).data;
+ tp0[2] = tp0[2] - tp0[3];
+ CHECK1(image->lwf_test, tp0[2]);
+ }
+ /* Bottom Right Corner Difference*/
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *tp0 = MACROBLK_UP1(image,ch,tx,image->tile_column_width[tx]-1).data;
+ tp0[3] = tp0[3] - tp0[2];
+ CHECK1(image->lwf_test, tp0[3]);
+ }
+ }
+ }
+
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ /* Top edge */
+ if(top_my == 0 || (image->disableTileOverlapFlag && TOP_Y(top_my)))
+ {
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ /* Top edge across */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag) || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+ int*tp0 = MACROBLK_UP1(image,ch,tx,idx+0).data;
+ int*tp1 = MACROBLK_UP1(image,ch,tx,idx-1).data;
+ _jxr_2PreFilter(tp1+1, tp0+0);
+ }
+ }
+ }
+
+ /* Bottom edge */
+ if ((top_my+1) == (int) EXTENDED_HEIGHT_BLOCKS(image) || (image->disableTileOverlapFlag && BOTTOM_Y(top_my))) {
+
+ /* This is the last row, so there is no UP below
+ TOP. */
+ for (idx = 0; idx < image->tile_column_width[tx] ; idx += 1)
+ {
+ /* Bottom edge across */
+ if ( (image->tile_column_position[tx] + idx > 0 && !image->disableTileOverlapFlag)
+ || (image->disableTileOverlapFlag && !LEFT_X(idx))) {
+ int*tp0 = MACROBLK_UP1(image,ch,tx,idx+0).data;
+ int*tp1 = MACROBLK_UP1(image,ch,tx,idx-1).data;
+ _jxr_2PreFilter(tp1+3, tp0+2);
+ }
+ }
+ }
+ else
+ {
+ for (idx = 0 ; idx < image->tile_column_width[tx] ; idx += 1) {
+
+ if ((tx == 0 && idx==0 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && LEFT_X(idx) && !BOTTOM_Y(top_my))) {
+ /* Left edge across vertical MBs */
+ int*tp0 = MACROBLK_UP1(image,ch,tx,0).data;
+ int*up0 = MACROBLK_UP2(image,ch,tx,0).data;
+
+ _jxr_2PreFilter(tp0+2, up0+0);
+ }
+
+ if((image->tile_column_position[tx] + idx == (int) EXTENDED_WIDTH_BLOCKS(image)-1 && !image->disableTileOverlapFlag) ||
+ (image->disableTileOverlapFlag && RIGHT_X(idx) && !BOTTOM_Y(top_my)))
+ {
+ /* Right edge across vertical MBs */
+ int*tp0 = MACROBLK_UP1(image,ch,tx,image->tile_column_width[tx]-1).data;
+ int*up0 = MACROBLK_UP2(image,ch,tx,image->tile_column_width[tx]-1).data;
+
+ _jxr_2PreFilter(tp0+3, up0+1);
+ }
+
+ if (((image->tile_column_position[tx] + idx < EXTENDED_WIDTH_BLOCKS(image)-1) && !image->disableTileOverlapFlag ) ||
+ ( image->disableTileOverlapFlag && !RIGHT_X(idx) && !BOTTOM_Y(top_my) )
+ )
+ {
+ /* This assumes that the DCLP coefficients are the first
+ 16 values in the array, and ordered properly. */
+ /* MB below, right, right-below */
+ int*tp0 = MACROBLK_UP1(image,ch,tx,idx+0).data;
+ int*tp1 = MACROBLK_UP1(image,ch,tx,idx+1).data;
+ int*up0 = MACROBLK_UP2(image,ch,tx,idx+0).data;
+ int*up2 = MACROBLK_UP2(image,ch,tx,idx+1).data;
+
+ _jxr_2x2PreFilter(tp0+3, tp1+2,
+ up0+1, up2+0);
+ }
+ }
+ }
+ }
+
+ /* Top edge */
+ if(top_my == 0 || (image->disableTileOverlapFlag && TOP_Y(top_my)))
+ {
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ /* Top Left Corner Addition */
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP1(image,ch,tx,0).data;
+ tp0[0] = tp0[0] + tp0[1];
+ CHECK1(image->lwf_test, tp0[0]);
+ }
+ /* Top Right Corner Addition */
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *tp0 = MACROBLK_UP1(image,ch,tx,image->tile_column_width[tx]-1).data;
+ tp0[1] = tp0[1] + tp0[0];
+ CHECK1(image->lwf_test, tp0[1]);
+ }
+ }
+ }
+
+
+ /* Bottom edge */
+ if ((top_my+1) == (int) EXTENDED_HEIGHT_BLOCKS(image) || (image->disableTileOverlapFlag && BOTTOM_Y(top_my)))
+ {
+ for(tx = 0; tx < image->tile_columns; tx++)
+ {
+ /* Bottom Left Corner Addition*/
+ if(tx == 0 || image->disableTileOverlapFlag)
+ {
+ int*tp0 = MACROBLK_UP1(image,ch,tx,0).data;
+ tp0[2] = tp0[2] + tp0[3];
+ CHECK1(image->lwf_test, tp0[2]);
+ }
+ /* Bottom Right Corner Addition*/
+ if(tx == image->tile_columns -1 || image->disableTileOverlapFlag)
+ {
+ int *tp0 = MACROBLK_UP1(image,ch,tx,image->tile_column_width[tx]-1).data;
+ tp0[3] = tp0[3] + tp0[2];
+ CHECK1(image->lwf_test, tp0[3]);
+ }
+ }
+ }
+}
+
+static void second_prefilter_up1(jxr_image_t image, int ty)
+{
+ int ch;
+ second_prefilter444_up1(image, 0, ty);
+ switch (image->use_clr_fmt) {
+ case 0:
+ assert(image->num_channels == 1);
+ break;
+ case 1:/*YUV420*/
+ second_prefilter420_up1(image, 1, ty);
+ second_prefilter420_up1(image, 2, ty);
+ break;
+ case 2:/*YUV422*/
+ second_prefilter422_up1(image, 1, ty);
+ second_prefilter422_up1(image, 2, ty);
+ break;
+ default:
+ for (ch = 1 ; ch < image->num_channels ; ch += 1)
+ second_prefilter444_up1(image, ch, ty);
+ break;
+ }
+}
+
+static void dclphp_unshuffle(int*data, int dclp_count)
+{
+ int buf[256];
+ int idx, jdx;
+
+ for (idx = 0 ; idx < dclp_count ; idx += 1) {
+ buf[idx] = data[idx*16];
+
+ for (jdx = 1 ; jdx < 16 ; jdx += 1) {
+ buf[16 + 15*idx + jdx-1] = data[16*idx+jdx];
+ }
+ }
+
+ for (idx = 0 ; idx < 16+15*dclp_count ; idx += 1)
+ data[idx] = buf[idx];
+}
+
+static void PCT_stage1_up2(jxr_image_t image, int ch, int ty)
+{
+ int tx = 0;
+ int use_my = image->cur_my + 2;
+ int mx;
+ int dclp_count;
+
+ /* make adjustments based on tiling */
+ if (use_my >= image->tile_row_height[ty]) {
+ use_my -= image->tile_row_height[ty];
+ ty += 1;
+ if (use_my >= image->tile_row_height[ty]) {
+ use_my -= image->tile_row_height[ty];
+ ty += 1;
+ }
+ }
+
+ dclp_count = 16;
+ if (ch>0 && image->use_clr_fmt == 2/*YUV422*/)
+ dclp_count = 8;
+ else if (ch>0 && image->use_clr_fmt == 1/*YUV420*/)
+ dclp_count = 4;
+
+ for (mx = 0 ; mx < (int) EXTENDED_WIDTH_BLOCKS(image) ; mx += 1) {
+ int jdx;
+ int hp_quant_raw;
+ int hp_quant;
+ for (jdx = 0 ; jdx < 16*dclp_count ; jdx += 16) {
+#if defined(DETAILED_DEBUG)
+ {
+ int pix;
+ DEBUG(" DC-LP-HP (strip=%3d, mbx=%4d ch=%d, block=%2d) pre-PCT:",
+ use_my, mx, ch, jdx/16);
+ for (pix = 0; pix < 16 ; pix += 1) {
+ DEBUG(" 0x%08x", image->strip[ch].up2[mx].data[jdx+pix]);
+ if (pix%4 == 3 && pix != 15)
+ DEBUG("\n%*s:", 55, "");
+ }
+ DEBUG("\n");
+ }
+#endif
+ _jxr_4x4PCT(image->strip[ch].up2[mx].data+jdx);
+
+#if defined(DETAILED_DEBUG)
+ {
+ int pix;
+ DEBUG(" DC-LP-HP (strip=%3d, mbx=%4d ch=%d, block=%2d) PCT:",
+ use_my, mx, ch, jdx/16);
+ for (pix = 0; pix < 16 ; pix += 1) {
+ DEBUG(" 0x%08x", image->strip[ch].up2[mx].data[jdx+pix]);
+ if (pix%4 == 3 && pix != 15)
+ DEBUG("\n%*s:", 51, "");
+ }
+ DEBUG("\n");
+ }
+#endif
+ }
+
+ dclphp_unshuffle(image->strip[ch].up2[mx].data, dclp_count);
+
+ hp_quant_raw = w_guess_hp_quant(image, ch, tx, ty, mx, use_my);
+ hp_quant = _jxr_quant_map(image, hp_quant_raw, 1);
+ assert(hp_quant > 0);
+
+ DEBUG(" DC-LP-HP (mx=%d ch=%d) use_hp_quant=%d (hp quant index=%u raw=%d)\n", mx, ch,
+ hp_quant, _jxr_select_hp_index(image, tx, ty, mx, use_my), hp_quant_raw);
+
+ for (jdx = 0 ; jdx < dclp_count ; jdx += 1) {
+ int k;
+ for (k = 0 ; k < 15 ; k += 1) {
+ int value;
+ CHECK1(image->lwf_test, MACROBLK_UP2_HP(image,ch,tx,mx,jdx,k));
+ value = MACROBLK_UP2_HP(image,ch,tx,mx,jdx,k);
+ MACROBLK_UP2_HP(image,ch,tx,mx,jdx,k) = quantize_lphp(value, hp_quant);
+ }
+#if defined(DETAILED_DEBUG)
+ {
+ int pix;
+ DEBUG(" DC-LP-HP (strip=%3d, mbx=%4d ch=%d, block=%2d) Quantized: 0x%08x",
+ use_my, mx, ch, jdx, MACROBLK_UP2_LP(image,ch,tx,mx,jdx));
+ for (pix = 1; pix < 16 ; pix += 1) {
+ DEBUG(" 0x%08x", MACROBLK_UP2_HP(image,ch,tx,mx,jdx,pix-1));
+ if (pix%4 == 3 && pix != 15)
+ DEBUG("\n%*s:", 57, "");
+ }
+ DEBUG("\n");
+ }
+#endif
+ }
+ }
+}
+
+/*
+* Calcualte the value of MBDCMode, which defines the prediction for
+* the macroblock. There is one MBDCMode value for all the components,
+* and will take into account some of the chroma planes if it makes
+* sense.
+*
+* Note that CUR is before UP1 in the stream, and UP1 is the strip
+* that is being worked on.
+*/
+static int w_calculate_mbdc_mode(jxr_image_t image, int tx, int mx, int my)
+{
+ /* The context. */
+ long left = MACROBLK_UP1(image, 0, tx, mx-1).pred_dclp[0];
+ long top = MACROBLK_CUR(image, 0, tx, mx).pred_dclp[0];
+ long topleft = MACROBLK_CUR(image, 0, tx, mx-1).pred_dclp[0];
+ long strhor = 0;
+ long strvert = 0;
+
+ if (mx == 0 && my == 0)
+ return 3; /* No prediction. */
+
+ if (mx == 0)
+ return 1; /* Predictions from top only. */
+
+ if (my == 0)
+ return 0; /* prediction from left only */
+
+ /* Calculate horizontal and vertical "strengths". We will use
+ those strengths to decide which direction prediction should
+ be. */
+ if (image->use_clr_fmt==0 || image->use_clr_fmt==6) {/* YONLY or NCOMPONENT */
+
+ /* YONLY and NCOMPONENT use only the context of channel-0
+ to calculate the strengths. */
+ strhor = labs(topleft - left);
+ strvert = labs(topleft - top);
+
+ } else {
+ /* YUV4XX and YUVK also include the U and V channels to
+ calculate the strengths. Note that YUVK (CMYK)
+ ignores the K channel so that all color images are
+ processed the same, generally. */
+ long left_u = MACROBLK_UP1(image, 1, tx, mx-1).pred_dclp[0];
+ long top_u = MACROBLK_CUR(image, 1, tx, mx).pred_dclp[0];
+ long topleft_u = MACROBLK_CUR(image, 1, tx, mx-1).pred_dclp[0];
+ long left_v = MACROBLK_UP1(image, 2, tx, mx-1).pred_dclp[0];
+ long top_v = MACROBLK_CUR(image, 2, tx, mx).pred_dclp[0];
+ long topleft_v = MACROBLK_CUR(image, 2, tx, mx-1).pred_dclp[0];
+
+ long scale = 2;
+ if (image->use_clr_fmt == 2 /*YUV422*/)
+ scale = 4;
+ if (image->use_clr_fmt == 1 /*YUV420*/)
+ scale = 8;
+
+ strhor = labs(topleft - left)*scale + labs(topleft_u - left_u) + labs(topleft_v - left_v);
+ strvert = labs(topleft - top)*scale + labs(topleft_u - top_u) + labs(topleft_v - top_v);
+ }
+
+ if ((strhor*4) < strvert)
+ return 1;
+
+ if ((strvert*4) < strhor)
+ return 0;
+
+ return 2;
+}
+
+/*
+* Do DC-LP prediction on the UP1 strip. The CUR strip has already
+* been processed (and (rotated down from UP1) so CUR is earlier in
+* the image stream and is the top context for the prediction.
+*/
+static void w_predict_up1_dclp(jxr_image_t image, int tx, int ty, int mx)
+{
+ int my = image->cur_my + 1;
+ int mblp_mode;
+ unsigned char mblp_index;
+ int mbdc_mode;
+ int ch;
+
+ /* make adjustments based on tiling */
+ if (my == image->tile_row_height[ty]) {
+ my = 0;
+ ty += 1;
+ }
+
+ /* Calculate the mbcd prediction mode. This mode is used for
+ all the planes of DC data. */
+ mbdc_mode = w_calculate_mbdc_mode(image, tx, mx, my);
+ /* Now process all the planes of DC data. */
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ long left = mx>0? MACROBLK_UP1(image,ch,tx,mx-1).pred_dclp[0] : 0;
+ long top = MACROBLK_CUR(image,ch,tx,mx).pred_dclp[0];
+
+ DEBUG(" MBDC_MODE=%d for TX=%d, MBx=%d, MBy=%d, ch=%d, left=0x%lx, top=0x%lx, cur=0x%x\n",
+ mbdc_mode, tx, mx, my, ch, left, top, MACROBLK_UP_DC(image,ch,tx,mx));
+
+ /* Save this unpredicted DC value for later prediction steps. */
+ MACROBLK_UP1(image,ch,tx,mx).pred_dclp[0] = MACROBLK_UP_DC(image,ch,tx,mx);
+
+ /* Perform the actual DC prediction. */
+ switch (mbdc_mode) {
+ case 0: /* left */
+ MACROBLK_UP_DC(image,ch,tx,mx) -= left;
+ break;
+ case 1: /* top */
+ MACROBLK_UP_DC(image,ch,tx,mx) -= top;
+ break;
+ case 2:/* top and left */
+ /* Note that we really MEAN >>1 and NOT /2. in
+ particular, if the sum is -1, we want the
+ result to also be -1. That extra stuff after
+ the "|" is there to make sure the sign bit is
+ not lost. Also, the chroma planes for YUV42X
+ formats round *up* the mean, where all other
+ planes round down. */
+ if (ch>0 && (image->use_clr_fmt==1/*YUV420*/||image->use_clr_fmt==2/*YUV422*/))
+ MACROBLK_UP_DC(image,ch,tx,mx) -= (left+top+1) >> 1 | ((left+top+1)&~INT_MAX);
+ else
+ MACROBLK_UP_DC(image,ch,tx,mx) -= (left+top) >> 1 | ((left+top)&~INT_MAX);
+ break;
+ default:
+ break;
+ }
+ CHECK1(image->lwf_test, MACROBLK_UP_DC(image,ch,tx,mx));
+
+ }
+
+ /* The MBLPMode decides the LP prediction within the
+ macroblock. It is generally the same as the prediction
+ direction for DC in the macroblock, but we modify it based
+ on the MBLP QP Index. In particular, if MBDC mode is
+ predicting from the left, bug the MBLP QP Index from the
+ left is different from that of the current MB, then cancel
+ prediction. Same for prediction from above. */
+ mblp_mode = 2;
+ mblp_index = _jxr_select_lp_index(image, tx, ty, mx, my);
+ if (mbdc_mode == 0) {
+ unsigned char mblp_index_left = _jxr_select_lp_index(image, tx, ty, mx-1, my);
+ if (mblp_index == mblp_index_left)
+ mblp_mode = 0;
+ else
+ mblp_mode = 2;
+
+ DEBUG(" MBLP_MODE=%d for MBx=%d, MBy=%d (lp_quant=%d,lp_quant_ctx=%d)\n", mblp_mode, mx, my,
+ mblp_index, mblp_index_left);
+
+ } else if (mbdc_mode == 1) {
+ unsigned char mblp_index_up = _jxr_select_lp_index(image, tx, ty, mx, my-1);
+ if (mblp_index == mblp_index_up)
+ mblp_mode = 1;
+ else
+ mblp_mode = 2;
+
+ DEBUG(" MBLP_MODE=%d for MBx=%d, MBy=%d (lp_quant=%d,lp_quant_ctx=%d)\n", mblp_mode, mx, my,
+ mblp_index, mblp_index_up);
+ } else {
+
+ mblp_mode = 2;
+ DEBUG(" MBLP_MODE=%d for MBx=%d, MBy=%d (lp_quant=%d,lp_quant_ctx=-1)\n", mblp_mode, mx, my,
+ mblp_index);
+ }
+
+ w_predict_lp444(image, tx, mx, my, 0, mblp_mode);
+ for (ch = 1 ; ch < image->num_channels ; ch += 1) {
+ switch (image->use_clr_fmt) {
+ case 1: /* YUV420 */
+ w_predict_lp420(image, tx, mx, my, ch, mblp_mode);
+ break;
+ case 2: /* YUV422 */
+ w_predict_lp422(image, tx, mx, my, ch, mblp_mode, mbdc_mode);
+ break;
+ default:
+ w_predict_lp444(image,tx, mx, my, ch, mblp_mode);
+ break;
+ }
+ }
+}
+
+static int w_calculate_mbhp_mode_up1(jxr_image_t image, int tx, int mx)
+{
+ long strength_hor = 0;
+ long strength_ver = 0;
+ const long orientation_weight = 4;
+
+ /* Add up the LP magnitudes along the top edge */
+ strength_hor += abs(MACROBLK_UP_LP(image, 0, tx, mx, 0));
+ strength_hor += abs(MACROBLK_UP_LP(image, 0, tx, mx, 1));
+ strength_hor += abs(MACROBLK_UP_LP(image, 0, tx, mx, 2));
+
+ /* Add up the LP magnitudes along the left edge */
+ strength_ver += abs(MACROBLK_UP_LP(image, 0, tx, mx, 3));
+ strength_ver += abs(MACROBLK_UP_LP(image, 0, tx, mx, 7));
+ strength_ver += abs(MACROBLK_UP_LP(image, 0, tx, mx, 11));
+
+ switch (image->use_clr_fmt) {
+ case 0: /*YONLY*/
+ case 6: /*NCOMPONENT*/
+ break;
+ case 3: /*YUV444*/
+ case 4: /*YUVK */
+ strength_hor += abs(MACROBLK_UP_LP(image, 1, tx, mx, 0));
+ strength_hor += abs(MACROBLK_UP_LP(image, 2, tx, mx, 0));
+ strength_ver += abs(MACROBLK_UP_LP(image, 1, tx, mx, 3));
+ strength_ver += abs(MACROBLK_UP_LP(image, 2, tx, mx, 3));
+ break;
+ case 2: /*YUV422*/
+ strength_hor += abs(MACROBLK_UP_LP(image, 1, tx, mx, 0));
+ strength_hor += abs(MACROBLK_UP_LP(image, 2, tx, mx, 0));
+ strength_ver += abs(MACROBLK_UP_LP(image, 1, tx, mx, 1));
+ strength_ver += abs(MACROBLK_UP_LP(image, 2, tx, mx, 1));
+ strength_hor += abs(MACROBLK_UP_LP(image, 1, tx, mx, 4));
+ strength_hor += abs(MACROBLK_UP_LP(image, 2, tx, mx, 4));
+ strength_ver += abs(MACROBLK_UP_LP(image, 1, tx, mx, 5));
+ strength_ver += abs(MACROBLK_UP_LP(image, 2, tx, mx, 5));
+ break;
+ case 1: /*YUV420*/
+ strength_hor += abs(MACROBLK_UP_LP(image, 1, tx, mx, 0));
+ strength_hor += abs(MACROBLK_UP_LP(image, 2, tx, mx, 0));
+ strength_ver += abs(MACROBLK_UP_LP(image, 1, tx, mx, 1));
+ strength_ver += abs(MACROBLK_UP_LP(image, 2, tx, mx, 1));
+ break;
+ default:
+ assert(0);
+ }
+
+ if (strength_hor * orientation_weight < strength_ver)
+ return 0; /* predict from left */
+ if (strength_ver * orientation_weight < strength_hor)
+ return 1; /* predict from top */
+
+ /* There is no strong weight from top or left, so do not
+ bother with prediction. */
+ return 2;
+}
+
+static void w_predict_up1_hp(jxr_image_t image, int ch, int tx, int mx, int mbhp_pred_mode)
+{
+ if (mbhp_pred_mode == 0) { /* Prediction left to right */
+ int idx;
+ for (idx = 15 ; idx > 0 ; idx -= 1) {
+ if (idx%4 == 0)
+ continue;
+
+ MACROBLK_UP1_HP(image,ch,tx,mx,idx, 3) -= MACROBLK_UP1_HP(image,ch,tx,mx,idx-1, 3);
+ MACROBLK_UP1_HP(image,ch,tx,mx,idx, 7) -= MACROBLK_UP1_HP(image,ch,tx,mx,idx-1, 7);
+ MACROBLK_UP1_HP(image,ch,tx,mx,idx,11) -= MACROBLK_UP1_HP(image,ch,tx,mx,idx-1,11);
+ CHECK3(image->lwf_test, MACROBLK_CUR_HP(image,ch,tx,mx,idx, 3), MACROBLK_CUR_HP(image,ch,tx,mx,idx, 7), MACROBLK_CUR_HP(image,ch,tx,mx,idx, 11));
+ }
+ } else if (mbhp_pred_mode == 1) { /* Prediction top to bottom */
+ int idx;
+ for (idx = 15 ; idx >= 4 ; idx -= 1) {
+ MACROBLK_UP1_HP(image,ch,tx,mx,idx,0) -= MACROBLK_UP1_HP(image,ch,tx,mx,idx-4,0);
+ MACROBLK_UP1_HP(image,ch,tx,mx,idx,1) -= MACROBLK_UP1_HP(image,ch,tx,mx,idx-4,1);
+ MACROBLK_UP1_HP(image,ch,tx,mx,idx,2) -= MACROBLK_UP1_HP(image,ch,tx,mx,idx-4,2);
+ CHECK3(image->lwf_test, MACROBLK_CUR_HP(image,ch,tx,mx,idx, 0), MACROBLK_CUR_HP(image,ch,tx,mx,idx, 1), MACROBLK_CUR_HP(image,ch,tx,mx,idx, 2));
+ }
+ }
+
+ switch (image->use_clr_fmt) {
+ case 1:/*YUV420*/
+ assert(ch == 0);
+ if (mbhp_pred_mode == 0) {
+ int idx;
+ for (idx = 3 ; idx > 0 ; idx -= 2) {
+ MACROBLK_UP1_HP(image,1,tx,mx,idx,3) -= MACROBLK_UP1_HP(image,1,tx,mx,idx-1,3);
+ MACROBLK_UP1_HP(image,2,tx,mx,idx,3) -= MACROBLK_UP1_HP(image,2,tx,mx,idx-1,3);
+ MACROBLK_UP1_HP(image,1,tx,mx,idx,7) -= MACROBLK_UP1_HP(image,1,tx,mx,idx-1,7);
+ MACROBLK_UP1_HP(image,2,tx,mx,idx,7) -= MACROBLK_UP1_HP(image,2,tx,mx,idx-1,7);
+ MACROBLK_UP1_HP(image,1,tx,mx,idx,11)-= MACROBLK_UP1_HP(image,1,tx,mx,idx-1,11);
+ MACROBLK_UP1_HP(image,2,tx,mx,idx,11)-= MACROBLK_UP1_HP(image,2,tx,mx,idx-1,11);
+ CHECK3(image->lwf_test, MACROBLK_CUR_HP(image,1,tx,mx,idx, 3), MACROBLK_CUR_HP(image,1,tx,mx,idx, 7), MACROBLK_CUR_HP(image,1,tx,mx,idx, 11));
+ CHECK3(image->lwf_test, MACROBLK_CUR_HP(image,2,tx,mx,idx, 3), MACROBLK_CUR_HP(image,2,tx,mx,idx, 7), MACROBLK_CUR_HP(image,2,tx,mx,idx, 11));
+ }
+ } else if (mbhp_pred_mode == 1) {
+ int idx;
+ for (idx = 3 ; idx >= 2 ; idx -= 1) {
+ MACROBLK_UP1_HP(image,1,tx,mx,idx,0) -= MACROBLK_UP1_HP(image,1,tx,mx,idx-2,0);
+ MACROBLK_UP1_HP(image,2,tx,mx,idx,0) -= MACROBLK_UP1_HP(image,2,tx,mx,idx-2,0);
+ MACROBLK_UP1_HP(image,1,tx,mx,idx,1) -= MACROBLK_UP1_HP(image,1,tx,mx,idx-2,1);
+ MACROBLK_UP1_HP(image,2,tx,mx,idx,1) -= MACROBLK_UP1_HP(image,2,tx,mx,idx-2,1);
+ MACROBLK_UP1_HP(image,1,tx,mx,idx,2) -= MACROBLK_UP1_HP(image,1,tx,mx,idx-2,2);
+ MACROBLK_UP1_HP(image,2,tx,mx,idx,2) -= MACROBLK_UP1_HP(image,2,tx,mx,idx-2,2);
+ CHECK3(image->lwf_test, MACROBLK_CUR_HP(image,1,tx,mx,idx, 0), MACROBLK_CUR_HP(image,1,tx,mx,idx, 1), MACROBLK_CUR_HP(image,1,tx,mx,idx, 2));
+ CHECK3(image->lwf_test, MACROBLK_CUR_HP(image,2,tx,mx,idx, 0), MACROBLK_CUR_HP(image,2,tx,mx,idx, 1), MACROBLK_CUR_HP(image,2,tx,mx,idx, 2));
+ }
+ }
+ break;
+
+ case 2:/*YUV422*/
+ assert(ch == 0);
+ if (mbhp_pred_mode == 0) {
+ int idx;
+ for (idx = 7 ; idx > 0 ; idx -= 2) {
+ MACROBLK_UP1_HP(image,1,tx,mx,idx,3) -= MACROBLK_UP1_HP(image,1,tx,mx,idx-1,3);
+ MACROBLK_UP1_HP(image,2,tx,mx,idx,3) -= MACROBLK_UP1_HP(image,2,tx,mx,idx-1,3);
+ MACROBLK_UP1_HP(image,1,tx,mx,idx,7) -= MACROBLK_UP1_HP(image,1,tx,mx,idx-1,7);
+ MACROBLK_UP1_HP(image,2,tx,mx,idx,7) -= MACROBLK_UP1_HP(image,2,tx,mx,idx-1,7);
+ MACROBLK_UP1_HP(image,1,tx,mx,idx,11)-= MACROBLK_UP1_HP(image,1,tx,mx,idx-1,11);
+ MACROBLK_UP1_HP(image,2,tx,mx,idx,11)-= MACROBLK_UP1_HP(image,2,tx,mx,idx-1,11);
+ CHECK3(image->lwf_test, MACROBLK_CUR_HP(image,1,tx,mx,idx, 3), MACROBLK_CUR_HP(image,1,tx,mx,idx, 7), MACROBLK_CUR_HP(image,1,tx,mx,idx, 11));
+ CHECK3(image->lwf_test, MACROBLK_CUR_HP(image,2,tx,mx,idx, 3), MACROBLK_CUR_HP(image,2,tx,mx,idx, 7), MACROBLK_CUR_HP(image,2,tx,mx,idx, 11));
+ }
+ } else if (mbhp_pred_mode == 1) {
+ int idx;
+ for (idx = 7; idx >= 2 ; idx -= 1) {
+ MACROBLK_UP1_HP(image,1,tx,mx,idx,0) -= MACROBLK_UP1_HP(image,1,tx,mx,idx-2,0);
+ MACROBLK_UP1_HP(image,2,tx,mx,idx,0) -= MACROBLK_UP1_HP(image,2,tx,mx,idx-2,0);
+ MACROBLK_UP1_HP(image,1,tx,mx,idx,1) -= MACROBLK_UP1_HP(image,1,tx,mx,idx-2,1);
+ MACROBLK_UP1_HP(image,2,tx,mx,idx,1) -= MACROBLK_UP1_HP(image,2,tx,mx,idx-2,1);
+ MACROBLK_UP1_HP(image,1,tx,mx,idx,2) -= MACROBLK_UP1_HP(image,1,tx,mx,idx-2,2);
+ MACROBLK_UP1_HP(image,2,tx,mx,idx,2) -= MACROBLK_UP1_HP(image,2,tx,mx,idx-2,2);
+ CHECK3(image->lwf_test, MACROBLK_CUR_HP(image,1,tx,mx,idx, 0), MACROBLK_CUR_HP(image,1,tx,mx,idx, 1), MACROBLK_CUR_HP(image,1,tx,mx,idx, 2));
+ CHECK3(image->lwf_test, MACROBLK_CUR_HP(image,2,tx,mx,idx, 0), MACROBLK_CUR_HP(image,2,tx,mx,idx, 1), MACROBLK_CUR_HP(image,2,tx,mx,idx, 2));
+ }
+ }
+#if defined(DETAILED_DEBUG) && 0
+ {
+ int idx;
+ for (idx = 0 ; idx < 8 ; idx += 1) {
+ int k;
+ DEBUG(" HP val difference[ch=1, tx=%u, mx=%d, block=%d] ==", tx, mx, idx);
+ for (k = 1 ; k<16; k+=1) {
+ DEBUG(" 0x%x", MACROBLK_UP1_HP(image,1,tx,mx,idx,k-1));
+ }
+ DEBUG("\n");
+ DEBUG(" HP val difference[ch=2, tx=%u, mx=%d, block=%d] ==", tx, mx, idx);
+ for (k = 1 ; k<16; k+=1) {
+ DEBUG(" 0x%x", MACROBLK_UP1_HP(image,2,tx,mx,idx,k-1));
+ }
+ DEBUG("\n");
+ }
+ }
+#endif
+ break;
+ default:
+ break;
+ }
+}
+
+static void w_predict_lp444(jxr_image_t image, int tx, int mx, int my, int ch, int mblp_mode)
+{
+ MACROBLK_UP1(image,ch,tx,mx).pred_dclp[1] = MACROBLK_UP_LP(image,ch,tx,mx,0);
+ MACROBLK_UP1(image,ch,tx,mx).pred_dclp[2] = MACROBLK_UP_LP(image,ch,tx,mx,1);
+ MACROBLK_UP1(image,ch,tx,mx).pred_dclp[3] = MACROBLK_UP_LP(image,ch,tx,mx,2);
+ MACROBLK_UP1(image,ch,tx,mx).pred_dclp[4] = MACROBLK_UP_LP(image,ch,tx,mx,3);
+ MACROBLK_UP1(image,ch,tx,mx).pred_dclp[5] = MACROBLK_UP_LP(image,ch,tx,mx,7);
+ MACROBLK_UP1(image,ch,tx,mx).pred_dclp[6] = MACROBLK_UP_LP(image,ch,tx,mx,11);
+
+#if defined(DETAILED_DEBUG)
+ {
+ int jdx;
+ DEBUG(" DC/LP (strip=%3d, mbx=%4d, ch=%d) Predicted:", my, mx, ch);
+ DEBUG(" 0x%08x", MACROBLK_UP1(image,ch,tx,mx).pred_dclp[0]);
+ for (jdx = 0; jdx < 15 ; jdx += 1) {
+ DEBUG(" 0x%08x", MACROBLK_UP_LP(image,ch,tx,mx,jdx));
+ if ((jdx+1)%4 == 3 && jdx != 14)
+ DEBUG("\n%*s:", 45, "");
+ }
+ DEBUG("\n");
+ }
+#endif
+
+ switch (mblp_mode) {
+ case 0: /* left */
+ MACROBLK_UP_LP(image,ch,tx,mx,3) -= MACROBLK_UP1(image,ch,tx,mx-1).pred_dclp[4];
+ MACROBLK_UP_LP(image,ch,tx,mx,7) -= MACROBLK_UP1(image,ch,tx,mx-1).pred_dclp[5];
+ MACROBLK_UP_LP(image,ch,tx,mx,11) -= MACROBLK_UP1(image,ch,tx,mx-1).pred_dclp[6];
+ CHECK3(image->lwf_test, MACROBLK_CUR_LP(image,ch,tx,mx,3), MACROBLK_CUR_LP(image,ch,tx,mx,7), MACROBLK_CUR_LP(image,ch,tx,mx,11));
+ break;
+ case 1: /* up */
+ MACROBLK_UP_LP(image,ch,tx,mx,0) -= MACROBLK_CUR(image,ch,tx,mx).pred_dclp[1];
+ MACROBLK_UP_LP(image,ch,tx,mx,1) -= MACROBLK_CUR(image,ch,tx,mx).pred_dclp[2];
+ MACROBLK_UP_LP(image,ch,tx,mx,2) -= MACROBLK_CUR(image,ch,tx,mx).pred_dclp[3];
+ CHECK3(image->lwf_test, MACROBLK_CUR_LP(image,ch,tx,mx,0), MACROBLK_CUR_LP(image,ch,tx,mx,1), MACROBLK_CUR_LP(image,ch,tx,mx,2));
+ break;
+ case 2:
+ break;
+ }
+#if defined(DETAILED_DEBUG)
+ {
+ int jdx;
+ DEBUG(" DC/LP (strip=%3d, mbx=%4d, ch=%d) Difference:", my, mx, ch);
+ DEBUG(" 0x%08x", MACROBLK_UP_DC(image,ch,tx,mx));
+ for (jdx = 0; jdx < 15 ; jdx += 1) {
+ DEBUG(" 0x%08x", MACROBLK_UP_LP(image,ch,tx,mx,jdx));
+ if ((jdx+1)%4 == 3 && jdx != 14)
+ DEBUG("\n%*s:", 46, "");
+ }
+ DEBUG("\n");
+ }
+#endif
+}
+
+static void w_predict_lp422(jxr_image_t image, int tx, int mx, int my, int ch, int mblp_mode, int mbdc_mode)
+{
+ MACROBLK_UP1(image,ch,tx,mx).pred_dclp[1] = MACROBLK_UP_LP(image,ch,tx,mx,0);
+ MACROBLK_UP1(image,ch,tx,mx).pred_dclp[2] = MACROBLK_UP_LP(image,ch,tx,mx,1);
+ MACROBLK_UP1(image,ch,tx,mx).pred_dclp[4] = MACROBLK_UP_LP(image,ch,tx,mx,3);
+ MACROBLK_UP1(image,ch,tx,mx).pred_dclp[5] = MACROBLK_UP_LP(image,ch,tx,mx,4);
+ MACROBLK_UP1(image,ch,tx,mx).pred_dclp[6] = MACROBLK_UP_LP(image,ch,tx,mx,5);
+
+#if defined(DETAILED_DEBUG)
+ {
+ int jdx;
+ DEBUG(" DC/LP (strip=%3d, mbx=%4d, ch=%d) Predicted:", my, mx, ch);
+ DEBUG(" 0x%08x", MACROBLK_UP1(image,ch,tx,mx).pred_dclp[0]);
+ for (jdx = 0; jdx < 7 ; jdx += 1) {
+ DEBUG(" 0x%08x", MACROBLK_UP_LP(image,ch,tx,mx,jdx));
+ if ((jdx+1)%4 == 3 && jdx != 6)
+ DEBUG("\n%*s:", 45, "");
+ }
+ DEBUG("\n");
+ }
+#endif
+ switch (mblp_mode) {
+ case 0: /* left */
+ MACROBLK_UP_LP(image,ch,tx,mx,3) -= MACROBLK_UP1(image,ch,tx,mx-1).pred_dclp[4];
+ MACROBLK_UP_LP(image,ch,tx,mx,1) -= MACROBLK_UP1(image,ch,tx,mx-1).pred_dclp[2];
+ MACROBLK_UP_LP(image,ch,tx,mx,5) -= MACROBLK_UP1(image,ch,tx,mx-1).pred_dclp[6];
+ CHECK3(image->lwf_test, MACROBLK_CUR_LP(image,ch,tx,mx,3), MACROBLK_CUR_LP(image,ch,tx,mx,1), MACROBLK_CUR_LP(image,ch,tx,mx,5));
+ break;
+ case 1: /* up */
+ MACROBLK_UP_LP(image,ch,tx,mx,3) -= MACROBLK_CUR(image,ch,tx,mx).pred_dclp[4];
+ MACROBLK_UP_LP(image,ch,tx,mx,0) -= MACROBLK_CUR(image,ch,tx,mx).pred_dclp[5];
+ MACROBLK_UP_LP(image,ch,tx,mx,4) -= MACROBLK_UP1(image,ch,tx,mx).pred_dclp[1];
+ CHECK3(image->lwf_test, MACROBLK_CUR_LP(image,ch,tx,mx,3), MACROBLK_CUR_LP(image,ch,tx,mx,0), MACROBLK_CUR_LP(image,ch,tx,mx,4));
+ break;
+ case 2:
+ if (mbdc_mode == 1) {
+ MACROBLK_UP_LP(image,ch,tx,mx,4) -= MACROBLK_UP_LP(image,ch,tx,mx,0);
+ CHECK1(image->lwf_test, MACROBLK_CUR_LP(image,ch,tx,mx,4));
+ }
+ break;
+ }
+#if defined(DETAILED_DEBUG)
+ {
+ int jdx;
+ DEBUG(" DC/LP (strip=%3d, mbx=%4d, ch=%d) Difference:", my, mx, ch);
+ DEBUG(" 0x%08x", MACROBLK_UP_DC(image,ch,tx,mx));
+ for (jdx = 0; jdx < 7 ; jdx += 1) {
+ DEBUG(" 0x%08x", MACROBLK_UP_LP(image,ch,tx,mx,jdx));
+ if ((jdx+1)%4 == 3 && jdx != 6)
+ DEBUG("\n%*s:", 46, "");
+ }
+ DEBUG("\n");
+ }
+#endif
+}
+
+static void w_predict_lp420(jxr_image_t image, int tx, int mx, int my, int ch, int mblp_mode)
+{
+ MACROBLK_UP1(image,ch,tx,mx).pred_dclp[1] = MACROBLK_UP_LP(image,ch,tx,mx,0);
+ MACROBLK_UP1(image,ch,tx,mx).pred_dclp[2] = MACROBLK_UP_LP(image,ch,tx,mx,1);
+
+ switch (mblp_mode) {
+ case 0: /* left */
+ MACROBLK_UP_LP(image,ch,tx,mx,1) -= MACROBLK_UP1(image,ch,tx,mx-1).pred_dclp[2];
+ CHECK1(image->lwf_test, MACROBLK_CUR_LP(image,ch,tx,mx,1));
+ break;
+ case 1: /* up */
+ MACROBLK_UP_LP(image,ch,tx,mx,0) -= MACROBLK_CUR(image,ch,tx,mx).pred_dclp[1];
+ CHECK1(image->lwf_test, MACROBLK_CUR_LP(image,ch,tx,mx,0));
+ break;
+ }
+}
+
+/*
+* This calculations the HP CBP for the macroblock. It also calculates
+* and saves the HP model_bits values for this block and stores them
+* away in the macroblock for later use by the MB_HP formatter.
+*/
+static void calculate_hpcbp_up1(jxr_image_t image, int tx, int ty, int mx)
+{
+ int use_my = image->cur_my + 1;
+ int lap_mean[2];
+ int ch;
+
+ /* make adjustments based on tiling */
+ if (use_my == image->tile_row_height[ty]) {
+ use_my = 0;
+ ty += 1;
+ }
+
+ if (_jxr_InitContext(image, tx, ty, mx, use_my)) {
+ _jxr_InitializeModelMB(&image->model_hp, 2/*band=HP*/);
+ }
+
+ lap_mean[0] = 0;
+ lap_mean[1] = 0;
+
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ int chroma_flag = (ch>0)? 1 : 0;
+ unsigned model_bits = image->model_hp.bits[chroma_flag];
+
+ int cbp_mask = 0;
+
+ int blk_count = 16;
+ int blk;
+ if (chroma_flag && image->use_clr_fmt==2/*YUV422*/)
+ blk_count = 8;
+ if (chroma_flag && image->use_clr_fmt==1/*YUV420*/)
+ blk_count = 4;
+
+ for (blk = 0 ; blk < blk_count ; blk += 1) {
+ int bpos = blk;
+ int idx;
+ if (blk_count==16)
+ bpos = _jxr_hp_scan_map[bpos];
+ for (idx = 0 ; idx < 15 ; idx += 1) {
+ int value = MACROBLK_UP1_HP(image,ch,tx,mx,bpos,idx);
+ value = abs(value) >> model_bits;
+ if (value != 0) {
+ cbp_mask |= 1<<blk;
+ lap_mean[chroma_flag] += 1;
+ }
+ }
+ }
+
+ MACROBLK_UP1_HPCBP(image, ch, tx, mx) = cbp_mask;
+ }
+
+ MACROBLK_UP1(image,0,tx,mx).hp_model_bits[0] = image->model_hp.bits[0];
+ MACROBLK_UP1(image,0,tx,mx).hp_model_bits[1] = image->model_hp.bits[1];
+
+ DEBUG(" MP_HP: lap_mean={%u, %u}, model_hp.bits={%u %u}, model_hp.state={%d %d}\n",
+ lap_mean[0], lap_mean[1],
+ image->model_hp.bits[0], image->model_hp.bits[1],
+ image->model_hp.state[0], image->model_hp.state[1]);
+
+ _jxr_UpdateModelMB(image, lap_mean, &image->model_hp, 2/*band=HP*/);
+
+ DEBUG(" MP_HP: Updated: lap_mean={%u, %u}, model_hp.bits={%u %u}, model_hp.state={%d %d}\n",
+ lap_mean[0], lap_mean[1],
+ image->model_hp.bits[0], image->model_hp.bits[1],
+ image->model_hp.state[0], image->model_hp.state[1]);
+
+}
+
+static void w_PredCBP(jxr_image_t image, unsigned tx, unsigned ty, unsigned mx)
+{
+ int use_my = image->cur_my+1;
+ int ch;
+ if (use_my == image->tile_row_height[ty]) {
+ use_my = 0;
+ ty += 1;
+ }
+
+ if (_jxr_InitContext(image, tx, ty, mx, use_my)) {
+ _jxr_InitializeCBPModel(image);
+ }
+
+ switch (image->use_clr_fmt) {
+ case 1: /* YUV420 */
+ _jxr_w_PredCBP444(image, 0, tx, mx, use_my);
+ _jxr_w_PredCBP420(image, 1, tx, mx, use_my);
+ _jxr_w_PredCBP420(image, 2, tx, mx, use_my);
+ break;
+ case 2: /* YUV422 */
+ _jxr_w_PredCBP444(image, 0, tx, mx, use_my);
+ _jxr_w_PredCBP422(image, 1, tx, mx, use_my);
+ _jxr_w_PredCBP422(image, 2, tx, mx, use_my);
+ break;
+ default:
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ DEBUG(" PredCBP: Predicted HPCBP[ch=%d]: 0x%04x\n",
+ ch, MACROBLK_UP1_HPCBP(image,ch,tx,mx));
+ _jxr_w_PredCBP444(image, ch, tx, mx, use_my);
+ }
+ break;
+ }
+}
+
+
+/*
+* $Log: w_strip.c,v $
+* Revision 1.50 2009/09/16 12:00:00 microsoft
+* Reference Software v1.8 updates.
+*
+* Revision 1.49 2009/05/29 12:00:00 microsoft
+* Reference Software v1.6 updates.
+*
+* Revision 1.48 2009/04/13 12:00:00 microsoft
+* Reference Software v1.5 updates.
+*
+* Revision 1.47 2008/03/24 18:06:56 steve
+* Imrpove DEBUG messages around quantization.
+*
+* Revision 1.46 2008/03/21 18:05:53 steve
+* Proper CMYK formatting on input.
+*
+* Revision 1.45 2008/03/21 00:08:56 steve
+* Handle missing LP/HP QP maps.
+*
+* Revision 1.44 2008/03/20 22:39:41 steve
+* Fix various debug prints of QP data.
+*
+* Revision 1.43 2008/03/20 18:11:50 steve
+* Clarify MBLPMode calculations.
+*
+* Revision 1.42 2008/03/19 00:35:28 steve
+* Fix MBLPMode prediction during distributed QP
+*
+* Revision 1.41 2008/03/18 21:09:12 steve
+* Fix distributed color prediction.
+*
+* Revision 1.40 2008/03/18 18:36:56 steve
+* Support compress of CMYK images.
+*
+* Revision 1.39 2008/03/14 17:08:51 gus
+* *** empty log message ***
+*
+* Revision 1.38 2008/03/14 16:10:47 steve
+* Clean up some signed/unsigned warnings.
+*
+* Revision 1.37 2008/03/14 00:54:09 steve
+* Add second prefilter for YUV422 and YUV420 encode.
+*
+* Revision 1.36 2008/03/14 00:12:00 steve
+* Fix YUV420 UV subsampling at bottom of MB.
+*
+* Revision 1.35 2008/03/13 23:46:24 steve
+* First level filter encoding.
+*
+* Revision 1.34 2008/03/13 21:23:27 steve
+* Add pipeline step for YUV420.
+*
+* Revision 1.33 2008/03/13 18:56:37 steve
+* Fix compile-time support for dumb 422-to-420
+*
+* Revision 1.32 2008/03/13 18:52:01 steve
+* Pipeline 422 to 420 handling.
+*
+* Revision 1.31 2008/03/13 18:37:45 steve
+* Better YUV422 to YUV420 scaling
+*
+* Revision 1.30 2008/03/13 17:49:31 steve
+* Fix problem with YUV422 CBP prediction for UV planes
+*
+* Add support for YUV420 encoding.
+*
+* Revision 1.29 2008/03/13 00:07:23 steve
+* Encode HP of YUV422
+*
+* Revision 1.28 2008/03/12 21:10:27 steve
+* Encode LP of YUV422
+*
+* Revision 1.27 2008/03/12 00:39:11 steve
+* Rework yuv444_to_yuv422 to match WmpEncApp.
+*
+* Revision 1.26 2008/03/11 22:12:49 steve
+* Encode YUV422 through DC.
+*
+* Revision 1.25 2008/03/06 02:05:49 steve
+* Distributed quantization
+*
+* Revision 1.24 2008/03/05 06:58:10 gus
+* *** empty log message ***
+*
+* Revision 1.23 2008/03/03 02:04:05 steve
+* Get encoding of BD16 correct.
+*
+* Revision 1.22 2008/02/26 23:52:44 steve
+* Remove ident for MS compilers.
+*
+* Revision 1.21 2008/02/04 19:21:36 steve
+* Fix rounding of scaled chroma DC/LP values.
+*
+* Revision 1.20 2008/02/01 22:49:53 steve
+* Handle compress of YUV444 color DCONLY
+*
+* Revision 1.19 2008/01/08 23:56:22 steve
+* Add remaining 444 overlap filtering.
+*
+* Revision 1.18 2008/01/08 01:06:20 steve
+* Add first pass overlap filtering.
+*
+* Revision 1.17 2008/01/05 01:19:55 steve
+* Use secret-handshake version of quantization.
+*
+* Revision 1.16 2008/01/04 22:48:55 steve
+* Quantization division rounds, not truncates.
+*
+* Revision 1.15 2008/01/04 17:07:36 steve
+* API interface for setting QP values.
+*
+* Revision 1.14 2008/01/03 18:07:31 steve
+* Detach prediction mode calculations from prediction.
+*
+* Revision 1.13 2008/01/01 01:07:26 steve
+* Add missing HP prediction.
+*
+* Revision 1.12 2007/12/30 00:16:00 steve
+* Add encoding of HP values.
+*
+* Revision 1.11 2007/12/17 23:02:57 steve
+* Implement MB_CBP encoding.
+*
+* Revision 1.10 2007/12/14 17:10:39 steve
+* HP CBP Prediction
+*
+* Revision 1.9 2007/12/12 00:38:07 steve
+* Encode LP data.
+*
+* Revision 1.8 2007/12/07 16:34:52 steve
+* Use repeat bytes to pad to MB boundary.
+*
+* Revision 1.7 2007/12/06 17:54:59 steve
+* Fix input data block ordering.
+*
+* Revision 1.6 2007/11/30 01:50:58 steve
+* Compression of DCONLY GRAY.
+*
+* Revision 1.5 2007/11/26 01:47:16 steve
+* Add copyright notices per MS request.
+*
+* Revision 1.4 2007/11/16 20:03:58 steve
+* Store MB Quant, not qp_index.
+*
+* Revision 1.3 2007/11/12 23:21:55 steve
+* Infrastructure for frequency mode ordering.
+*
+* Revision 1.2 2007/11/09 22:15:41 steve
+* DC prediction for the encoder.
+*
+* Revision 1.1 2007/11/09 01:18:59 steve
+* Stub strip input processing.
+*
+*/
+
diff --git a/jpegxr/w_tile_frequency.c b/jpegxr/w_tile_frequency.c
new file mode 100644
index 000000000..c379a0646
--- /dev/null
+++ b/jpegxr/w_tile_frequency.c
@@ -0,0 +1,306 @@
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+***********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: w_tile_frequency.c,v 1.1 2009/03/09 12:00:00 dan Exp $")
+#else
+#ident "$Id: w_tile_frequency.c,v 1.1 2009/03/09 21:00:00 dan Exp $"
+#endif
+
+# include "jxr_priv.h"
+# include <assert.h>
+
+void _jxr_w_TILE_DC(jxr_image_t image, struct wbitstream*str,
+ unsigned tx, unsigned ty)
+{
+ unsigned tile_idx;
+ unsigned mx, my;
+ unsigned mb_height;
+ unsigned mb_width;
+ uint8_t bands_present;
+ DEBUG("START TILE_DC at tile=[%u %u] bitpos=%zu\n", tx, ty, _jxr_wbitstream_bitpos(str));
+
+ bands_present = image->bands_present_of_primary;
+
+ /* TILE_STARTCODE == 1 */
+ DEBUG(" DC_TILE_STARTCODE at bitpos=%zu\n", _jxr_wbitstream_bitpos(str));
+ _jxr_wbitstream_uint8(str, 0x00);
+ _jxr_wbitstream_uint8(str, 0x00);
+ _jxr_wbitstream_uint8(str, 0x01);
+ _jxr_wbitstream_uint8(str, 0x00); /* ARBITRARY_BYTE */
+
+ /* Write out the tile header (which includes sub-headers for
+ all the major passes). */
+
+ _jxr_w_TILE_HEADER_DC(image, str, 0, tx, ty);
+ if (ALPHACHANNEL_FLAG(image)) {
+ _jxr_w_TILE_HEADER_DC(image->alpha, str, 1, tx, ty);
+ }
+
+ /* Now form and write out all the compressed data for the
+ tile. This involves scanning the macroblocks, and the
+ blocks within the macroblocks, generating bits as we go. */
+
+ mb_height = EXTENDED_HEIGHT_BLOCKS(image);
+ mb_width = EXTENDED_WIDTH_BLOCKS(image);
+
+ if (TILING_FLAG(image)) {
+ mb_height = image->tile_row_height[ty];
+ mb_width = image->tile_column_width[tx];
+ }
+
+ DEBUG(" TILE_DC at [%d %d] is %u x %u MBs\n", tx, ty, mb_width, mb_height);
+ for (my = 0 ; my < mb_height ; my += 1) {
+
+ _jxr_wflush_mb_strip(image, tx, ty, my, 1);
+
+ for (mx = 0 ; mx < mb_width ; mx += 1) {
+
+ _jxr_w_MB_DC(image, str, 0 /* IsCurrPlaneAlphaFlag = FALSE */, tx, ty, mx, my);
+ if (ALPHACHANNEL_FLAG(image)) {
+ _jxr_w_MB_DC(image->alpha, str, 1 /* IsCurrPlaneAlphaFlag = TRUE */, tx, ty, mx, my);
+ }
+ }
+ }
+
+ tile_idx = ty * image->tile_columns + tx;
+
+ _jxr_wbitstream_syncbyte(str);
+ _jxr_wbitstream_flush(str);
+ DEBUG("END TILE_DC\n");
+}
+
+void _jxr_w_TILE_LP(jxr_image_t image, struct wbitstream*str,
+ unsigned tx, unsigned ty)
+{
+ unsigned tile_idx;
+ unsigned mx, my;
+ unsigned mb_height;
+ unsigned mb_width;
+ uint8_t bands_present;
+ DEBUG("START TILE_LP at tile=[%u %u] bitpos=%zu\n", tx, ty, _jxr_wbitstream_bitpos(str));
+
+ bands_present = image->bands_present_of_primary;
+
+ if (bands_present < 3 /* LOWPASS */) {
+ /* TILE_STARTCODE == 1 */
+ DEBUG(" LP_TILE_STARTCODE at bitpos=%zu\n", _jxr_wbitstream_bitpos(str));
+ _jxr_wbitstream_uint8(str, 0x00);
+ _jxr_wbitstream_uint8(str, 0x00);
+ _jxr_wbitstream_uint8(str, 0x01);
+ _jxr_wbitstream_uint8(str, 0x00); /* ARBITRARY_BYTE */
+
+ _jxr_w_TILE_HEADER_LOWPASS(image, str, 0, tx, ty);
+ if (ALPHACHANNEL_FLAG(image)) {
+ _jxr_w_TILE_HEADER_LOWPASS(image->alpha, str, 1, tx, ty);
+ }
+ }
+
+ /* Now form and write out all the compressed data for the
+ tile. This involves scanning the macroblocks, and the
+ blocks within the macroblocks, generating bits as we go. */
+
+ mb_height = EXTENDED_HEIGHT_BLOCKS(image);
+ mb_width = EXTENDED_WIDTH_BLOCKS(image);
+
+ if (TILING_FLAG(image)) {
+ mb_height = image->tile_row_height[ty];
+ mb_width = image->tile_column_width[tx];
+ }
+
+ DEBUG(" TILE_LP at [%d %d] is %u x %u MBs\n", tx, ty, mb_width, mb_height);
+ for (my = 0 ; my < mb_height ; my += 1) {
+
+ _jxr_wflush_mb_strip(image, tx, ty, my, 0);
+
+ for (mx = 0 ; mx < mb_width ; mx += 1) {
+
+ if (bands_present<3 /* LOWPASS */) {
+ if (image->num_lp_qps>1 && !image->lp_use_dc_qp) {
+ unsigned qp_index = _jxr_select_lp_index(image, tx,ty,mx,my);
+ DEBUG(" DECODE_QP_INDEX(%d) --> %u\n", image->num_lp_qps, qp_index);
+ _jxr_w_ENCODE_QP_INDEX(image, str, tx, ty, mx, my, image->num_lp_qps, qp_index);
+ }
+
+ _jxr_w_MB_LP(image, str, 0 /* IsCurrPlaneAlphaFlag = FALSE */, tx, ty, mx, my);
+ if (ALPHACHANNEL_FLAG(image)) {
+ _jxr_w_MB_LP(image->alpha, str, 1 /* IsCurrPlaneAlphaFlag = TRUE */, tx, ty, mx, my);
+ }
+ }
+ }
+ }
+
+ tile_idx = ty * image->tile_columns + tx;
+
+ _jxr_wbitstream_syncbyte(str);
+ _jxr_wbitstream_flush(str);
+ DEBUG("END TILE_LP\n");
+}
+
+void _jxr_w_TILE_HP_FLEX(jxr_image_t image, struct wbitstream*str,
+ unsigned tx, unsigned ty)
+{
+ unsigned tile_idx;
+ uint8_t bands_present ;
+ struct wbitstream strFP;
+ FILE*fdFP;
+ unsigned mx, my;
+ unsigned mb_height;
+ unsigned mb_width;
+ DEBUG("START TILE_HP_FLEX at tile=[%u %u] bitpos=%zu\n", tx, ty, _jxr_wbitstream_bitpos(str));
+
+ bands_present = image->bands_present_of_primary;
+
+ fdFP = fopen("fp.tmp", "wb");
+ _jxr_wbitstream_initialize(&strFP, fdFP);
+
+ if (bands_present < 2 /* HIGHPASS */) {
+ /* TILE_STARTCODE == 1 */
+ DEBUG(" HP_TILE_STARTCODE at bitpos=%zu\n", _jxr_wbitstream_bitpos(str));
+ _jxr_wbitstream_uint8(str, 0x00);
+ _jxr_wbitstream_uint8(str, 0x00);
+ _jxr_wbitstream_uint8(str, 0x01);
+ _jxr_wbitstream_uint8(str, 0x00); /* ARBITRARY_BYTE */
+
+ _jxr_w_TILE_HEADER_HIGHPASS(image, str, 0, tx, ty);
+ if (ALPHACHANNEL_FLAG(image)) {
+ _jxr_w_TILE_HEADER_HIGHPASS(image->alpha, str, 1, tx, ty);
+ }
+ }
+
+ if (bands_present == 0 /* ALL */) {
+ /* TILE_STARTCODE == 1 */
+ DEBUG(" FLEX_TILE_STARTCODE at bitpos=%zu\n", _jxr_wbitstream_bitpos(&strFP));
+ _jxr_wbitstream_uint8(&strFP, 0x00);
+ _jxr_wbitstream_uint8(&strFP, 0x00);
+ _jxr_wbitstream_uint8(&strFP, 0x01);
+ _jxr_wbitstream_uint8(&strFP, 0x00); /* ARBITRARY_BYTE */
+
+ if (TRIM_FLEXBITS_FLAG(image)) {
+ _jxr_wbitstream_uint4(&strFP, image->trim_flexbits);
+ }
+ }
+
+ /* Now form and write out all the compressed data for the
+ tile. This involves scanning the macroblocks, and the
+ blocks within the macroblocks, generating bits as we go. */
+
+ mb_height = EXTENDED_HEIGHT_BLOCKS(image);
+ mb_width = EXTENDED_WIDTH_BLOCKS(image);
+
+ if (TILING_FLAG(image)) {
+ mb_height = image->tile_row_height[ty];
+ mb_width = image->tile_column_width[tx];
+ }
+
+ DEBUG(" TILE_HP_FLEX at [%d %d] is %u x %u MBs\n", tx, ty, mb_width, mb_height);
+ for (my = 0 ; my < mb_height ; my += 1) {
+
+ _jxr_wflush_mb_strip(image, tx, ty, my, 0);
+
+ for (mx = 0 ; mx < mb_width ; mx += 1) {
+
+ if (bands_present<2 /* HIGHPASS */) {
+ if (image->num_hp_qps>1 && !image->hp_use_lp_qp) {
+ unsigned qp_index = _jxr_select_hp_index(image, tx,ty,mx,my);
+ DEBUG(" DECODE_QP_INDEX(%d) --> %u\n", image->num_hp_qps, qp_index);
+ _jxr_w_ENCODE_QP_INDEX(image, str, tx, ty, mx, my, image->num_hp_qps, qp_index);
+ }
+
+ _jxr_w_MB_CBP(image, str, 0 /* IsCurrPlaneAlphaFlag = FALSE */, tx, ty, mx, my);
+ if (bands_present == 0 /* ALL */) {
+ _jxr_w_MB_HP(image, str, 0 /* IsCurrPlaneAlphaFlag = FALSE */, tx, ty, mx, my, &strFP);
+ }
+ else {
+ _jxr_w_MB_HP(image, str, 0 /* IsCurrPlaneAlphaFlag = FALSE */, tx, ty, mx, my, 0);
+ }
+
+ if (ALPHACHANNEL_FLAG(image)) {
+ _jxr_w_MB_CBP(image->alpha, str, 1 /* IsCurrPlaneAlphaFlag = TRUE */, tx, ty, mx, my);
+ if (bands_present == 0 /* ALL */) {
+ _jxr_w_MB_HP(image->alpha, str, 1 /* IsCurrPlaneAlphaFlag = TRUE */, tx, ty, mx, my, &strFP);
+ }
+ else {
+ _jxr_w_MB_HP(image->alpha, str, 1 /* IsCurrPlaneAlphaFlag = TRUE */, tx, ty, mx, my, 0);
+ }
+ }
+ }
+ }
+ }
+
+ tile_idx = ty * image->tile_columns + tx;
+
+ _jxr_wbitstream_syncbyte(str);
+ _jxr_wbitstream_flush(str);
+ image->tile_index_table[tile_idx * (4 - bands_present) + 2] = str->write_count;
+
+ _jxr_wbitstream_syncbyte(&strFP);
+ _jxr_wbitstream_flush(&strFP);
+ fclose(fdFP);
+ if (bands_present == 0 /* ALL */) {
+ struct rbitstream strFPRead;
+ FILE*fdFPRead = fopen("fp.tmp", "rb");
+ size_t idx;
+ _jxr_rbitstream_initialize(&strFPRead, fdFPRead);
+
+ for (idx = 0; idx < strFP.write_count; idx++) {
+ _jxr_wbitstream_uint8(str, _jxr_rbitstream_uint8(&strFPRead));
+ }
+ fclose(fdFPRead);
+ _jxr_wbitstream_flush(str);
+ image->tile_index_table[tile_idx * (4 - bands_present) + 3] = str->write_count;
+ }
+ /* delete file associated with CodedTiles */
+ remove("fp.tmp");
+
+ _jxr_wbitstream_flush(str);
+ DEBUG("END TILE_HP_FLEX\n");
+}
+
+/*
+* $Log: w_tile_frequency.c,v $
+* Revision 1.2 2009/05/29 12:00:00 microsoft
+* Reference Software v1.6 updates.
+*
+* Revision 1.1 2009/04/13 12:00:00 microsoft
+* Reference Software v1.5 updates.
+*
+*/
+
diff --git a/jpegxr/w_tile_spatial.c b/jpegxr/w_tile_spatial.c
new file mode 100644
index 000000000..fbc942d60
--- /dev/null
+++ b/jpegxr/w_tile_spatial.c
@@ -0,0 +1,306 @@
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+**********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: w_tile_spatial.c,v 1.47 2008/03/20 18:11:25 steve Exp $")
+#else
+#ident "$Id: w_tile_spatial.c,v 1.47 2008/03/20 18:11:25 steve Exp $"
+#endif
+
+# include "jxr_priv.h"
+# include <stdlib.h>
+# include <assert.h>
+
+
+void _jxr_w_TILE_SPATIAL(jxr_image_t image, struct wbitstream*str,
+ unsigned tx, unsigned ty)
+{
+ unsigned mx, my;
+ unsigned plane_idx, num_planes;
+ unsigned mb_height;
+ unsigned mb_width;
+ DEBUG("START TILE_SPATIAL at tile=[%u %u] bitpos=%zu\n", tx, ty, _jxr_wbitstream_bitpos(str));
+
+ /* TILE_STARTCODE == 1 */
+ DEBUG(" TILE_STARTCODE at bitpos=%zu\n", _jxr_wbitstream_bitpos(str));
+ _jxr_wbitstream_uint8(str, 0x00);
+ _jxr_wbitstream_uint8(str, 0x00);
+ _jxr_wbitstream_uint8(str, 0x01);
+ _jxr_wbitstream_uint8(str, 0x00); /* ARBITRARY_BYTE */
+
+ if (TRIM_FLEXBITS_FLAG(image)) {
+ _jxr_wbitstream_uint4(str, image->trim_flexbits);
+ }
+
+ /* Write out the tile header (which includes sub-headers for
+ all the major passes). */
+
+ _jxr_w_TILE_HEADER_DC(image, str, 0, tx, ty);
+ if (image->bands_present != 3 /* DCONLY */) {
+ _jxr_w_TILE_HEADER_LOWPASS(image, str, 0, tx, ty);
+
+ if (image->bands_present != 2 /* NO_HIGHPASS */) {
+ _jxr_w_TILE_HEADER_HIGHPASS(image, str, 0, tx, ty);
+ }
+ }
+
+ if (ALPHACHANNEL_FLAG(image)) {
+ _jxr_w_TILE_HEADER_DC(image->alpha, str, 1, tx, ty);
+ if (image->bands_present != 3 /* DCONLY */) {
+ _jxr_w_TILE_HEADER_LOWPASS(image->alpha, str, 1, tx, ty);
+
+ if (image->bands_present != 2 /* NO_HIGHPASS */) {
+ _jxr_w_TILE_HEADER_HIGHPASS(image->alpha, str, 1, tx, ty);
+ }
+ }
+ }
+
+
+ /* Now form and write out all the compressed data for the
+ tile. This involves scanning the macroblocks, and the
+ blocks within the macroblocks, generating bits as we go. */
+
+ mb_height = EXTENDED_HEIGHT_BLOCKS(image);
+ mb_width = EXTENDED_WIDTH_BLOCKS(image);
+
+ if (TILING_FLAG(image)) {
+ mb_height = image->tile_row_height[ty];
+ mb_width = image->tile_column_width[tx];
+ }
+
+ DEBUG(" TILE_SPATIAL at [%d %d] is %u x %u MBs\n", tx, ty, mb_width, mb_height);
+ num_planes = ((ALPHACHANNEL_FLAG(image)) ? 2 : 1);
+
+ for (my = 0 ; my < mb_height ; my += 1) {
+
+ _jxr_wflush_mb_strip(image, tx, ty, my, 1);
+
+ for (mx = 0 ; mx < mb_width ; mx += 1)
+ for (plane_idx = 0; plane_idx < num_planes; plane_idx ++) {
+
+ jxr_image_t plane = (plane_idx == 0 ? image : image->alpha);
+ if (plane->bands_present!=3) {
+ if (plane->num_lp_qps>1 && !plane->lp_use_dc_qp) {
+ unsigned qp_index = _jxr_select_lp_index(plane, tx,ty,mx,my);
+ DEBUG(" DECODE_QP_INDEX(%d) --> %u\n", plane->num_lp_qps, qp_index);
+ _jxr_w_ENCODE_QP_INDEX(plane, str, tx, ty, mx, my, plane->num_lp_qps, qp_index);
+ }
+ if (plane->bands_present!=2 && plane->num_hp_qps>1 && !plane->hp_use_lp_qp) {
+ unsigned qp_index = _jxr_select_hp_index(plane, tx,ty,mx,my);
+ DEBUG(" DECODE_QP_INDEX(%d) --> %u\n", plane->num_hp_qps, qp_index);
+ _jxr_w_ENCODE_QP_INDEX(plane, str, tx, ty, mx, my, plane->num_hp_qps, qp_index);
+ }
+ }
+
+ _jxr_w_MB_DC(plane, str, 0, tx, ty, mx, my);
+ if (plane->bands_present != 3 /* DCONLY */) {
+ _jxr_w_MB_LP(plane, str, 0, tx, ty, mx, my);
+ if (plane->bands_present != 2 /* NOHIGHPASS */) {
+ _jxr_w_MB_CBP(plane, str, 0, tx, ty, mx, my);
+ _jxr_w_MB_HP(plane, str, 0, tx, ty, mx, my, 0);
+
+ /* In SPATIAL mode, the MB_HP block
+ will include the FLEXBITS. DO NOT
+ include the MB_FLEXBITS separately. */
+ }
+ }
+ }
+ }
+
+ _jxr_wbitstream_syncbyte(str);
+ _jxr_wbitstream_flush(str);
+ DEBUG("END TILE_SPATIAL\n");
+}
+
+
+/*
+* $Log: w_tile_spatial.c,v $
+* Revision 1.49 2009/05/29 12:00:00 microsoft
+* Reference Software v1.6 updates.
+*
+* Revision 1.48 2009/04/13 12:00:00 microsoft
+* Reference Software v1.5 updates.
+*
+* Revision 1.47 2008/03/20 18:11:25 steve
+* Handle case of NumLPQP==1 and NumHPQPS>1
+*
+* Revision 1.46 2008/03/18 18:36:56 steve
+* Support compress of CMYK images.
+*
+* Revision 1.45 2008/03/13 17:49:31 steve
+* Fix problem with YUV422 CBP prediction for UV planes
+*
+* Add support for YUV420 encoding.
+*
+* Revision 1.44 2008/03/13 00:07:23 steve
+* Encode HP of YUV422
+*
+* Revision 1.43 2008/03/12 21:10:27 steve
+* Encode LP of YUV422
+*
+* Revision 1.42 2008/03/06 22:47:40 steve
+* Clean up parsing/encoding of QP counts
+*
+* Revision 1.41 2008/03/06 19:21:59 gus
+* *** empty log message ***
+*
+* Revision 1.40 2008/03/06 02:05:49 steve
+* Distributed quantization
+*
+* Revision 1.39 2008/03/05 00:31:18 steve
+* Handle UNIFORM/IMAGEPLANE_UNIFORM compression.
+*
+* Revision 1.38 2008/02/28 18:50:31 steve
+* Portability fixes.
+*
+* Revision 1.37 2008/02/26 23:52:44 steve
+* Remove ident for MS compilers.
+*
+* Revision 1.36 2008/02/24 17:42:33 steve
+* Remove dead code.
+*
+* Revision 1.35 2008/02/23 01:55:52 steve
+* CBP REFINE is more complex when CHR is involved.
+*
+* Revision 1.34 2008/02/22 23:54:15 steve
+* Encode large NUM_BLKCBP values.
+*
+* Revision 1.33 2008/02/22 23:08:15 steve
+* Remove dead code.
+*
+* Revision 1.32 2008/02/22 23:01:33 steve
+* Compress macroblock HP CBP packets.
+*
+* Revision 1.31 2008/02/05 23:18:26 steve
+* Fix cbplp encoding is backwards.
+*
+* Revision 1.30 2008/02/05 19:14:42 steve
+* Encode LP values of YUV444 data.
+*
+* Revision 1.29 2008/02/01 22:49:53 steve
+* Handle compress of YUV444 color DCONLY
+*
+* Revision 1.28 2008/01/07 16:18:54 steve
+* Shift out trimmed flexbits.
+*
+* Revision 1.27 2008/01/06 01:29:28 steve
+* Add support for TRIM_FLEXBITS in compression.
+*
+* Revision 1.26 2008/01/05 02:11:54 steve
+* Add FLEXBITS support.
+*
+* Revision 1.25 2008/01/04 19:34:05 steve
+* Fix DecNumBlkCBP table adaptation.
+*
+* Revision 1.24 2008/01/03 18:07:31 steve
+* Detach prediction mode calculations from prediction.
+*
+* Revision 1.23 2008/01/02 21:13:58 steve
+* Extract HP model bits accounts for sign.
+*
+* Revision 1.22 2008/01/02 21:02:55 steve
+* Account for model_bits while encoding HP values.
+*
+* Revision 1.21 2008/01/01 23:13:00 steve
+* Fix AdaptiveHPPermute totals counting.
+*
+* Revision 1.20 2008/01/01 01:07:26 steve
+* Add missing HP prediction.
+*
+* Revision 1.19 2007/12/30 00:16:00 steve
+* Add encoding of HP values.
+*
+* Revision 1.18 2007/12/17 23:02:57 steve
+* Implement MB_CBP encoding.
+*
+* Revision 1.17 2007/12/14 21:33:39 steve
+* Process LPInput values in sign-magnitude form.
+*
+* Revision 1.16 2007/12/14 17:10:39 steve
+* HP CBP Prediction
+*
+* Revision 1.15 2007/12/13 19:27:36 steve
+* Careful of small negative LP values that are all refinement.
+*
+* Revision 1.14 2007/12/13 18:01:09 steve
+* Stubs for HP encoding.
+*
+* Revision 1.13 2007/12/12 00:38:07 steve
+* Encode LP data.
+*
+* Revision 1.12 2007/12/07 01:20:34 steve
+* Fix adapt not adapting on line ends.
+*
+* Revision 1.11 2007/12/06 23:12:41 steve
+* Stubs for LP encode operations.
+*
+* Revision 1.10 2007/12/06 17:55:30 steve
+* Fix AbsLevelInd tabel select and adaptation.
+*
+* Revision 1.9 2007/12/05 02:18:01 steve
+* Formatting of nil LP values.
+*
+* Revision 1.8 2007/12/04 23:44:02 steve
+* Calculation of encoded IS_DC_CH accounts for sign.
+*
+* Revision 1.7 2007/12/04 22:06:10 steve
+* Infrastructure for encoding LP.
+*
+* Revision 1.6 2007/11/30 01:50:58 steve
+* Compression of DCONLY GRAY.
+*
+* Revision 1.5 2007/11/26 01:47:16 steve
+* Add copyright notices per MS request.
+*
+* Revision 1.4 2007/11/09 01:18:59 steve
+* Stub strip input processing.
+*
+* Revision 1.3 2007/11/08 19:38:38 steve
+* Get stub DCONLY compression to work.
+*
+* Revision 1.2 2007/11/08 02:52:33 steve
+* Some progress in some encoding infrastructure.
+*
+* Revision 1.1 2007/06/06 17:19:13 steve
+* Introduce to CVS.
+*
+*/
+
diff --git a/jpegxr/x_strip.c b/jpegxr/x_strip.c
new file mode 100644
index 000000000..6e047ec52
--- /dev/null
+++ b/jpegxr/x_strip.c
@@ -0,0 +1,86 @@
+
+/*************************************************************************
+*
+* This software module was originally contributed by Microsoft
+* Corporation in the course of development of the
+* ITU-T T.832 | ISO/IEC 29199-2 ("JPEG XR") format standard for
+* reference purposes and its performance may not have been optimized.
+*
+* This software module is an implementation of one or more
+* tools as specified by the JPEG XR standard.
+*
+* ITU/ISO/IEC give You a royalty-free, worldwide, non-exclusive
+* copyright license to copy, distribute, and make derivative works
+* of this software module or modifications thereof for use in
+* products claiming conformance to the JPEG XR standard as
+* specified by ITU-T T.832 | ISO/IEC 29199-2.
+*
+* ITU/ISO/IEC give users the same free license to this software
+* module or modifications thereof for research purposes and further
+* ITU/ISO/IEC standardization.
+*
+* Those intending to use this software module in products are advised
+* that its use may infringe existing patents. ITU/ISO/IEC have no
+* liability for use of this software module or modifications thereof.
+*
+* Copyright is not released for products that do not conform to
+* to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* Microsoft Corporation retains full right to modify and use the code
+* for its own purpose, to assign or donate the code to a third party,
+* and to inhibit third parties from using the code for products that
+* do not conform to the JPEG XR standard as specified by ITU-T T.832 |
+* ISO/IEC 29199-2.
+*
+* This copyright notice must be included in all copies or derivative
+* works.
+*
+* Copyright (c) ITU-T/ISO/IEC 2008, 2009.
+***********************************************************************/
+
+#ifdef _MSC_VER
+#pragma comment (user,"$Id: x_strip.c,v 1.4 2008/03/05 06:58:10 gus Exp $")
+#else
+#ident "$Id: x_strip.c,v 1.4 2008/03/05 06:58:10 gus Exp $"
+#endif
+
+# include "jxr_priv.h"
+# include <assert.h>
+
+void _jxr_clear_strip_cur(jxr_image_t image)
+{
+ int ch;
+ assert(image->num_channels > 0);
+ for (ch = 0 ; ch < image->num_channels ; ch += 1) {
+ unsigned idx;
+ for (idx = 0 ; idx < EXTENDED_WIDTH_BLOCKS(image) ; idx += 1) {
+ int jdx;
+ for (jdx = 0 ; jdx < 256 ; jdx += 1)
+ image->strip[ch].cur[idx].data[jdx] = 0;
+ }
+ }
+}
+
+/*
+* $Log: x_strip.c,v $
+* Revision 1.6 2009/05/29 12:00:00 microsoft
+* Reference Software v1.6 updates.
+*
+* Revision 1.5 2009/04/13 12:00:00 microsoft
+* Reference Software v1.5 updates.
+*
+* Revision 1.4 2008/03/05 06:58:10 gus
+* *** empty log message ***
+*
+* Revision 1.3 2008/02/26 23:52:45 steve
+* Remove ident for MS compilers.
+*
+* Revision 1.2 2007/11/26 01:47:16 steve
+* Add copyright notices per MS request.
+*
+* Revision 1.1 2007/11/12 23:21:55 steve
+* Infrastructure for frequency mode ordering.
+*
+*/
+