summaryrefslogtreecommitdiff
path: root/jpegxr
diff options
context:
space:
mode:
authorChris Liddell <chris.liddell@artifex.com>2013-07-23 16:24:19 +0100
committerChris Liddell <chris.liddell@artifex.com>2015-07-20 18:21:17 +0100
commit6948650efd3fb9e2a70b8cf16aca57e9d0b7eb0a (patch)
tree5c2a1c671c1d4521f8a770d1e69e3d4342718030 /jpegxr
parent7fd9e0be26e67c36f87733bc89ea07dc26d9f839 (diff)
downloadghostpdl-6948650efd3fb9e2a70b8cf16aca57e9d0b7eb0a.tar.gz
Commit of build_consolidation branch
Squashed into one commit (see branch for details of the evolution of the branch). This brings gpcl6 and gxps into the Ghostscript build system, and a shared set of graphics library object files for all the interpreters. Also, brings the same configuration options to the pcl and xps products as we have for Ghostscript.
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.
+*
+*/
+