commit 41ecc696ca3e4b4ec4a5ee109704be61267a551c Author: Patrick Vogler Date: Tue Mar 5 14:56:22 2024 +0100 Initial commit diff --git a/1-bwc/CMakeLists.txt b/1-bwc/CMakeLists.txt new file mode 100755 index 0000000..d0d4735 --- /dev/null +++ b/1-bwc/CMakeLists.txt @@ -0,0 +1,201 @@ +#*================================================================================================*# +#| |# +#| /$$$$$$$ /$$ /$$ /$$ /$$ |# +#| | $$__ $$|__/ | $$ /$ | $$| $$ |# +#| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ |# +#| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ |# +#| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ |# +#| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ |# +#| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ |# +#| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ |# +#| /$$ \ $$ | $$ |# +#| | $$$$$$/ | $$ |# +#| \______/ |__/ |# +#| |# +#| DESCRIPTION: |# +#| ------------ |# +#| |# +#| Defines the global cmake script for the Big Whoop compression algorithm. |# +#| |# +#| -------------------------------------------------------------------------------------------- |# +#| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart |# +#| |# +#| Redistribution and use in source and binary forms, with or without modification, are |# +#| permitted provided that the following conditions are met: |# +#| |# +#| (1) Redistributions of source code must retain the above copyright notice, this list of |# +#| conditions and the following disclaimer. |# +#| |# +#| (2) Redistributions in binary form must reproduce the above copyright notice, this list |# +#| of conditions and the following disclaimer in the documentation and/or other |# +#| materials provided with the distribution. |# +#| |# +#| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS |# +#| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |# +#| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |# +#| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |# +#| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |# +#| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |# +#| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |# +#| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |# +#| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |# +#| |# +#*================================================================================================*# +#----------------------------------------------------------# +# Check if the version requirement for cmake is met. # +#----------------------------------------------------------# +cmake_minimum_required(VERSION 3.5.1) + +#----------------------------------------------------------# +# Set the project name and description. # +#----------------------------------------------------------# +project(BWC LANGUAGES C) +set(PROJECT_DESCRIPTION "Compression algorithm for IEEE 754 datasets") + +#----------------------------------------------------------# +# Check that the current build is not a in-source build. # +#----------------------------------------------------------# +if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) + message(FATAL_ERROR "In-source builds are prohibited. Please create a separate build directory") +endif() + +#----------------------------------------------------------# +# Save the bwc.c file in a temporary variable and match # +# the current version number with a regular expression. # +#----------------------------------------------------------# +file(READ ${CMAKE_CURRENT_SOURCE_DIR}/src/library/libbwc.c _bwc_c_contents) +string(REGEX MATCH "V[ \t]+([0-9]+).([0-9]+).([0-9]+)" _ ${ver} ${_bwc_c_contents}) +set(BWC_VERSION_MAJOR ${CMAKE_MATCH_1}) +set(BWC_VERSION_MINOR ${CMAKE_MATCH_2}) +set(BWC_VERSION_PATCH ${CMAKE_MATCH_3}) +set(BWC_VERSION "${BWC_VERSION_MAJOR}.${BWC_VERSION_MINOR}.${BWC_VERSION_PATCH}") + +#----------------------------------------------------------# +# Setup a user-specified option used to control the sample # +# precision during compression. The standard option is # +# set to double precision. # +#----------------------------------------------------------# +set(PREC "Double" CACHE STRING "User-specified option used to control\ + the precision during compression") + +#----------------------------------------------------------# +# Inlude the GNU standard installation directories module # +# to set up the output directories. # +#----------------------------------------------------------# +include(GNUInstallDirs) + +#----------------------------------------------------------# +# Set up the output directories for the Big Whoop library # +# and utility binaries. # +#----------------------------------------------------------# +list(INSERT CMAKE_MODULE_PATH 0 "${BWC_SOURCE_DIR}/cmake") +if(${TOOL}) + if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BWC_SOURCE_DIR}/${CMAKE_INSTALL_BINDIR}) + endif() +endif() +if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${BWC_SOURCE_DIR}/${CMAKE_INSTALL_LIBDIR}) +endif() +if(NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${BWC_SOURCE_DIR}/${CMAKE_INSTALL_LIBDIR}) +endif() + +#----------------------------------------------------------# +# Set the target installation directory of the config-file # +# packaging configuration files. # +#----------------------------------------------------------# +set(CMAKE_INSTALL_CMAKEDIR ${CMAKE_INSTALL_LIBDIR}/cmake/bwc + CACHE PATH "Installation directory for config-file package cmake files") + +#----------------------------------------------------------# +# Suggest the C standard (C99) used by the compiler. # +#----------------------------------------------------------# +if(NOT CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 11) +endif() + +message(STATUS "Compiling with C standard: ${CMAKE_C_STANDARD}") + +#----------------------------------------------------------# +# Suggest the C++ standard (CXX98) used by the compiler. # +#----------------------------------------------------------# +# Suggest C++98 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 11) +endif() + +message(STATUS "Compiling with C++ standard: ${CMAKE_CXX_STANDARD}") + +#----------------------------------------------------------# +# Check if the OpenMP package is available for the current # +# setup and set the appropriate C/C++ flags. # +#----------------------------------------------------------# +if("${CMAKE_BUILD_TYPE}" STREQUAL "Release") + find_package(OpenMP) + if (OPENMP_FOUND) + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") + endif() +endif() + +#----------------------------------------------------------# +# Add all necessary compiler warnings for debugging. # +#----------------------------------------------------------# +if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") +endif() + +#----------------------------------------------------------# +# Include the CMake dependent option macro. # +#----------------------------------------------------------# +include(CMakeDependentOption) + +#----------------------------------------------------------# +# Set the -fPIC compile option for static libraries. # +#----------------------------------------------------------# +get_property(SHARED_LIBS_SUPPORTED GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS) +cmake_dependent_option(BUILD_SHARED_LIBS + "Whether or not to build shared libraries" ON + "SHARED_LIBS_SUPPORTED" OFF) + +if(SHARED_LIBS_SUPPORTED) + cmake_dependent_option(BWC_ENABLE_PIC + "Build with Position Independent Code" ON + "NOT BUILD_SHARED_LIBS" ON) +endif() + +if(BWC_ENABLE_PIC) + set(CMAKE_POSITION_INDEPENDENT_CODE ON) +endif() + +#----------------------------------------------------------# +# Add the project source code. # +#----------------------------------------------------------# +add_subdirectory(src/library) + +#----------------------------------------------------------# +# Add the utilities source code if requested. # +#----------------------------------------------------------# +if(${TOOL}) + add_subdirectory(src/tools) +endif() + +#----------------------------------------------------------# +# Config-file packaging # +#----------------------------------------------------------# +export(TARGETS bwclib NAMESPACE bwc:: FILE "bwc-targets.cmake") +configure_file(${PROJECT_SOURCE_DIR}/bwc-config.cmake.in + "${PROJECT_BINARY_DIR}/bwc-config.cmake" @ONLY) +configure_file(${PROJECT_SOURCE_DIR}/bwc-config-version.cmake.in + "${PROJECT_BINARY_DIR}/bwc-config-version.cmake" @ONLY) + +install( FILES "${PROJECT_BINARY_DIR}/bwc-config.cmake" + "${PROJECT_BINARY_DIR}/bwc-config-version.cmake" + DESTINATION ${CMAKE_INSTALL_CMAKEDIR}) + +install( EXPORT bwc-targets + NAMESPACE bwc:: + DESTINATION ${CMAKE_INSTALL_CMAKEDIR}) \ No newline at end of file diff --git a/1-bwc/LICENSE b/1-bwc/LICENSE new file mode 100644 index 0000000..3903c06 --- /dev/null +++ b/1-bwc/LICENSE @@ -0,0 +1,9 @@ +Copyright (c) 2023, High Performance Computing Center - University of Stuttgart + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/1-bwc/Makefile b/1-bwc/Makefile new file mode 100755 index 0000000..4db8802 --- /dev/null +++ b/1-bwc/Makefile @@ -0,0 +1,198 @@ +#*====================================================================================================================*# +#| |# +#| /$$$$$$$ /$$ /$$ /$$ /$$ |# +#| | $$__ $$|__/ | $$ /$ | $$| $$ |# +#| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ |# +#| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ |# +#| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ |# +#| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ |# +#| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ |# +#| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ |# +#| /$$ \ $$ | $$ |# +#| | $$$$$$/ | $$ |# +#| \______/ |__/ |# +#| |# +#| |# +#| Version 0.1.0 |# +#| |# +#| DESCRIPTION: |# +#| ------------ |# +#| Defines a wrapper for the Big Whoop cmake & make tools. This Makefile creates the |# +#| build dir if it does not exist, switches to it and executes cmake and make. |# +#| |# +#| ---------------------------------------------------------------------------------------------------------------- |# +#| |# +#| Copyright (c) 2021, High Performance Computing Center - University of Stuttgart |# +#| |# +#| Redistribution and use in source and binary forms, with or without modification, are permitted provided that the |# +#| following conditions are met: |# +#| |# +#| (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the |# +#| following disclaimer. |# +#| |# +#| (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and |# +#| the following disclaimer in the documentation and/or other materials provided with the distribution. |# +#| |# +#| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED |# +#| WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |# +#| PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY |# +#| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |# +#| PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |# +#| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |# +#| OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |# +#| DAMAGE. |# +#| |# +#*====================================================================================================================*# +#*--------------------------------------------------------*# +# Define special targets for the required build commands. # +#*--------------------------------------------------------*# +.PHONY: clean +.PHONY: help + +.PHONY: static +.PHONY: single + +.PHONY: tool +.PHONY: eas3 +.PHONY: netCDF + +.PHONY: --build_debug + +.PHONY: default +.PHONY: debug +.PHONY: full + +#*--------------------------------------------------------*# +# Initialize the compiler flags used to build the library. # +#*--------------------------------------------------------*# +BUILD_TYPE="Release" + +LINK_TYPE="Dynamic" + +BUILD_PREC="Double" + +BUILD_TOOL="False" + +BUILD_EAS3="False" + +BUILD_NETCDF="False" + +#*--------------------------------------------------------*# +# Define default target. # +#*--------------------------------------------------------*# +default: | build_bwc display + +#*--------------------------------------------------------*# +# Define helper target. # +#*--------------------------------------------------------*# +help: + + @echo "Usage: make [options] [argument] Compile the BigWhoop library using the specified" + @echo " [options] and [argument]. Only one argument is " + @echo " accepted per compile run." + @echo "" + @echo "Arguments:" + @echo "" + @echo " [Type] [Description]" + @echo "" + @echo " debug Compiles BigWhoop and the command line tool with " + @echo " full file support. All relevant debug flags are set." + @echo "" + @echo " full Compiles BigWhoop (with OpenMP enabled if applica-" + @echo " ble) and the command line tool with full file sup-" + @echo " port. Code optimization is set to the highest level." + @echo "" + @echo " clean Removes all files and folders created during a pre-" + @echo " vious compile run." + @echo "" + @echo "Options:" + @echo "" + @echo " [Type] [Description]" + @echo "" + @echo " static Builds BigWhoop as a static library." + @echo "" + @echo " single Compiles the BigWhoop library in single precision" + @echo " mode." + @echo "" + @echo " tool Build the command line tool." + @echo "" + @echo " eas3 Adds support for the eas3 file format to the com-" + @echo " mand line tool." + @echo "" + @echo " netCDF Adds support for the eas3 file format to the com-" + @echo " mand line tool." + +#*--------------------------------------------------------*# +# Define private targets. # +#*--------------------------------------------------------*# +--build_debug: + $(eval BUILD_TYPE="Debug") + +#*--------------------------------------------------------*# +# Define targets used to instrument library properites. # +#*--------------------------------------------------------*# +static: + $(eval LINK_TYPE="Static") + +single: + $(eval BUILD_PREC="Single") + +#*--------------------------------------------------------*# +# Define target used to activate command line tool build. # +#*--------------------------------------------------------*# +tool: + $(eval BUILD_TOOL="True") + + +#*--------------------------------------------------------*# +# Define targets used to activate file format support. # +#*--------------------------------------------------------*# +eas3: + $(eval BUILD_EAS3="True") + +netCDF: + $(eval BUILD_NETCDF="True") + +#*--------------------------------------------------------*# +# Define the wrappers for the compile command targets. # +#*--------------------------------------------------------*# +debug: | clean --build_debug tool eas3 build_bwc display +release: | build_bwc display +full: | clean tool eas3 build_bwc display + +#*--------------------------------------------------------*# +# Define target used to output compile information. # +#*--------------------------------------------------------*# +display: + @echo "==============================================================" + @echo "" + @echo " .:-------------: .:-------------: " + @echo " .+++++++++++++++= :+++++++++++++++- " + @echo " :+++. -++= -++= " + @echo " :+++. -++= -++= " + @echo " -++++++++++++++= -++= -++= " + @echo " .=++---------=++= -++= -++= " + @echo " :+++ :++= -++= -++= " + @echo " .+++=--------=+++---=+++---=+++------------: " + @echo " -=++++++++++++++++++++++++++++++++++++++++- " + @echo "" + @echo "----------------- Successfully Compiled -----------------" + @echo "" + @echo " Build Type: $(BUILD_TYPE)" + @echo " Link Type: $(LINK_TYPE)" + @echo " Precision: $(BUILD_PREC)" + @echo " Utilities: $(BUILD_TOOL)" + @echo "" + @echo " Build date: $(shell date)" + @echo " User: $(USER)" + @echo "" + @echo "==============================================================" + +#*--------------------------------------------------------*# +# Define the main compile command targets. # +#*--------------------------------------------------------*# +build_bwc: + mkdir -p build && cd build && cmake .. "-DCMAKE_BUILD_TYPE=${BUILD_TYPE}" "-DLINK:STRING=${LINK_TYPE}" "-DPREC:STRING=${BUILD_PREC}" "-DTOOL=${BUILD_TOOL}" "-DBUILD_EAS3=${BUILD_EAS3}" "-DBUILD_NETCDF=${BUILD_NETCDF}" && $(MAKE) -j + +clean: + - /bin/rm -rf build/ bin/ lib/ lib64/ include/library/public \ No newline at end of file diff --git a/1-bwc/bwc-config-version.cmake.in b/1-bwc/bwc-config-version.cmake.in new file mode 100644 index 0000000..8a480ef --- /dev/null +++ b/1-bwc/bwc-config-version.cmake.in @@ -0,0 +1,59 @@ +#*================================================================================================*# +#| |# +#| /$$$$$$$ /$$ /$$ /$$ /$$ |# +#| | $$__ $$|__/ | $$ /$ | $$| $$ |# +#| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ |# +#| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ |# +#| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ |# +#| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ |# +#| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ |# +#| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ |# +#| /$$ \ $$ | $$ |# +#| | $$$$$$/ | $$ |# +#| \______/ |__/ |# +#| |# +#| DESCRIPTION: |# +#| ------------ |# +#| |# +#| Config that handles package versioning. |# +#| |# +#| -------------------------------------------------------------------------------------------- |# +#| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart |# +#| |# +#| Redistribution and use in source and binary forms, with or without modification, are |# +#| permitted provided that the following conditions are met: |# +#| |# +#| (1) Redistributions of source code must retain the above copyright notice, this list of |# +#| conditions and the following disclaimer. |# +#| |# +#| (2) Redistributions in binary form must reproduce the above copyright notice, this list |# +#| of conditions and the following disclaimer in the documentation and/or other |# +#| materials provided with the distribution. |# +#| |# +#| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS |# +#| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |# +#| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |# +#| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |# +#| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |# +#| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |# +#| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |# +#| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |# +#| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |# +#| |# +#*================================================================================================*# +set(PACKAGE_VERSION_MAJOR @BWC_VERSION_MAJOR@) +set(PACKAGE_VERSION_MINOR @BWC_VERSION_MINOR@) +set(PACKAGE_VERSION_PATCH @BWC_VERSION_PATCH@) + +set(PACKAGE_VERSION @BWC_VERSION@) + +# Check whether the requested PACKAGE_FIND_VERSION is compatible +if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION OR + PACKAGE_VERSION_MAJOR GREATER PACKAGE_FIND_VERSION_MAJOR) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if(PACKAGE_VERSION VERSION_EQUAL PACKAGE_FIND_VERSION) + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() \ No newline at end of file diff --git a/1-bwc/bwc-config.cmake.in b/1-bwc/bwc-config.cmake.in new file mode 100644 index 0000000..a92e0ba --- /dev/null +++ b/1-bwc/bwc-config.cmake.in @@ -0,0 +1,61 @@ +#*================================================================================================*# +#| |# +#| /$$$$$$$ /$$ /$$ /$$ /$$ |# +#| | $$__ $$|__/ | $$ /$ | $$| $$ |# +#| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ |# +#| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ |# +#| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ |# +#| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ |# +#| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ |# +#| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ |# +#| /$$ \ $$ | $$ |# +#| | $$$$$$/ | $$ |# +#| \______/ |__/ |# +#| |# +#| DESCRIPTION: |# +#| ------------ |# +#| |# +#| Config file for the bwc package defining the following variables: |# +#| |# +#| BWC_INCLUDE_DIRS - include directories for bwc, |# +#| BWC_LIBRARIES - libraries to link against, |# +#| |# +#| and the following imported targets: |# +#| |# +#| bwc::bwclib |# +#| |# +#| -------------------------------------------------------------------------------------------- |# +#| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart |# +#| |# +#| Redistribution and use in source and binary forms, with or without modification, are |# +#| permitted provided that the following conditions are met: |# +#| |# +#| (1) Redistributions of source code must retain the above copyright notice, this list of |# +#| conditions and the following disclaimer. |# +#| |# +#| (2) Redistributions in binary form must reproduce the above copyright notice, this list |# +#| of conditions and the following disclaimer in the documentation and/or other |# +#| materials provided with the distribution. |# +#| |# +#| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS |# +#| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |# +#| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |# +#| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |# +#| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |# +#| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |# +#| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |# +#| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |# +#| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |# +#| |# +#*================================================================================================*# +include("${CMAKE_CURRENT_LIST_DIR}/bwc-config-version.cmake") + +include(FindPackageHandleStandardArgs) +set(${CMAKE_FIND_PACKAGE_NAME}_CONFIG "${CMAKE_CURRENT_LIST_FILE}") +find_package_handle_standard_args(${CMAKE_FIND_PACKAGE_NAME} CONFIG_MODE) + +if(NOT TARGET bwc::bwclib) + include("${CMAKE_CURRENT_LIST_DIR}/bwc-targets.cmake") + set(BWC_LIBRARIES "bwc::bwclib") + get_target_property(BWC_INCLUDE_DIRS bwc::bwclib INTERFACE_INCLUDE_DIRECTORIES) +endif() diff --git a/1-bwc/docs/img/Headline.svg b/1-bwc/docs/img/Headline.svg new file mode 100644 index 0000000..730cac6 --- /dev/null +++ b/1-bwc/docs/img/Headline.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/1-bwc/docs/img/Logo.svg b/1-bwc/docs/img/Logo.svg new file mode 100644 index 0000000..0097f5a --- /dev/null +++ b/1-bwc/docs/img/Logo.svg @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/1-bwc/docs/templates/header.h b/1-bwc/docs/templates/header.h new file mode 100755 index 0000000..82dc3df --- /dev/null +++ b/1-bwc/docs/templates/header.h @@ -0,0 +1,299 @@ +/*==================================================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| File: header.h || +|| ----- || +|| || +|| DESCRIPTION: || +|| ------------ || +|| DESCRIPTION NEEDED. || +|| || +|| STRUCTS: || +|| -------- || +|| || +|| PUBLIC FUNCTIONS: || +|| ----------------- || +|| || +|| DEVELOPMENT HISTORY: || +|| -------------------- || +|| || +|| Date Author Change Id Release Description Of Change || +|| ---- ------ --------- ------- --------------------- || +|| - Patrick Vogler B87D120 V - header file created || +|| - Patrick Vogler B880CA2 V - header file patched || +|| - Patrick Vogler B87E7E4 V - header file updated || +|| - Patrick Vogler B87F684 V - header file new version || +|| || +|| -------------------------------------------------------------------------------------------------------------------- || +|| || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are permitted provided that the || +|| following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of conditions and || +|| the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions || +|| and the following disclaimer in the documentation and/or other materials provided with the || +|| distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, || +|| INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE || +|| DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, || +|| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR || +|| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, || +|| WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE || +|| USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*==================================================================================================================================*/ +#ifndef HEADER_H +#define HEADER_H + + /************************************************************************************************************\ + || _ _ _ ____ _ _ _ ___ ____ || + || | |\ | | | | | | \ |___ || + || | | \| |___ |___ |__| |__/ |___ || + || || + \************************************************************************************************************/ + + /************************************************************************************************************\ + || _ _ ____ ____ ____ ____ ____ || + || |\/| |__| | |__/ | | [__ || + || | | | | |___ | \ |__| ___] || + || || + \************************************************************************************************************/ + /*----------------------------------------------------------------------------------------------------------*\ + ! DESCRIPTION: ! + ! ------------ ! + ! DESCRIPTION NEEDED ! + ! ! + ! Macros: ! + ! ------- ! + ! Macro Description ! + ! ----- ----------- ! + ! ! + ! ! + ! DEVELOPMENT HISTORY: ! + ! -------------------- ! + ! ! + ! Date Author Change Id Release Description Of Change ! + ! ---- ------ --------- ------- --------------------- ! + ! - Patrick Vogler B87D120 V - Macros created ! + ! - Patrick Vogler B880CA2 V - Macros patched ! + ! - Patrick Vogler B87E7E4 V - Macros updated ! + ! - Patrick Vogler B87F684 V - Macros new version ! + ! ! + \*----------------------------------------------------------------------------------------------------------*/ + + /************************************************************************************************************\ + || ____ ____ _ _ ____ ___ ____ _ _ ___ ____ || + || | | | |\ | [__ | |__| |\ | | [__ || + || |___ |__| | \| ___] | | | | \| | ___] || + || || + \************************************************************************************************************/ + /*----------------------------------------------------------------------------------------------------------*\ + ! DESCRIPTION: ! + ! ------------ ! + ! DESCRIPTION NEEDED ! + ! ! + ! CONSTANTS: ! + ! ----------- ! + ! Constant Description ! + ! -------- ----------- ! + ! ! + ! ! + ! DEVELOPMENT HISTORY: ! + ! -------------------- ! + ! ! + ! Date Author Change Id Release Description Of Change ! + ! ---- ------ --------- ------- --------------------- ! + ! - Patrick Vogler B87D120 V - Constants created ! + ! - Patrick Vogler B880CA2 V - Constants patched ! + ! - Patrick Vogler B87E7E4 V - Constants updated ! + ! - Patrick Vogler B87F684 V - Constants new version ! + ! ! + \*----------------------------------------------------------------------------------------------------------*/ + /************************************************************************************************************\ + || ____ _ _ ___ ____ ____ _ _ ____ _ _ _ ____ ____ _ ____ ___ _ ____ ____ || + || |___ \/ | |___ |__/ |\ | |__| | | | |__| |__/ | |__| |__] | |___ [__ || + || |___ _/\_ | |___ | \ | \| | | |___ \/ | | | \ | | | |__] |___ |___ ___] || + || || + \************************************************************************************************************/ + /*----------------------------------------------------------------------------------------------------------*\ + ! DESCRIPTION: ! + ! ------------ ! + ! DESCRIPTION NEEDED ! + ! ! + ! VARIABLES: ! + ! ----------- ! + ! VARIABLE Description ! + ! -------- ----------- ! + ! ! + ! ! + ! DEVELOPMENT HISTORY: ! + ! -------------------- ! + ! ! + ! Date Author Change Id Release Description Of Change ! + ! ---- ------ --------- ------- --------------------- ! + ! - Patrick Vogler B87D120 V - Variables created ! + ! - Patrick Vogler B880CA2 V - Variables patched ! + ! - Patrick Vogler B87E7E4 V - Variables updated ! + ! - Patrick Vogler B87F684 V - Variables new version ! + ! ! + \*----------------------------------------------------------------------------------------------------------*/ + /************************************************************************************************************\ + || ____ _ _ ___ ____ ____ _ _ ____ _ ____ ____ _ _ ____ ___ ____ _ _ ___ ____ || + || |___ \/ | |___ |__/ |\ | |__| | | | | |\ | [__ | |__| |\ | | [__ || + || |___ _/\_ | |___ | \ | \| | | |___ |___ |__| | \| ___] | | | | \| | ___] || + || || + \************************************************************************************************************/ + /*----------------------------------------------------------------------------------------------------------*\ + ! DESCRIPTION: ! + ! ------------ ! + ! DESCRIPTION NEEDED ! + ! ! + ! CONSTANTS: ! + ! ----------- ! + ! Constant Description ! + ! -------- ----------- ! + ! ! + ! ! + ! DEVELOPMENT HISTORY: ! + ! -------------------- ! + ! ! + ! Date Author Change Id Release Description Of Change ! + ! ---- ------ --------- ------- --------------------- ! + ! - Patrick Vogler B87D120 V - Constants created ! + ! - Patrick Vogler B880CA2 V - Constants patched ! + ! - Patrick Vogler B87E7E4 V - Constants updated ! + ! - Patrick Vogler B87F684 V - Constants new version ! + ! ! + \*----------------------------------------------------------------------------------------------------------*/ + /************************************************************************************************************\ + || ___ _ _ ___ ____ ____ || + || | \_/ |__] |___ [__ || + || | | | |___ ___] || + || || + \************************************************************************************************************/ + /*----------------------------------------------------------------------------------------------------------*\ + ! STRUCT NAME: Template ! + ! ----------- ! + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! DESCRIPTION NEEDED ! + ! ! + ! PARAMETERS: ! + ! ----------- ! + ! Variable Type Description ! + ! -------- ---- ----------- ! + ! - - - ! + ! ! + ! DEPENDENCIES: ! + ! ------------- ! + ! Variable Type Description ! + ! -------- ---- ----------- ! + ! ! + ! DEVELOPMENT HISTORY: ! + ! -------------------- ! + ! ! + ! Date Author Change Id Release Description Of Change ! + ! ---- ------ --------- ------- --------------------- ! + ! - Patrick Vogler B87D120 V - Struct created ! + ! - Patrick Vogler B880CA2 V - Struct patched ! + ! - Patrick Vogler B87E7E4 V - Struct updated ! + ! - Patrick Vogler B87F684 V - Struct new version ! + ! ! + \*----------------------------------------------------------------------------------------------------------*/ + + /*----------------------------------------------------------------------------------------------------------*\ + ! ENUM NAME: Template ! + ! ----------- ! + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! DESCRIPTION NEEDED ! + ! ! + ! PARAMETERS: ! + ! ----------- ! + ! Variable Type Description ! + ! -------- ---- ----------- ! + ! - - - ! + ! ! + ! DEPENDENCIES: ! + ! ------------- ! + ! Variable Type Description ! + ! -------- ---- ----------- ! + ! ! + ! DEVELOPMENT HISTORY: ! + ! -------------------- ! + ! ! + ! Date Author Change Id Release Description Of Change ! + ! ---- ------ --------- ------- --------------------- ! + ! - Patrick Vogler B87D120 V - Enum created ! + ! - Patrick Vogler B880CA2 V - Enum patched ! + ! - Patrick Vogler B87E7E4 V - Enum updated ! + ! - Patrick Vogler B87F684 V - Enum new version ! + ! ! + \*----------------------------------------------------------------------------------------------------------*/ + + /*----------------------------------------------------------------------------------------------------------*\ + ! UNION NAME: Template ! + ! ----------- ! + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! DESCRIPTION NEEDED ! + ! ! + ! PARAMETERS: ! + ! ----------- ! + ! Variable Type Description ! + ! -------- ---- ----------- ! + ! - - - ! + ! ! + ! DEPENDENCIES: ! + ! ------------- ! + ! Variable Type Description ! + ! -------- ---- ----------- ! + ! ! + ! DEVELOPMENT HISTORY: ! + ! -------------------- ! + ! ! + ! Date Author Change Id Release Description Of Change ! + ! ---- ------ --------- ------- --------------------- ! + ! - Patrick Vogler B87D120 V - Union created ! + ! - Patrick Vogler B880CA2 V - Union patched ! + ! - Patrick Vogler B87E7E4 V - Union updated ! + ! - Patrick Vogler B87F684 V - Union new version ! + ! ! + \*----------------------------------------------------------------------------------------------------------*/ + + /************************************************************************************************************\ + || ___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || + || |__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ || + || | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] || + || || + \************************************************************************************************************/ + + /*----------------------------------------------------------------------------------------------------------*\ + ! TYPE NAME: Template ! + ! ----------- ! + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! DESCRIPTION NEEDED ! + ! ! + \*----------------------------------------------------------------------------------------------------------*/ +#endif \ No newline at end of file diff --git a/1-bwc/docs/templates/source.c b/1-bwc/docs/templates/source.c new file mode 100755 index 0000000..626cde2 --- /dev/null +++ b/1-bwc/docs/templates/source.c @@ -0,0 +1,179 @@ +/*==================================================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| FILE NAME: source.c || +|| || +|| || +|| DESCRIPTION: || +|| ------------ || +|| DESCRIPTION NEEDED. || +|| || +|| FILE REFERENCES: || +|| ---------------- || +|| || +|| Name I/O Description || +|| ---- --- ----------- || +|| none - - || +|| || +|| || +|| PRIVATE FUNCTIONS: || +|| ------------------ || +|| || +|| PUBLIC FUNCTIONS: || +|| ----------------- || +|| || +|| DEVELOPMENT HISTORY: || +|| -------------------- || +|| || +|| Date Author Change Id Release Description Of Change || +|| ---- ------ --------- ------- --------------------- || +|| - Patrick Vogler B87D120 V - source file created || +|| - Patrick Vogler B880CA2 V - source file patched || +|| - Patrick Vogler B87E7E4 V - source file updated || +|| - Patrick Vogler B87F684 V - source file new version || +|| || +|| -------------------------------------------------------------------------------------------------------------------- || +|| || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are permitted provided that the || +|| following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of conditions and || +|| the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions || +|| and the following disclaimer in the documentation and/or other materials provided with the || +|| distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, || +|| INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE || +|| DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, || +|| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR || +|| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, || +|| WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE || +|| USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*==================================================================================================================================*/ + +/************************************************************************************************************\ +|| _ _ _ ____ _ _ _ ___ ____ || +|| | |\ | | | | | | \ |___ || +|| | | \| |___ |___ |__| |__/ |___ || +|| || +\************************************************************************************************************/ +/************************************************************************************************************\ +|| ____ _ _ ___ ____ ____ _ _ ____ _ _ _ ____ ____ _ ____ ___ _ ____ ____ || +|| |___ \/ | |___ |__/ |\ | |__| | | | |__| |__/ | |__| |__] | |___ [__ || +|| |___ _/\_ | |___ | \ | \| | | |___ \/ | | | \ | | | |__] |___ |___ ___] || +|| || +\************************************************************************************************************/ +/************************************************************************************************************\ +|| ____ _ _ ___ ____ ____ _ _ ____ _ ____ ____ _ _ ____ ___ ____ _ _ ___ ____ || +|| |___ \/ | |___ |__/ |\ | |__| | | | | |\ | [__ | |__| |\ | | [__ || +|| |___ _/\_ | |___ | \ | \| | | |___ |___ |__| | \| ___] | | | | \| | ___] || +|| || +\************************************************************************************************************/ + +/************************************************************************************************************\ +|| ___ ____ _ _ _ ____ ___ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || +|| |__] |__/ | | | |__| | |___ |___ | | |\ | | | | | | |\ | [__ || +|| | | \ | \/ | | | |___ | |__| | \| |___ | | |__| | \| ___] || +|| || +\************************************************************************************************************/ +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *template(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! - Patrick Vogler B87D120 V - function created ! +! - Patrick Vogler B880CA2 V - function patched ! +! - Patrick Vogler B87E7E4 V - function updated ! +! - Patrick Vogler B87F684 V - function new version ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ + +/************************************************************************************************************\ +|| ___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || +|| |__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ || +|| | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] || +|| || +\************************************************************************************************************/ + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! - Patrick Vogler B87D120 V - function created ! +! - Patrick Vogler B880CA2 V - function patched ! +! - Patrick Vogler B87E7E4 V - function updated ! +! - Patrick Vogler B87F684 V - function new version ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +/*-----------------------*\ +! DEFINE INT VARIABLES: ! +\*-----------------------*/ +/*-----------------------*\ +! DEFINE FLOAT VARIABLES: ! +\*-----------------------*/ +/*-----------------------*\ +! DEFINE CHAR VARIABLES: ! +\*-----------------------*/ +/*-----------------------*\ +! DEFINE STRUCTS: ! +\*-----------------------*/ +/*--------------------------------------------------------*\ +! COMMENTCOMMENTCOMMENTCOMMENTCOMMENTCOMMENTCOMMENTCOMMENT ! +\*--------------------------------------------------------*/ \ No newline at end of file diff --git a/1-bwc/include/interfaces/reader/eas3.h b/1-bwc/include/interfaces/reader/eas3.h new file mode 100644 index 0000000..9fe0d20 --- /dev/null +++ b/1-bwc/include/interfaces/reader/eas3.h @@ -0,0 +1,360 @@ +/*==================================================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| File: header.h || +|| ----- || +|| || +|| DESCRIPTION: || +|| ------------ || +|| This file defines simple read and write functions used to access conforming eas3 datasets. || +|| || +|| STRUCTS: || +|| -------- || +|| - eas3_std_params || +|| || +|| PUBLIC FUNCTIONS: || +|| ----------------- || +|| - read_eas3 || +|| - write_eas3 || +|| || +|| DEVELOPMENT HISTORY: || +|| -------------------- || +|| || +|| Date Author Change Id Release Description Of Change || +|| ---- ------ --------- ------- --------------------- || +|| - Patrick Vogler B87D120 V 0.1.0 header file created || +|| || +|| -------------------------------------------------------------------------------------------------------------------- || +|| || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are permitted provided that the || +|| following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of conditions and || +|| the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions || +|| and the following disclaimer in the documentation and/or other materials provided with the || +|| distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, || +|| INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE || +|| DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, || +|| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR || +|| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, || +|| WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE || +|| USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*==================================================================================================================================*/ +#ifndef EAS3_H +#define EAS3_H + + /************************************************************************************************************\ + || _ _ _ ____ _ _ _ ___ ____ || + || | |\ | | | | | | \ |___ || + || | | \| |___ |___ |__| |__/ |___ || + || || + \************************************************************************************************************/ + #include + #include + #include + + /************************************************************************************************************\ + || _ _ ____ ____ ____ ____ ____ || + || |\/| |__| | |__/ | | [__ || + || | | | | |___ | \ |__| ___] || + || || + \************************************************************************************************************/ + /*----------------------------------------------------------------------------------------------------------*\ + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These macros are used to identify the spatial and temporal dimensions. ! + ! ! + ! MACROS: ! + ! ------- ! + ! Name Description ! + ! ---- ----------- ! + ! DIM_X, DIM_Y, DIM_Z - Spatial Dimensions ! + ! ! + ! DIM_TS - Temporal Dimension ! + ! ! + ! DIM_ALL - All Dimensions ! + ! ! + ! DEVELOPMENT HISTORY: ! + ! -------------------- ! + ! ! + ! Date Author Change Id Release Description ! + ! ---- ------ --------- ------- ----------- ! + ! 04.12.2017 Patrick Vogler B87D120 V 0.1.0 macros created ! + ! ! + \*----------------------------------------------------------------------------------------------------------*/ + #define DIM_X 1 + #define DIM_Y 2 + #define DIM_Z 4 + #define DIM_TS 8 + #define DIM_ALL 15 + + /*----------------------------------------------------------------------------------------------------------*\ + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These macros are used to instruct the read_eas3_header function. ! + ! ! + ! Macros: ! + ! ------- ! + ! Macro Description ! + ! ----- ----------- ! + ! EAS3_NO_ATTR 1 - Specifies that no attributes are present in the bit- ! + ! stream. ! + ! ! + ! EAS3_ALL_ATTR 2 - Specifies that all attributes are present in the bit- ! + ! bitstream. ! + ! ! + ! ATTRLEN 10 - Defines the number of bytes used to define an attrib- ! + ! ute. ! + ! ! + ! UDEFLEN 20 - Defines the number of bytes used to define a user de- ! + ! fined data. ! + ! ! + ! EAS3_NO_G 1 - Specifies that no geometry data is present in the bit- ! + ! stream. ! + ! ! + ! EAS3_X0DX_G 2 - Specifies that a start value and step size are present ! + ! in the bitstream. ! + ! ! + ! EAS3_UDEF_G 3 - Specifies that ng = number of coordinate data is pres- ! + ! ent in the bitstream. ! + ! ! + ! EAS3_ALL_G 4 - Specifies that an element for every appropriate di- ! + ! mension is present in the bitstream. ! + ! ! + ! EAS3_FULL_G 5 - Specifies that an element for every dimension is pres- ! + ! ent in the bitstream. ! + ! ! + ! EAS3_NO_UDEF 1 - Specifies that no user defined data is present in the ! + ! bitstream. ! + ! ! + ! EAS3_ALL_UDEF 2 - Specifies that all user defined fields are present in ! + ! the bitstream. ! + ! ! + ! EAS3_INT_UDEF 3 - Specifies that an user defined integer field is pres- ! + ! ent in the bitstream. ! + ! ! + ! DEVELOPMENT HISTORY: ! + ! -------------------- ! + ! ! + ! Date Author Change Id Release Description Of Change ! + ! ---- ------ --------- ------- --------------------- ! + ! 20.06.2018 Patrick Vogler B87D120 V 0.1.0 Macros created ! + \*----------------------------------------------------------------------------------------------------------*/ + #define EAS3_NO_ATTR 0x100000000000000 + #define EAS3_ALL_ATTR 0x200000000000000 + + #define EAS2_TYPE 0x100000000000000 + #define EAS3_TYPE 0x200000000000000 + + #define ATTRLEN 10 + #define UDEFLEN 20 + + #define EAS3_NO_G 0x100000000000000 + #define EAS3_X0DX_G 0x200000000000000 + #define EAS3_UDEF_G 0x300000000000000 + #define EAS3_ALL_G 0x400000000000000 + #define EAS3_FULL_G 0x500000000000000 + + #define EAS3_NO_UDEF 0x100000000000000 + #define EAS3_ALL_UDEF 0x200000000000000 + #define EAS3_INT_UDEF 0x300000000000000 + + #define AUX_SIZE 0x8000 + + /************************************************************************************************************\ + || ___ _ _ ___ ____ ____ || + || | \_/ |__] |___ [__ || + || | | | |___ ___] || + || || + \************************************************************************************************************/ + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure is used to read/assemble a packed codestream during coding. The ! + ! byte buffer is flushed to the packed stream as soon as the a single byte has ! + ! been assembled. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + uchar error; // Error flag used during streaming. + + uint64 L; // Number of bytes written to/from stream. + uint64 Lmax; // Size of packed stream. + uint64 size_incr; // Size incrmnt used for stream assembly. + + uint8 T; // Byte buffer. + int8 t; // Byte buffer counter. + + uchar *memory; // Memory handle for packed stream chunck. + } bitstream; + + /*----------------------------------------------------------------------------------------------------------*\ + ! STRUCT NAME: eas3_header ! + ! ----------- ! + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! This structure is used to store the eas3 header information. For a more thorough discussion ! + ! of the eas3 datatype see: ! + ! ! + ! https://wiki.iag.uni-stuttgart.de/eas3wiki/index.php/EAS3_File_Format/de ! + ! ! + ! PARAMETERS: ! + ! ----------- ! + ! Variable Type Description ! + ! -------- ---- ----------- ! + ! file_type unsigned int(64 bit) - Defines an identifier for the EAS type. ! + ! ! + ! accuracy unsigned int(64 bit) - Defines the accuracy of an eas3 file. ! + ! ! + ! nzs unsigned int(64 bit) - Variable defining the temporal size of ! + ! the uncompressed dataset. ! + ! ! + ! npar unsigned int(64 bit) - Defines the number of parameters in the ! + ! eas3 dataset. ! + ! ! + ! ndim1, -2, -3 unsigned int(64 bit) - Variables defining the spatial size of ! + ! the eas3 dataset. ! + ! ! + ! attribute_mode; unsigned int(64 bit) - Defines an identifier used to signal ! + ! the attribute mode of the eas3 file. ! + ! ! + ! gmode_time unsigned int(64 bit) - Defines the geometry mode for the temp- ! + ! oral dimension. ! + ! ! + ! gmode_param unsigned int(64 bit) - Defines the geometry mode for the para- ! + ! meters. ! + ! ! + ! gmode_dim1 unsigned int(64 bit) - Defines the geometry mode for the first ! + ! spatial dimension. ! + ! ! + ! gmode_dim2 unsigned int(64 bit) - Defines the geometry mode for the sec- ! + ! ond spatial dimension. ! + ! ! + ! gmode_dim3 unsigned int(64 bit) - Defines the geometry mode for the third ! + ! spatial dimension. ! + ! ! + ! size_time unsigned int(64 bit) - Defines the geometry array size for the ! + ! temporal dimension. ! + ! ! + ! size_parameter unsigned int(64 bit) - Defines the geometry array size for the ! + ! parameters. ! + ! ! + ! size_dim1 unsigned int(64 bit) - Defines the geometry array size for the ! + ! first spatial dimension. ! + ! ! + ! size_dim2 unsigned int(64 bit) - Defines the geometry array size for the ! + ! second spatial dimension. ! + ! ! + ! size_dim3 unsigned int(64 bit) - Defines the geometry array size for the ! + ! third spatial dimension. ! + ! ! + ! udef_param unsigned int(64 bit) - Defines a marker used to signal which ! + ! user defined parameters are present in ! + ! the eas3 file. ! + ! ! + ! udef_char_size unsigned int(64 bit) - Defines the size for the user defined ! + ! char array. ! + ! ! + ! udef_int_size unsigned int(64 bit) - Defines the size for the user defined ! + ! int array. ! + ! ! + ! udef_real_size unsigned int(64 bit) - Defines the size for the user defined ! + ! real array. ! + ! ! + ! DEPENDENCIES: ! + ! ------------- ! + ! Variable Type Description ! + ! -------- ---- ----------- ! + ! - - - ! + ! ! + ! DEVELOPMENT HISTORY: ! + ! -------------------- ! + ! ! + ! Date Author Change Id Release Description Of Change ! + ! ---- ------ --------- ------- --------------------- ! + ! 20.06.2018 Patrick Vogler B87D120 V 0.1.0 struct created ! + ! ! + \*----------------------------------------------------------------------------------------------------------*/ + typedef struct + { + uint64_t file_type; + uint64_t accuracy; + uint64_t nzs; + uint64_t npar; + uint64_t ndim1; + uint64_t ndim2; + uint64_t ndim3; + uint64_t attribute_mode; + uint64_t gmode_time; + uint64_t gmode_param; + uint64_t gmode_dim1; + uint64_t gmode_dim2; + uint64_t gmode_dim3; + uint64_t size_time; + uint64_t size_parameter; + uint64_t size_dim1; + uint64_t size_dim2; + uint64_t size_dim3; + uint64_t udef_param; + uint64_t udef_char_size; + uint64_t udef_int_size; + uint64_t udef_real_size; + } eas3_std_params; + + /************************************************************************************************************\ + || ___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || + || |__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ || + || | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] || + || || + \************************************************************************************************************/ + /*----------------------------------------------------------------------------------------------------------*\ + ! FUNCTION NAME: bwc_data* read_eas3(const char* const filename) ! + ! -------------- ! + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! This function opens an eas3 file and checks it for its validity. Once the specified file ! + ! has been verified, its header and flow field data is read and stored in the bwc_data ! + ! structure. ! + ! ! + \*----------------------------------------------------------------------------------------------------------*/ + bwc_data* + read_eas3(char *const filename); + + /*----------------------------------------------------------------------------------------------------------*\ + ! FUNCTION NAME: uchar write_eas3(bwc_data *const file, char *const filename) ! + ! -------------- ! + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! This function creates a valid eas3 file from the information stored in the bwc_data ! + ! structure. ! + ! ! + \*----------------------------------------------------------------------------------------------------------*/ + uchar + write_eas3(bwc_data *const file, char *const filename); +#endif \ No newline at end of file diff --git a/1-bwc/include/library/private/bitstream.h b/1-bwc/include/library/private/bitstream.h new file mode 100755 index 0000000..6363775 --- /dev/null +++ b/1-bwc/include/library/private/bitstream.h @@ -0,0 +1,124 @@ +/*================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| DESCRIPTION: || +|| ------------ || +|| || +|| This file describes a set of functions that can be used to create, manipulate || +|| and terminate a bitstream. These functions facilitate the creation or reading || +|| of a compressed bwc codestream and can emit/extract information on a per bit, || +|| symbol (64-bit) or string basis. || +|| || +|| -------------------------------------------------------------------------------------------- || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are || +|| permitted provided that the following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of || +|| conditions and the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || +|| of conditions and the following disclaimer in the documentation and/or other || +|| materials provided with the distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS || +|| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF || +|| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE || +|| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, || +|| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF || +|| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) || +|| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || +|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, || +|| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*================================================================================================*/ +#ifndef BITSTREAM_H +#define BITSTREAM_H + /************************************************************************************************\ + || _ _ _ ____ _ _ _ ___ ____ || + || | |\ | | | | | | \ |___ || + || | | \| |___ |___ |__| |__/ |___ || + || || + \************************************************************************************************/ + #include "types.h" + + /************************************************************************************************\ + || ___ ____ ____ ____ _ _ _ ____ ___ ___ _ _ ___ ____ ____ || + || | \ |___ |__/ |__/ | | | |___ | \ | \_/ |__] |___ [__ || + || |__/ |___ | \ | \ | \/ |___ |__/ | | | |___ ___] || + || || + \************************************************************************************************/ + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure is used to read/assemble a packed codestream during coding. The ! + ! byte buffer is flushed to the packed stream as soon as the a single byte has ! + ! been assembled. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + uchar error; // Error flag used during streaming. + + uint64 L; // Number of bytes written to/from stream. + uint64 Lmax; // Size of packed stream. + uint64 size_incr; // Size incrmnt used for stream assembly. + + uint8 T; // Byte buffer. + int8 t; // Byte buffer counter. + + uchar *memory; // Memory handle for packed stream chunck. + } bitstream; + + /************************************************************************************************\ + || ___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || + || |__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ || + || | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] || + || || + \************************************************************************************************/ + uint64 bytes_used (bitstream const *const stream); + //==========|==========================|======================|======|======|===================== + bitstream* init_stream (uchar *const memory, + uint32 const size, + char const instr); + //==========|==========================|======================|======|======|===================== + void emit_chunck (bitstream *const stream, + uchar const *const chunck, + uint64 const size); + //==========|==========================|======================|======|======|===================== + void emit_symbol (bitstream *const stream, + uint64 const symbol, + uint8 const size); + //==========|==========================|======================|======|======|===================== + void emit_bit (bitstream *const stream, + uint64 const bit); + //==========|==========================|======================|======|======|===================== + void flush_stream (bitstream *const stream); + //==========|==========================|======================|======|======|===================== + uchar* get_chunck (bitstream *const stream, + uint64 const length); + //==========|==========================|======================|======|======|===================== + uint64 get_symbol (bitstream *const stream, + uint8 const length); + //==========|==========================|======================|======|======|===================== + uchar get_bit (bitstream *const stream); + //==========|==========================|======================|======|======|===================== + uchar terminate_stream (bitstream *stream, + bwc_stream *const packed_stream); + //==========|==========================|======================|======|======|===================== + void release_packed_stream (bwc_stream *const stream); +#endif diff --git a/1-bwc/include/library/private/codestream.h b/1-bwc/include/library/private/codestream.h new file mode 100755 index 0000000..482b8eb --- /dev/null +++ b/1-bwc/include/library/private/codestream.h @@ -0,0 +1,104 @@ +/*================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| DESCRIPTION: || +|| ------------ || +|| || +|| This file describes a set of function that can be used to create and manipulate || +|| a BigWhoop Codestream. They facilitate the assembly and parsing of the main || +|| header and tile bitsreams as well as read and write functions used to access || +|| conforming bwc datasets. || +|| || +|| -------------------------------------------------------------------------------------------- || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are || +|| permitted provided that the following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of || +|| conditions and the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || +|| of conditions and the following disclaimer in the documentation and/or other || +|| materials provided with the distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS || +|| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF || +|| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE || +|| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, || +|| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF || +|| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) || +|| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || +|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, || +|| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*================================================================================================*/ +#ifndef CODESTREAM_H +#define CODESTREAM_H + + /************************************************************************************************\ + || _ _ _ ____ _ _ _ ___ ____ || + || | |\ | | | | | | \ |___ || + || | | \| |___ |___ |__| |__/ |___ || + || || + \************************************************************************************************/ + #include "types.h" + #include "bitstream.h" + + /************************************************************************************************\ + || _ _ ____ ____ ____ ____ ____ || + || |\/| |__| | |__/ | | [__ || + || | | | | |___ | \ |__| ___] || + || || + \************************************************************************************************/ + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These macros define stream manipulation operations to rewind, forward, inquire ! + ! the availability and get access to the current memory position of a bitstrean. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + #define rewind_stream(stream, delta) \ + { \ + stream->L -= delta; \ + } + + #define forward_stream(stream, delta) \ + { \ + stream->L += delta; \ + } + + #define get_access(stream) (uchar*)stream->memory + stream->L + + /************************************************************************************************\ + || ___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || + || |__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ || + || | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] || + || || + \************************************************************************************************/ + uchar assemble_main_header (bwc_field *const field); + //==========|==========================|======================|======|======|===================== + uchar codestream_write_aux (bwc_stream *const header, + bwc_stream *const aux); + //==========|==========================|======================|======|======|===================== + uchar codestream_write_com (bwc_stream *const header, + bwc_stream *const com); + //==========|==========================|======================|======|======|===================== + bwc_stream* assemble_codestream (bwc_field *const field); + //==========|==========================|======================|======|======|===================== + bwc_field* parse_codestream (bwc_data *const data, + uint8 const layer); +#endif \ No newline at end of file diff --git a/1-bwc/include/library/private/constants.h b/1-bwc/include/library/private/constants.h new file mode 100755 index 0000000..7cb1b56 --- /dev/null +++ b/1-bwc/include/library/private/constants.h @@ -0,0 +1,106 @@ +/*================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| DESCRIPTION: || +|| ------------ || +|| || +|| This file defines simple constants that are used to make the code more readable. || +|| || +|| -------------------------------------------------------------------------------------------- || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are || +|| permitted provided that the following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of || +|| conditions and the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || +|| of conditions and the following disclaimer in the documentation and/or other || +|| materials provided with the distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS || +|| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF || +|| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE || +|| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, || +|| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF || +|| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) || +|| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || +|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, || +|| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*================================================================================================*/ +#ifndef CONSTANTS_H +#define CONSTANTS_H + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These constants are used to signal spatial or temporal the wavelet filter. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef enum + { + bwc_dwt_9_7, // Cohen Daubechies Feauveau 9/7 Wavelet + bwc_dwt_5_3, // LeGall 5/3 Wavelet + bwc_dwt_haar // Haar Wavelet + } bwc_dwt_filter; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These constants are used to signal the packing order of the codestream. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef enum + { + bwc_prog_LRCP, // Layer / Resolution / Parameter / Packet + bwc_prog_RLCP, // Resolution / Layer / Parameter / Packet + bwc_prog_RPCL, // Resolution / Packet / Parameter / Layer + bwc_prog_PCRL, // Packet / Parameter / Resolution / Layer + bwc_prog_CPRL // Parameter / Packet / Resolution / Layer + } bwc_prog_ord; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These constants are used to signal the quantisation style during ! + ! (de)coompression. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef enum + { + bwc_qt_none, // No quantization + bwc_qt_derived, // Derrived according to Taubman/Marcellin + } bwc_quant_st; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These constants are used to signal dataset tiling by the function caller. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef enum + { + bwc_tile_sizeof, // Tiling defined by size of one tile + bwc_tile_numbof, // Tiling defined by the number of tiles + } bwc_tile_instr; +#endif \ No newline at end of file diff --git a/1-bwc/include/library/private/dwt.h b/1-bwc/include/library/private/dwt.h new file mode 100755 index 0000000..d9fa0eb --- /dev/null +++ b/1-bwc/include/library/private/dwt.h @@ -0,0 +1,169 @@ +/*================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| DESCRIPTION: || +|| ------------ || +|| || +|| This file describes a set of functions that can be used to performe the forward/ || +|| inverse discrete wavelet transform on 1- to 4-dimensional IEEE 754 data-sets. || +|| For more information please refere to JPEG2000 by D. S. Taubman and M. W. || +|| Marcellin. || +|| || +|| -------------------------------------------------------------------------------------------- || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are || +|| permitted provided that the following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of || +|| conditions and the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || +|| of conditions and the following disclaimer in the documentation and/or other || +|| materials provided with the distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS || +|| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF || +|| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE || +|| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, || +|| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF || +|| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) || +|| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || +|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, || +|| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*================================================================================================*/ +#ifndef DWT_H +#define DWT_H + /************************************************************************************************\ + || _ _ _ ____ _ _ _ ___ ____ || + || | |\ | | | | | | \ |___ || + || | | \| |___ |___ |__| |__/ |___ || + || || + \************************************************************************************************/ + #include "types.h" + + /************************************************************************************************\ + || _ _ ____ ____ ____ ____ ____ || + || |\/| |__| | |__/ | | [__ || + || | | | | |___ | \ |__| ___] || + || || + \************************************************************************************************/ + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! Maximum number of wavelet layers for which the energy gain is calculated. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + #define MAX_DECOMP_LEVELS 4 + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These macros define the irrational coefficients for the high and low pass ! + ! synthesis filters associated with the (9-7) Cohen-Daubechies-Feauveau-Wavelet ! + ! as well as the coefficients for its coressponding lifting scheme. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + #define DWT_9X7_H0 1.115087052457000f // Low pass synthesis filter ... + #define DWT_9X7_H1 0.591271763114250f // ... coefficients + #define DWT_9X7_H2 -0.057543526228500f + #define DWT_9X7_H3 -0.091271763114250f + + #define DWT_9X7_G0 1.205898036472721f // High pass synthesis filter ... + #define DWT_9X7_G1 -0.533728236885750f // ... coefficients + #define DWT_9X7_G2 -0.156446533057980f + #define DWT_9X7_G3 0.033728236885750f + #define DWT_9X7_G4 0.053497514821620f + + #define ALPHA -1.586134342059924f // Lifting coefficients. + #define BETA -0.052980118572961f + #define GAMMA 0.882911075530934f + #define DELTA 0.360523644801462f + #define KAPPA_H 1.230174104914001f + #define KAPPA_L 0.812893066115961f + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These macros define the irrational coefficients for the high and low pass ! + ! synthesis filters associated with the (5-3) LeGall-Wavelet. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + #define DWT_5X3_H0 1.0f // Low pass synthesis filter ... + #define DWT_5X3_H1 0.5f // ... coefficients + + #define DWT_5X3_G0 0.75f // High pass synthesis filter + #define DWT_5X3_G1 -0.25f // ... coefficients + #define DWT_5X3_G2 -0.125f + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These macros define the irrational coefficients for the high and low pass ! + ! synthesis filters associated with the Haar-Wavelet. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + #define DWT_HAAR_H0 1 // Low pass synthesis filter ... + #define DWT_HAAR_H1 1 // ... coefficients + + #define DWT_HAAR_G0 0.5 // High pass synthesis filter ... + #define DWT_HAAR_G1 -0.5 // ... coefficients + + /************************************************************************************************\ + || ____ _ _ ___ ____ ____ _ _ ____ _ _ _ ____ ____ _ ____ ___ _ ____ ____ || + || |___ \/ | |___ |__/ |\ | |__| | | | |__| |__/ | |__| |__] | |___ [__ || + || |___ _/\_ | |___ | \ | \| | | |___ \/ | | | \ | | | |__] |___ |___ ___] || + || || + \************************************************************************************************/ + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This array defines a lookup table used to store the energy gain factors for the ! + ! one dimensional CDF(9/7), LeGall-(5/3) and Haar wavelet transform. Each LUT ! + ! contains energy gain factors for the 6 low-pass and 6 high-pass decomposition ! + ! including level zero. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + extern double DWT_ENERGY_GAIN_LUT[3][2 * MAX_DECOMP_LEVELS + 2]; + + + /************************************************************************************************\ + || ___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || + || |__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ || + || | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] || + || || + \************************************************************************************************/ + uchar initialize_gain_lut (); + //==========|==========================|======================|======|=======|==================== + bwc_float get_dwt_energy_gain (bwc_field *const field, + uchar const highband_flag, + uint16 const level); + //==========|==========================|======================|======|=======|==================== + uchar forward_wavelet_transform (bwc_field *const field, + bwc_parameter *const parameter); + //==========|==========================|======================|======|=======|==================== + uchar inverse_wavelet_transform (bwc_field *const field, + bwc_parameter *const parameter); +#endif \ No newline at end of file diff --git a/1-bwc/include/library/private/libbwc.h b/1-bwc/include/library/private/libbwc.h new file mode 100755 index 0000000..36d6e92 --- /dev/null +++ b/1-bwc/include/library/private/libbwc.h @@ -0,0 +1,147 @@ +/*================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| DESCRIPTION: || +|| ------------ || +|| || +|| Big Whoop is a compression codec for the lossy compression of IEEE 754 floating || +|| point arrays defined on curvelinear compute grids. || +|| || +|| -------------------------------------------------------------------------------------------- || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are || +|| permitted provided that the following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of || +|| conditions and the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || +|| of conditions and the following disclaimer in the documentation and/or other || +|| materials provided with the distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS || +|| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF || +|| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE || +|| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, || +|| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF || +|| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) || +|| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || +|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, || +|| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*================================================================================================*/ +#ifndef LIBBWC_H +#define LIBBWC_H + /************************************************************************************************\ + || _ _ _ ____ _ _ _ ___ ____ || + || | |\ | | | | | | \ |___ || + || | | \| |___ |___ |__| |__/ |___ || + || || + \************************************************************************************************/ + #include "bitstream.h" + #include "codestream.h" + #include "constants.h" + #include "macros.h" + #include "mq_types.h" + #include "types.h" + + /************************************************************************************************\ + || ___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || + || |__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ || + || | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] || + || || + \************************************************************************************************/ + //==========|==========================|======================|======|=======|==================== + bwc_data* bwc_initialize_data (double *const field, + uint64 const nX, + uint64 const nY, + uint64 const nZ, + uint16 const nTS, + uint8 const nPar, + char *const file_extension); + //==========|==========================|======================|======|=======|==================== + void bwc_add_param (bwc_data *const data, + char *const name, + uint8 const precision); + //==========|==========================|======================|======|=======|==================== + void bwc_get_data (bwc_data *const data, + uchar *const buffer, + uint64 const size); + //==========|==========================|======================|======|=======|==================== + void bwc_free_data (bwc_data *const data); + //==========|==========================|======================|======|=======|==================== + uchar create_field (bwc_field *const field); + //==========|==========================|======================|======|=======|==================== + void bwc_kill_compression (bwc_field *const field); + //==========|==========================|======================|======|=======|==================== + bwc_field* bwc_initialize_field (bwc_data *const data); + //==========|==========================|======================|======|=======|==================== + void bwc_set_error_resilience (bwc_field *const field); + //==========|==========================|======================|======|=======|==================== + void bwc_set_quant_style (bwc_field *const field, + bwc_quant_st const quantization_style); + //==========|==========================|======================|======|=======|==================== + void bwc_set_quant_step_size (bwc_field *const field, + double const delta); + //==========|==========================|======================|======|=======|==================== + void bwc_set_progression (bwc_field *const field, + bwc_prog_ord const progression); + //==========|==========================|======================|======|=======|==================== + void bwc_set_kernels (bwc_field *const field, + bwc_dwt_filter const KernelX, + bwc_dwt_filter const KernelY, + bwc_dwt_filter const KernelZ, + bwc_dwt_filter const KernelTS); + //==========|==========================|======================|======|=======|==================== + void bwc_set_decomp (bwc_field *const field, + uint8 const decompX, + uint8 const decompY, + uint8 const decompZ, + uint8 const decompTS); + //==========|==========================|======================|======|=======|==================== + void bwc_set_precincts (bwc_field *const field, + uint8 const pX, + uint8 const pY, + uint8 const pZ, + uint8 const pTS); + //==========|==========================|======================|======|=======|==================== + void bwc_set_codeblocks (bwc_field *const field, + uint8 const cbX, + uint8 const cbY, + uint8 const cbZ, + uint8 const cbTS); + //==========|==========================|======================|======|=======|==================== + void bwc_set_qm (bwc_field *const field, + uint8 const Qm); + //==========|==========================|======================|======|=======|==================== + void bwc_set_tiles (bwc_field *const field, + uint64 const tilesX, + uint64 const tilesY, + uint64 const tilesZ, + uint64 const tilesTS, + bwc_tile_instr const instr); + //==========|==========================|======================|======|=======|==================== + uchar bwc_create_compression (bwc_field *const field, + char *const rate_control); + //==========|==========================|======================|======|=======|==================== + uchar bwc_compress (bwc_field *const field, + bwc_data *const data); + //==========|==========================|======================|======|=======|==================== + bwc_field* bwc_create_decompression (bwc_data *const data, + uint8 const layer); + //==========|==========================|======================|======|=======|==================== + uchar bwc_decompress (bwc_field *const field, + bwc_data *const data); +#endif \ No newline at end of file diff --git a/1-bwc/include/library/private/macros.h b/1-bwc/include/library/private/macros.h new file mode 100755 index 0000000..855d567 --- /dev/null +++ b/1-bwc/include/library/private/macros.h @@ -0,0 +1,137 @@ +/*================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| DESCRIPTION: || +|| ------------ || +|| || +|| This file defines simple macros that are used to make the code more readable. || +|| || +|| -------------------------------------------------------------------------------------------- || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are || +|| permitted provided that the following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of || +|| conditions and the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || +|| of conditions and the following disclaimer in the documentation and/or other || +|| materials provided with the distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS || +|| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF || +|| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE || +|| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, || +|| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF || +|| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) || +|| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || +|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, || +|| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*================================================================================================*/ +#ifndef BWC_MACROSS_H +#define BWC_MACROSS_H + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These constants are used to identify the spatial and temporal dimensions. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + #define DIM_X 1 // 1st. spacial direction + #define DIM_Y 2 // 2nd. spacial direction + #define DIM_Z 4 // 3rd. spacial direction + #define DIM_TS 8 // temporal direction + #define DIM_ALL 15 // all dimensions + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These Constants define codestream markers used to create the embedded codestream. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + #define SOC 0xFF50 // Start of codestream + #define SGI 0xFF51 // Global data-set information + #define SGC 0xFF52 // Global control parameters + #define SAX 0xFF53 // Auxiliary data-set information + #define TLM 0xFF54 // Packet lengths: main header + #define PLM 0xFF55 // Packet lengths: tile-part + #define PPM 0xFF56 // Quantization default + #define COM 0xFF57 // Comment + #define EOH 0xFF58 // End of header + #define PLT 0xFF60 // Packed packet headers: main header + #define PPT 0xFF61 // Packed packet headers: tile-part + #define SOT 0xFF90 // Start of tile + #define SOP 0xFF91 // Start of packet + #define EPH 0xFF92 // End of packet header + #define SOD 0xFF93 // Start of data + #define EOC 0xFFFF // End of code-stream + + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These macros define flags used for codestream parsing. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + #define CODESTREAM_OK 0x00 // No errors detected in Codestream + #define CODESTREAM_ERROR 0x80 // Error detexted in Codestream + #define CODESTREAM_SGI_READ 0x01 // Global data-set information read + #define CODESTREAM_SGC_READ 0x02 // Global control parameters read + #define CODESTREAM_SAX_READ 0x08 // Auxiliary information block read + #define CODESTREAM_COM_READ 0x10 // Comment block read + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These macros define simple mathematicall oprators. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + #define MAX(x, y) (((x) < (y))?(y):(x)) // Returns maximum between two values + #define MIN(x, y) (((x) > (y))?(y):(x)) // Returns minimum between two values + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This macro is used to evaluate the size of an array. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + #define GET_DIM(x) (sizeof(x)/sizeof(*(x))) + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These Constants define common error messages used throughout the bwc library. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + #define MEMERROR "o##########################################################o\n"\ + "| ERROR: Out of memory |\n"\ + "o##########################################################o\n" + + #define CSERROR "o##########################################################o\n"\ + "| ERROR: Invalid Codestream |\n"\ + "o##########################################################o\n" +#endif \ No newline at end of file diff --git a/1-bwc/include/library/private/mq.h b/1-bwc/include/library/private/mq.h new file mode 100755 index 0000000..98de295 --- /dev/null +++ b/1-bwc/include/library/private/mq.h @@ -0,0 +1,114 @@ +/*================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| DESCRIPTION: || +|| ------------ || +|| || +|| DESCRIPTION NEEDED. || +|| | | || +|| || +|| -------------------------------------------------------------------------------------------- || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are || +|| permitted provided that the following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of || +|| conditions and the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || +|| of conditions and the following disclaimer in the documentation and/or other || +|| materials provided with the distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS || +|| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF || +|| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE || +|| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, || +|| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF || +|| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) || +|| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || +|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, || +|| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*================================================================================================*/ +#ifndef MQ_H +#define MQ_H + /************************************************************************************************\ + || _ _ _ ____ _ _ _ ___ ____ || + || | |\ | | | | | | \ |___ || + || | | \| |___ |___ |__| |__/ |___ || + || || + \************************************************************************************************/ + #include "tier1.h" + #include "types.h" + + /************************************************************************************************\ + || ____ ____ _ _ ____ ___ ____ _ _ ___ ____ || + || | | | |\ | [__ | |__| |\ | | [__ || + || |___ |__| | \| ___] | | | | \| | ___] || + || || + \************************************************************************************************/ + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These macros define the context state indices used by the mq coder for ! + ! probability estimation. For a more thorough treatment of the context assignments ! + ! see page 487 JPEG2000 by David S. Taubman and Michael W. Marcellin. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + #define CONTEXT_SIG 0 // Sig. context labels starting indices + #define CONTEXT_RUN 9 // Indices for the run context label + #define CONTEXT_SIGN 10 // Sign context labels starting indices + #define CONTEXT_MAG 15 // Mag. context labels starting indices + #define CONTEXT_UNI 18 // Indices for the uni context label + #define CONTEXT_TOTAL 19 // Total number of context labels + + /************************************************************************************************\ + || ___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || + || |__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ || + || | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] || + || || + \************************************************************************************************/ + uchar initialize_mq_encoder (bwc_coder *const coder, + uint8 const number_of_contexts); + //==========|==========================|======================|======|=======|==================== + uchar mq_next_run (bwc_bit_coder *const bitcoder); + //==========|==========================|======================|======|=======|==================== + void mq_bit_encode (bwc_bit_coder *const bitcoder, + uint8 const s, + uint8 const k); + //==========|==========================|======================|======|=======|==================== + void mq_truncation_length_min (bwc_coder_state *const state); + //==========|==========================|======================|======|=======|==================== + void mq_termination (bwc_bit_coder *const bitcoder); + //==========|==========================|======================|======|=======|==================== + void free_mq_encoder (bwc_coder *const coder); + //==========|==========================|======================|======|=======|==================== + uchar initialize_mq_decoder (bwc_coder *const coder, + uint8 const number_of_contexts, + int64 const Lmax); + //==========|==========================|======================|======|=======|==================== + uint8 mq_bit_decode (bwc_bit_coder *const bitcoder, + uint8 const k); + //==========|==========================|======================|======|=======|==================== + uint64 mq_get_no_bytes (bwc_bit_coder *const bitcoder); + //==========|==========================|======================|======|=======|==================== + void mq_get_pass_lengths (bwc_bit_coder *const bitcoder, + bwc_encoded_cblk *const encoded_cblk); + //==========|==========================|======================|======|=======|==================== + void mq_reset_ptr (bwc_bit_coder *const bitcoder, + uchar *const memory); +#endif \ No newline at end of file diff --git a/1-bwc/include/library/private/mq_types.h b/1-bwc/include/library/private/mq_types.h new file mode 100755 index 0000000..84c5c7b --- /dev/null +++ b/1-bwc/include/library/private/mq_types.h @@ -0,0 +1,121 @@ +/*================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| DESCRIPTION: || +|| ------------ || +|| || +|| This header defines a the bit coder and its context states used during the || +|| entropy encoding stage of the BigWhoop compression library. || +|| || +|| -------------------------------------------------------------------------------------------- || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are || +|| permitted provided that the following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of || +|| conditions and the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || +|| of conditions and the following disclaimer in the documentation and/or other || +|| materials provided with the distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS || +|| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF || +|| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE || +|| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, || +|| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF || +|| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) || +|| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || +|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, || +|| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*================================================================================================*/ +#ifndef MQ_TYPES_H +#define MQ_TYPES_H + /************************************************************************************************\ + || _ _ _ ____ _ _ _ ___ ____ || + || | |\ | | | | | | \ |___ || + || | | \| |___ |___ |__| |__/ |___ || + || || + \************************************************************************************************/ + #include + + /************************************************************************************************\ + || ___ ____ ____ ____ _ _ _ ____ ___ ___ _ _ ___ ____ ____ || + || | \ |___ |__/ |__/ | | | |___ | \ | \_/ |__] |___ [__ || + || |__/ |___ | \ | \ | \/ |___ |__/ | | | |___ ___] || + || || + \************************************************************************************************/ + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure is used to directly access the parameter codeblocks during ! + ! entropy (de-)encoding to facilitate shared memory parallelization. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct context + { + uint16_t p; // LPS probability estimate + uint8_t sk; // Most probable symbol + + const struct context *const MPS; // New context for Most Probable Symbol + const struct context *const LPS; // New context for Least Probable Symbol + } bwc_context_state; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! DESCRIPTION NEEDED ! + ! | | ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct state + { + int64_t L; // Number of bytes generated so far + uint32_t C; // Register def. lower bound of coding int + uint16_t A; // Register def. upper bound of coding int + int8_t t; // Counter evaluating when moving C into b + + unsigned char *b; // Byte buffer + unsigned char T; // Temporary byte buffer + + struct state *next; // State of the next coding phase + struct state *prev; // State of the previous coding phase + } bwc_coder_state; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! DESCRIPTION NEEDED ! + ! | | ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + int64_t Lmax; // Number of code bytes (used by decoder) + uint8_t nContext; // No. tracked context states + + unsigned char *b; // Temporary byte buffer + + bwc_coder_state *state; // State for the current coding pass + bwc_context_state const **context; // States for the current coding pass + } bwc_bit_coder; +#endif \ No newline at end of file diff --git a/1-bwc/include/library/private/prim_types_double.h b/1-bwc/include/library/private/prim_types_double.h new file mode 100755 index 0000000..4c8fc4b --- /dev/null +++ b/1-bwc/include/library/private/prim_types_double.h @@ -0,0 +1,133 @@ +/*================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| DESCRIPTION: || +|| ------------ || +|| || +|| This header defines a set of basic arithmetic types with specified widths to be || +|| used in the big whoop compression algorithm. || +|| || +|| -------------------------------------------------------------------------------------------- || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are || +|| permitted provided that the following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of || +|| conditions and the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || +|| of conditions and the following disclaimer in the documentation and/or other || +|| materials provided with the distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS || +|| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF || +|| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE || +|| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, || +|| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF || +|| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) || +|| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || +|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, || +|| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*================================================================================================*/ +#ifndef BWC_PRIM_TYPES_DOUBLE_H +#define BWC_PRIM_TYPES_DOUBLE_H + /************************************************************************************************\ + || _ _ _ ____ _ _ _ ___ ____ || + || | |\ | | | | | | \ |___ || + || | | \| |___ |___ |__| |__/ |___ || + || || + \************************************************************************************************/ + #include + + /************************************************************************************************\ + || ___ ____ _ _ _ _ ___ _ _ _ ____ ___ _ _ ___ ____ ____ || + || |__] |__/ | |\/| | | | | | |___ | \_/ |__] |___ [__ || + || | | \ | | | | | | \/ |___ | | | |___ ___] || + || || + \************************************************************************************************/ + typedef unsigned char uchar; + typedef unsigned short ushort; + typedef unsigned int uint; + + typedef int8_t int8; + typedef uint8_t uint8; + typedef int16_t int16; + typedef uint16_t uint16; + typedef int32_t int32; + typedef uint32_t uint32; + typedef int64_t int64; + typedef uint64_t uint64; + + typedef double bwc_float; + typedef uint64 bwc_raw; + + /************************************************************************************************\ + || _ _ ____ ____ ____ ____ ____ || + || |\/| |__| | |__/ | | [__ || + || | | | | |___ | \ |__| ___] || + || || + \************************************************************************************************/ + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These macros describe the minimum and maximum values for a double precision IEEE ! + ! 754 floating point variable. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + #define FLT_MAX 1.7976931348623157e+308 // Maximum finite value of a double + #define FLT_MIN 2.2250738585072014e-308 // Minimum finite value of a double + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These macros describe the precision (in bits and bytes) of the derrived floating ! + ! point type as well as the number of bits used to represent its mantissa and ! + ! exponent fields. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + #define PREC_BIT 63 // Double type precision in bits + #define PREC_MANTISSA 52 // Mantissa field precision in bits + #define PREC_EXPONENT 11 // Exponent field precision in bits + #define PREC_BYTE 8 // Double type precision in bytes + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These macros describe the bit masks used to access the sign, mantissa and ! + ! exponent of the derrived floating point type. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + #define SIGN 0x8000000000000000 // Sign bit mask + #define MANTISSA 0x000FFFFFFFFFFFFF // Mantissa bit mask + #define EXPONENT 0x7FF0000000000000 // Exponent bit mask + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This macro describe the maximum number of possible encoding passes during the ! + ! entropy encoding stage. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + #define MAXIMUM_NO_PASSES (64 * 3) - 2 +#endif \ No newline at end of file diff --git a/1-bwc/include/library/private/prim_types_single.h b/1-bwc/include/library/private/prim_types_single.h new file mode 100755 index 0000000..e2e8365 --- /dev/null +++ b/1-bwc/include/library/private/prim_types_single.h @@ -0,0 +1,133 @@ +/*================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| DESCRIPTION: || +|| ------------ || +|| || +|| This header defines a set of basic arithmetic types with specified widths to be || +|| used in the big whoop compression algorithm. || +|| || +|| -------------------------------------------------------------------------------------------- || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are || +|| permitted provided that the following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of || +|| conditions and the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || +|| of conditions and the following disclaimer in the documentation and/or other || +|| materials provided with the distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS || +|| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF || +|| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE || +|| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, || +|| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF || +|| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) || +|| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || +|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, || +|| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*================================================================================================*/ +#ifndef BWC_PRIM_TYPES_SINGLE_H +#define BWC_PRIM_TYPES_SINGLE_H + /************************************************************************************************\ + || _ _ _ ____ _ _ _ ___ ____ || + || | |\ | | | | | | \ |___ || + || | | \| |___ |___ |__| |__/ |___ || + || || + \************************************************************************************************/ + #include + + /************************************************************************************************\ + || ___ ____ _ _ _ _ ___ _ _ _ ____ ___ _ _ ___ ____ ____ || + || |__] |__/ | |\/| | | | | | |___ | \_/ |__] |___ [__ || + || | | \ | | | | | | \/ |___ | | | |___ ___] || + || || + \************************************************************************************************/ + typedef unsigned char uchar; + typedef unsigned short ushort; + typedef unsigned int uint; + + typedef int8_t int8; + typedef uint8_t uint8; + typedef int16_t int16; + typedef uint16_t uint16; + typedef int32_t int32; + typedef uint32_t uint32; + typedef int64_t int64; + typedef uint64_t uint64; + + typedef float bwc_float; + typedef uint32 bwc_raw; + + /************************************************************************************************\ + || _ _ ____ ____ ____ ____ ____ || + || |\/| |__| | |__/ | | [__ || + || | | | | |___ | \ |__| ___] || + || || + \************************************************************************************************/ + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These macros describe the minimum and maximum values for a single precision IEEE ! + ! 754 floating point variable. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + #define FLT_MAX 1.70141183e+38 // Maximum finite value of a float + #define FLT_MIN 1.17549435e-38 // Minimum finite value of a float + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These macros describe the precision (in bits and bytes) of the derrived floating ! + ! point type as well as the number of bits used to represent its mantissa and ! + ! exponent fields. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + #define PREC_BIT 31 // Float type precision in bits + #define PREC_MANTISSA 23 // Mantissa field precision in bits + #define PREC_EXPONENT 8 // Exponent field precision in bits + #define PREC_BYTE 4 // Float type precision in bytes + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These macros describe the bit masks used to access the sign, mantissa and ! + ! exponent of the derrived floating point type. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + #define SIGN 0x80000000 // Sign bit mask + #define MANTISSA 0x007FFFFF // Mantissa bit mask + #define EXPONENT 0x7F800000 // Exponent bit mask + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This macro describe the maximum number of possible encoding passes during the ! + ! entropy encoding stage. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + #define MAXIMUM_NO_PASSES (32 * 3) - 2 +#endif \ No newline at end of file diff --git a/1-bwc/include/library/private/tagtree.h b/1-bwc/include/library/private/tagtree.h new file mode 100755 index 0000000..7682cf4 --- /dev/null +++ b/1-bwc/include/library/private/tagtree.h @@ -0,0 +1,96 @@ +/*================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| DESCRIPTION: || +|| ------------ || +|| || +|| This file defines a tagtree procedure used to encode/decode two types of || +|| information found defining in a codeblock in specific quality layer: || +|| || +|| - The inclusion tag records if a codeblock has any contribution || +|| to a quality layer. || +|| - The number of leading bitplanes that are not significant/only || +|| populated by zero bits. || +|| || +|| For more information on the encoding/decoding process please refere to JPEG2000 || +|| by D. S. Taubman and M. W. Marcellin (p. 384). || +|| || +|| -------------------------------------------------------------------------------------------- || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are || +|| permitted provided that the following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of || +|| conditions and the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || +|| of conditions and the following disclaimer in the documentation and/or other || +|| materials provided with the distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS || +|| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF || +|| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE || +|| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, || +|| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF || +|| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) || +|| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || +|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, || +|| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*================================================================================================*/ +#ifndef TAGTREE_H +#define TAGTREE_H + /************************************************************************************************\ + || _ _ _ ____ _ _ _ ___ ____ || + || | |\ | | | | | | \ |___ || + || | | \| |___ |___ |__| |__/ |___ || + || || + \************************************************************************************************/ + #include "types.h" + #include "bitstream.h" + + /************************************************************************************************\ + || ___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || + || |__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ || + || | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] || + || || + \************************************************************************************************/ + void kill_tagtree (bwc_tagtree *const tagtree); + //==========|==========================|======================|======|=======|==================== + void reset_tagtree (bwc_tagtree *const tagtree); + //==========|==========================|======================|======|=======|==================== + bwc_tagtree* initialize_tagtree (uint64 const leafsX, + uint64 const leafsY, + uint64 const leafsZ, + uint64 const leafsTS); + //==========|==========================|======================|======|=======|==================== + uint16 tagtree_get_value (bwc_tagtree const *const tagtree, + uint64 const leaf_index); + //==========|==========================|======================|======|=======|==================== + void tagtree_set_value (bwc_tagtree *const tagtree, + uint64 const leaf_index, + uint16 const value); + //==========|==========================|======================|======|=======|==================== + void encode_tagtree (bwc_tagtree *const tagtree, + bitstream *const stream, + uint32 const threshold, + uint32 const leaf_index, + uchar const estimate); + //==========|==========================|======================|======|=======|==================== + uchar decode_tagtree (bwc_tagtree *const tagtree, + bitstream *const stream, + uint32 const threshold, + uint32 const leaf_index); +#endif \ No newline at end of file diff --git a/1-bwc/include/library/private/tier1.h b/1-bwc/include/library/private/tier1.h new file mode 100755 index 0000000..13f60eb --- /dev/null +++ b/1-bwc/include/library/private/tier1.h @@ -0,0 +1,168 @@ +/*================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| DESCRIPTION: || +|| ------------ || +|| || +|| This file describes a set of functions that can be used to de-/encode bwc || +|| codeblocks described by the bwc_field structure according to the embedded block || +|| coding paradigm described by the JPEG 2000 standard. For more information please || +|| refere to JPEG2000 by D. S. Taubman and M. W. Marcellin. || +|| || +|| -------------------------------------------------------------------------------------------- || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are || +|| permitted provided that the following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of || +|| conditions and the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || +|| of conditions and the following disclaimer in the documentation and/or other || +|| materials provided with the distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS || +|| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF || +|| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE || +|| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, || +|| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF || +|| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) || +|| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || +|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, || +|| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*================================================================================================*/ +#ifndef TIER1_H +#define TIER1_H + /************************************************************************************************\ + || _ _ _ ____ _ _ _ ___ ____ || + || | |\ | | | | | | \ |___ || + || | | \| |___ |___ |__| |__/ |___ || + || || + \************************************************************************************************/ + #include "types.h" + + /************************************************************************************************\ + || _ _ ____ ____ ____ ____ ____ || + || |\/| |__| | |__/ | | [__ || + || | | | | |___ | \ |__| ___] || + || || + \************************************************************************************************/ + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! The macros listed indicate how many bits, from the current coding position, ! + ! are used for error evaluation in the coding passes. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + #define DISTORTION_SIG 5 // Clean up/significance propagation pass. + #define DISTORTION_MAG 6 // Magnitude refinement pass. + + /************************************************************************************************\ + || ___ ____ ____ ____ _ _ _ ____ ___ ___ _ _ ___ ____ ____ || + || | \ |___ |__/ |__/ | | | |___ | \ | \_/ |__] |___ [__ || + || |__/ |___ | \ | \ | \/ |___ |__/ | | | |___ ___] || + || || + \************************************************************************************************/ + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure holds the sign (xi), bitfield (bit) and state (delta, sigma and ! + ! pi) information for four vertically adjacent samples for easy access during the ! + ! entropy encoding stage. Here, the delayed significance is set once the first bit ! + ! is encoded during the magnitude refinement pass, while the significance state ! + ! sigma is set once the first non-zero bit is encoded for a specific sample. ! + ! The stripe_* pointers are used to store the address of the left(l), upper(u), ! + ! right(r) and lower(d) neighbour of a specific stripe for easy access. To ! + ! facilitate distortion estimation the magnitude of the wavelet coefficients is ! + ! stored in an appropriate sample array. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct stripe + { + uint64 *sample; // Wavelet coef. for two adjacent stripes. + + uint8 delta; // Delayed sig. for two adjacent stripes. + uint8 sigma; // Significance for two adjacent stripes. + uint8 pi; // Cdng pass membership for adj. stripes. + + uint8 codingpass; // Last decoded coding pass. + + uint8 bitplane; // Last decoded bitplane. + uint8 *bit; // Bitplanes for vertically adj. stripes. + uint8 xi; // Wvlt coef. sign bit for adj. stripes. + + struct stripe *stripe_u; // Upper stripe. + struct stripe *stripe_r; // Right stripe. + struct stripe *stripe_d; // Lower stripe. + struct stripe *stripe_l; // Left stripe. + } bwc_coder_stripe; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure accumulates all necessary structures used to (de-)compress a ! + ! codeblock of wavelet coefficients. The spatial and temporal dimension of the ! + ! codeblock is defined by its width, height and number of slices (depth * dt). The ! + ! codeblock itself is subdivided into so-called stripes that represent 4 vertical- ! + ! ly adjacent coefficients. The parameter no_full_stripes stores overnumber of ! + ! full stripes present in one slice. ! + ! The look-up table sig2context is used to determine the coding context of a cur- ! + ! ren bit according to its significance context within the codeblock bitplane. ! + ! The look-up table is specific to a certain highband and is set accordingly. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + uchar highband_flag; // Flag indicating current wavelet subbnd. + uint8 K; // Idx of the first significant bitplane. + uchar erres; // Flag signaling error resilience. + + uint64 no_full_stripe; // Number of full, vert. adjacent stripes. + uint64 width, height; // Codeblock width and height. + uint64 no_slice; // N.o. slices in the spec. codeblock. + + uint8 const *sig2context; // Signifance-to-context loop-up table. + bwc_bit_coder *bitcoder; // BWC bitcoder. + + bwc_coder_stripe *data; // BWC coder stripe. + + uint64 buff_size; // Size of packed stream. + uint64 buff_incr; // Increment for packed stream assembly. + uchar *compressed; // Compressed data chunck. + } bwc_coder; + + /************************************************************************************************\ + || ___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || + || |__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ || + || | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] || + || || + \************************************************************************************************/ + uchar t1_encode (bwc_field *const field, + bwc_tile *const tile, + bwc_parameter *const parameter); + //==========|==========================|======================|======|=======|==================== + uchar t1_decode (bwc_field *const field, + bwc_tile *const tile, + bwc_parameter *const parameter); + + +#endif \ No newline at end of file diff --git a/1-bwc/include/library/private/tier2.h b/1-bwc/include/library/private/tier2.h new file mode 100755 index 0000000..3dc0bb2 --- /dev/null +++ b/1-bwc/include/library/private/tier2.h @@ -0,0 +1,86 @@ +/*================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| DESCRIPTION: || +|| ------------ || +|| || +|| This file describes a set of functions that can be used to de-/encode bwc || +|| codeblocks described by the bwc_field structure according to the embedded block || +|| coding paradigm described by the JPEG 2000 standard. For more information please || +|| refere to JPEG2000 by D. S. Taubman and M. W. Marcellin. || +|| || +|| -------------------------------------------------------------------------------------------- || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are || +|| permitted provided that the following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of || +|| conditions and the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || +|| of conditions and the following disclaimer in the documentation and/or other || +|| materials provided with the distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS || +|| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF || +|| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE || +|| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, || +|| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF || +|| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) || +|| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || +|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, || +|| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*================================================================================================*/ +#ifndef TIER2_H +#define TIER2_H + /************************************************************************************************\ + || _ _ _ ____ _ _ _ ___ ____ || + || | |\ | | | | | | \ |___ || + || | | \| |___ |___ |__| |__/ |___ || + || || + \************************************************************************************************/ + #include "types.h" + + /************************************************************************************************\ + || _ _ ____ ____ ____ ____ ____ || + || |\/| |__| | |__/ | | [__ || + || | | | | |___ | \ |__| ___] || + || || + \************************************************************************************************/ + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! Definition of the initial codestream packet header size. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + #define PACKET_HEADER_SIZE 512 + + /************************************************************************************************\ + || ___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || + || |__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ || + || | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] || + || || + \************************************************************************************************/ + uchar t2_encode (bwc_field *const field, + bwc_tile *const tile); + //==========|==========================|======================|======|=======|==================== + uchar parse_packet (bwc_field *const field, + bwc_tile *const tile, + bwc_packet *const packet, + uint64 const body_size); +#endif \ No newline at end of file diff --git a/1-bwc/include/library/private/types.h b/1-bwc/include/library/private/types.h new file mode 100755 index 0000000..153be17 --- /dev/null +++ b/1-bwc/include/library/private/types.h @@ -0,0 +1,736 @@ +/*================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| DESCRIPTION: || +|| ------------ || +|| || +|| This header defines a set of derrived types that are used to describe and || +|| instruct the bwc (de-)compression library. || +|| || +|| -------------------------------------------------------------------------------------------- || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are || +|| permitted provided that the following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of || +|| conditions and the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || +|| of conditions and the following disclaimer in the documentation and/or other || +|| materials provided with the distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS || +|| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF || +|| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE || +|| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, || +|| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF || +|| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) || +|| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || +|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, || +|| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*================================================================================================*/ +#ifndef BWC_TYPES_H +#define BWC_TYPES_H + + #include + /************************************************************************************************\ + || _ _ _ ____ _ _ _ ___ ____ || + || | |\ | | | | | | \ |___ || + || | | \| |___ |___ |__| |__/ |___ || + || || + \************************************************************************************************/ + #ifdef BWC_SINGLE_PRECISION + #include "prim_types_single.h" + #else + #include "prim_types_double.h" + #endif + + #include "constants.h" + #include "mq_types.h" + + /************************************************************************************************\ + || ___ ____ ____ ____ _ _ _ ____ ___ ___ _ _ ___ ____ ____ || + || | \ |___ |__/ |__/ | | | |___ | \ | \_/ |__] |___ [__ || + || |__/ |___ | \ | \ | \/ |___ |__/ | | | |___ ___] || + || || + \************************************************************************************************/ + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This union describes a simple data type used to store a single sample of a ! + ! numerical dataset. The union allows access to the raw bit representation of the ! + ! data sample. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef union + { + bwc_raw raw; // Raw data sample access. + bwc_float f; // IEEE 754 representation of sample. + } bwc_sample; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure is used to store the metadata and boy of a packed stream. Tile and ! + ! and paramter index can be supplied to uniquely identify the stream. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + uint64 size; // Size of packed stream. + uint64 position; // Reading/Writing pos. in the stream. + + uchar *access; // Pointer used to parse packed stream. + uchar *memory; // Memory handle for the packed stream. + } bwc_stream; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure defines a single tagtree node which stores the node value (tag), ! + ! node threshold as well as the address of the parent node. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct node + { + uint64 index; // Index of current node. + + uint16 value; // Tagtree node value. + uint16 threshold; // Tagtree node threshold. + + struct node* parent; // Parent of current node. + } bwc_tagtree_node; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure defines a tagtree instance with spatial and temporal leaves that ! + ! can be used to encode codeblock tags - e.g. number of significant bitplanes - to ! + ! efficiently store them in the compressed codestream. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + uint64 leavesX, leavesY; // Number of spatial tagtree leafs. + uint64 leavesZ, leavesTS; // Number of temporal tagtree leafs. + + bwc_tagtree_node *nodes; // Pointer to the tagtree nodes. + } bwc_tagtree; + + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure defines a linked list which stores the size, index, and bit pre- ! + ! cision The string name is used to store the parameter name supplied by the ! + ! function caller. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct opt + { + char name[24]; // Parameter name. + uint8 id; // Parameter index. + + uint64 size; // Parameter size after sub-sampling. + uint8 precision; // Parameter precision. + + struct opt *next; // Next element in linked-list. + struct opt *root; // Linked-list root. + } bwc_cmd_opts_ll; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure holds all the global information of an uncompressed data set ! + ! including its spatial and temporal dimensions, number of parameters, file ! + ! extension and parameter information as well as the codec precision. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + uint64 nX, nY, nZ; // Spatial size of uncompressed data-set. + uint64 nTS; // Temp. size of uncompressed data-set. + + uint8 nPar; // Number of parameters. + + uint8 precision; // Flag defining codec precision. + + uint8 codec_prec; // Encoder/decoder bit precision. + char f_ext[20]; // Uncompressed data set file extension. + + bwc_cmd_opts_ll *parameter; // Command options linked-list. + } bwc_gl_inf; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure stores the numerical dataset/compressed bitstream passed to or ! + ! returned from the (de)compressor. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + bwc_gl_inf info; // Gloabal info structure. + FILE *fp; // File point to (un)compr. data-set. + + struct codestream + { + bwc_stream *data; // Data codestream block. + bwc_stream *aux; // Auxiliary info. codestream block. + bwc_stream *com; // Comment codestream block. + }codestream; + + struct field + { + double *d; // Double precision numerical data-set. + float *f; // Single precision numerical data-set. + }field; + } bwc_data; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure defines and stores all necessary data for a compressed codeblock. ! + ! The coding pass lengths and distortion rate arrays define the convex hull used ! + ! for during rate controlling. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + uint64 L[MAXIMUM_NO_PASSES]; // Coding pass lengths of an ecnoded blck. + uint16 S[MAXIMUM_NO_PASSES + 1]; // Distortion rate of an encoded block. + + uint8 Kmsbs; // N.o. insignificant leading bitplanes. + uint8 K; // First significant bitplane. + + uint8 Z; // Number of coding passes generated. + + uchar *data; // Memory handle to compressed bitstream. + } bwc_encoded_cblk; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure holds all the control parameters for the current precinct used to ! + ! instruct the bwc codec to (de)compress a floating point array. The unique state ! + ! variables are used during length encoding both for quality layer estimation as ! + ! well as packet assembly. The cp_contr access pointer allows access to the memory ! + ! chunck employed to store the coding passes contributing to a specific quality ! + ! layer. The parameter K represents the most significant bitplane present in the ! + ! current codeblock. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + uint16 beta; // Codeblock unique state variable. + uint16 beta_est; // State variable used for ql estimation. + + uint16 K; // Codeblock spec. significant bitplane. + + int16 *memory; // Coding pass contribution to q. layer. + int16 *cp_contr; // Coding pass contribution access ptr. + } bwc_cblk_ctrl; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure is used to store the start and end points as well as the index ! + ! for a specific codeblock. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + uint32 idx; // Codeblock index w.r.t. precinct. + + uint64 X0, Y0, Z0, TS0; // Codeblock starting point. + uint64 X1, Y1, Z1, TS1; // Codeblock end point. + } bwc_cblk_inf; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure holds all the necessary parameters used to define and control a ! + ! bwc codeblock. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + bwc_cblk_inf info; // Codeblock info structure. + bwc_cblk_ctrl control; // Codeblock control structure. + bwc_encoded_cblk *encoded_block; // Encoded block structure. + } bwc_codeblock; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure holds all the control parameters for the current precinct used to ! + ! instruct the bwc codec to (de)compress a floating point array. The number ! + ! codeblocks are stored for all spatial and temporal dimensions as well as for the ! + ! entire precinct. The two tagtrees are employed to record specific properties of ! + ! the underlying data that is to be compressed. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + uint64 number_of_codeblocks; // Number of codeblocks w.r.t res. level. + + uint16 numCbX, numCbY; // Number of spaatial codeblocks. + uint16 numCbZ, numCbTS; // Number of temporal codeblocks. + + bwc_tagtree *tag_inclusion; // Quality layer contribution tagtree. + bwc_tagtree *tag_msbs; // Most significant bit-planes tagtree. + } bwc_prec_ctrl; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! DESCRIPTION NEEDED ! + ! This structure is used to store the start and end points for the current ! + ! precinct. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + uint32 X0, Y0, Z0, TS0; // Precinct starting point. + uint32 X1, Y1, Z1, TS1; // Precinct end point. + } bwc_prec_inf; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure holds all the necessary parameters used to define and control a ! + ! bwc precinct. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + bwc_prec_inf info; // Precinct info structure. + bwc_prec_ctrl control; // Precinct control structure. + bwc_codeblock *codeblock; // Precinct specific codeblocks. + } bwc_precinct; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure holds all the control parameters for the current subband used to ! + ! instruct the bwc codec to (de)compress a floating point array. The highband flag ! + ! is used to identify the type of highband a specific wavelet band belongs to ! + ! (e.g. HHHH). The quantization step size mantissa and exponent for a subband is ! + ! stored alongside its actual value as well as the effective step size that is ! + ! applied to the wavelet coefficients. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + uchar highband_flag; // Current wavelet highband type + + uint16 Kmax; // Dynamic ranger after transformation. + + uint16 qt_mantissa; // Quantization step size mantissa. + uint8 qt_exponent; // Quantization step size exponent. + + bwc_float qt_effective_step_size; // Effective quantization step size. + bwc_float qt_step_size; // Quantization step size. + } bwc_subb_ctrl; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure is used to store the start and end points as well as the energy ! + ! gain factor of the wavelet decomposition that has been applied to the subband ! + ! data samples during transformation. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + uint64 X0, Y0, Z0, TS0; // Subband starting point. + uint64 X1, Y1, Z1, TS1; // Subband end point. + + bwc_float dwt_gain; // Subband energy gain factor. + } bwc_subb_inf; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure holds all the necessary parameters used to define and control a ! + ! bwc subband. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + bwc_subb_inf info; // Subband info structure. + bwc_subb_ctrl control; // Subband control structure. + + bwc_precinct *precinct; // Subband specific precincts. + } bwc_subband; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure holds all the parameters used to assemble a codestream packet. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + bwc_stream header; // Packed stream header. + bwc_stream body; // Packed stream body. + uint8 e; // Indicator for packet cb. contributions. + + uint32 size; // Codestream packet size. + + uint32 p; // Position of curr. packet in codestream. + uint8 c, l, r; // Parameter, Quality Layer and Resolution + // codestream position markers. + } bwc_packet; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure holds all the control parameters for the current resolution level ! + ! used to instruct the bwc codec to (de)compress a floating point array. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + uint16 numPX, numPY; // Spatial number of precincts. + uint16 numPZ, numPTS; // Temporal number of precincts. + + uint8 rcbX, rcbY; // Real spatial codeblock size. + uint8 rcbZ, rcbTS; // Real temporal codeblock size. + + uint64 number_of_precincts; // N.o. precincts in resolution level. + uint8 number_of_subbands; // N.o. subbands in resolution level. + } bwc_res_ctrl; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure is used to store the name, start and end points of the current ! + ! resolution level. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + uint64 X0, Y0, Z0, TS0; // Resolution level starting point. + uint64 X1, Y1, Z1, TS1; // Resolution level end point. + } bwc_res_inf; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure holds all the necessary parameters used to define and control a ! + ! bwc resolution level. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + bwc_res_inf info; // Resolution level info structure. + bwc_res_ctrl control; // Resolution level control structure. + + bwc_subband *subband; // Structure defining a bwc subband. + bwc_packet *packet; // Structure defining a bwc packet. + } bwc_resolution; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure is used to directly access the parameter codeblocks during ! + ! entropy (de-)encoding to facilitate shared memory parallelization. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + bwc_codeblock *codeblock; // Access to all tile param. codeblocks. + bwc_precinct *precinct; // Access to all tile param. precincts. + bwc_subband *subband; // Access to all tile param. subbands. + } bwc_cblk_access; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure holds all the control parameters for the current tile param. used ! + ! to instruct the bwc codec to (de)compress a floating point array. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + uint64 number_of_codeblocks; // Number of codeblocks in the tile param. + bwc_float alpha, beta; // Parameters used for normalization. + } bwc_param_ctrl; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure is used to store the name, start and end points as well as the ! + ! overall size of a parameter tile. Furthermore, the minimum and maximum sample ! + ! values for the current parameter tile are stored. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + uint64 size; // Parameter size. + char *name; // Parameter name. + + uint64 X0, Y0, Z0, TS0; // Tile parameter starting point. + uint64 X1, Y1, Z1, TS1; // Tile parameter end point. + + uint8 precision; // Tile parameter precision. + + bwc_float parameter_min; // Min. value of tile parameter. + bwc_float parameter_max; // Max. value of tile parameter. + } bwc_param_inf; + + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure holds all the necessary parameters used to define and control the ! + ! (de)compression of a bwc tile parameter. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + uint64 size; // Size of the bwc_float data structure. + bwc_sample *data; // Tile parameter values. + + bwc_param_inf info; // Parameter info structure. + bwc_param_ctrl control; // Parameter control structure. + + bwc_resolution *resolution; // Tile parameter specific resol. levels. + + bwc_cblk_access *access; // Access to all tile param. codeblocks. + } bwc_parameter; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure holds all the control parameters for the current tile used to in- ! + ! struct the bwc codec to (de)compress a floating point array. ! + ! The slope_min and slope_max values represent the minimum and maximum distortion ! + ! rates for the compressed data-samples of a specific tile. These values define ! + ! the distortion-bitrate convex hull used for rate control. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + uint64 body_size; // Size of the tile parameter body. + uint64 Ltp; // Tile part size. + uint32 header_size; // Approx. size of the tile param. header. + + uint64 nPackets; // Number of packets assembled for tile. + uint32 max_Prec; // Max. N.o. precincts in all tile params. + + uint16 dflt_param_c; // Default idx when writing COD in header. + uint16 dflt_param_q; // Default idx when writing QCD in header. + + uint16 slope_min, slope_max; // Min/Max for the convex hull slp. + } bwc_tile_ctrl; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure is used to store the start and end points of the tile as well as ! + ! its overall size and index. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + uint64 size; // Tile size. + uint32 tile_index; // Unique tile index. + + uint64 X0, Y0, Z0, TS0; // Tile starting point. + uint64 X1, Y1, Z1, TS1; // Tile end point. + + } bwc_tile_inf; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure holds all the necessary parameters used to define and control the ! + ! (de)compression of a bwc tile. The packet_sequence pointer array is used to ! + ! store the bitstream packet memory hanldes of the underlying tile in a prede- ! + ! fined sequence according to the bwc_progression_ord parameter. The pointer array ! + ! is employed during codestream assembly. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + bwc_tile_inf info; // Tile info structure. + bwc_tile_ctrl control; // Tile control structure. + + bwc_parameter *parameter; // Tile specific parameter structure. + bwc_packet **packet_sequence; // Tile specific packet sequence. + } bwc_tile; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure holds all the global control parameters, including the tile, ! + ! precinct and codeblock sizes as well as the global number of tiles, used to ! + ! instruct the bwc codec to (de)compress a floating point array. ! + ! The number of decompositions (numDecompX etc.) define the number of times the ! + ! selected wavelet filter (kernelX etc.) is applied alongside each spatial and ! + ! temporal direction. The global number of decomposition levels is stored in the ! + ! appropriate variable. ! + ! The parameters qt_mantissa and qt_exponent define the mantissa and exponent of ! + ! the global quantization step size appropriate for the specified number of ! + ! wavelet decomposition levels. The quantization_style signals if the quantization ! + ! step size for the subsequent subbands should be derrived from the global ! + ! parameter, or not. The variable Qm represents the dynamic range of the ! + ! float-to-fixed point transformation employed pre-compression. ! + ! The bitrate array stores up to 10 bitrate values - average bits per datasample - ! + ! that define the codestream quality layers. The largest bitrates defines the ! + ! compression ratio, while the total number of defined bitrates represent the ! + ! number of (quality)layers. The parameter use_layer stores the index of the ! + ! quality layer that is used during decompression. The progression order defines ! + ! the packet sequence as they will appear in the compressed codestream. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + uint16 CSsgc; // Flag signaling user control variable. + uchar error_resilience; // Flag signalling error resilience. + + uint64 tileSizeX, tileSizeY; // Spatial tile size. + uint64 tileSizeZ, tileSizeTS; // Temporal tile size. + + uint64 nTiles; // Global number of tiles. + + uint8 precSizeX, precSizeY; // Spatial precinct size. + uint8 precSizeZ, precSizeTS; // Temporal precinct size. + + uint8 cbX, cbY; // Spatial codeblock size. + uint8 cbZ, cbTS; // Temporal codeblock size. + + bwc_dwt_filter KernelX, KernelY; // Spatial wavelet kernels. + bwc_dwt_filter KernelZ, KernelTS; // Temporal wavelet kernels. + + uint8 decompX, decompY; // Number of wavelet decompositions ... + uint8 decompZ, decompTS; // ... for each of the four dimensions. + uint8 nDecomp; // Maximum No. wavelet decompositions. + + uint32 qt_exponent, qt_mantissa; // Global qunatization exponent/mantissa. + uint8 Qm; // Q number format range (m). + + float *bitrate; // Quality layers defined by bitrate. + + uint8 nLayers; // Number of quality layers. + uint8 useLayer; // Quality layer used for decompression. + + uint8 guard_bits; // Number of guard bits during quant. + + bwc_stream header; // Main codestream header. + + bwc_quant_st quantization_style; // Quantization style. + bwc_prog_ord progression; // Packet progression order. + } bwc_gl_ctrl; + + /*----------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure holds all the necessary parameters defining and controling a bwc ! + ! (de-)compression run. ! + ! ! + ! The meter structure is used to store measurements, including important time ! + ! measurements, for a particular compression run. ! + ! ! + \*----------------------------------------------------------------------------------------------*/ + typedef struct + { + bwc_gl_inf *info; // Gloabal info structure + bwc_gl_ctrl control; // Global control structure + + bwc_tile *tile; // Structure defining bwc tile. + + struct meter + { + double bpd; // Average bits per datapoint. + double cpr; // Compression ratio + double css; // Codestream size. + + struct time + { + double ttl; // Total compression time. + + double cpy; // Total time used copying data. + double nrm; // Total time used normalizing data. + + double wav; // Total time used for wavelet transform. + double ent; // Total time used for entropy encoding. + double ass; // Total codestream assembly time. + } time; + } meter; + } bwc_field; +#endif \ No newline at end of file diff --git a/1-bwc/include/tools/bwccmdl.h b/1-bwc/include/tools/bwccmdl.h new file mode 100644 index 0000000..be53e0b --- /dev/null +++ b/1-bwc/include/tools/bwccmdl.h @@ -0,0 +1,350 @@ +/*====================================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| DESCRIPTION: || +|| ------------ || +|| This is a simple command line tool that uses the Big Whoop library to (de)com- || +|| press a 2- to 4-dimensional IEEE 754 floating point array. For further infor- || +|| mation use the --help (-h) argument in the command-line or consult the appro- || +|| priate README file. || +|| || +|| STRUCTS: || +|| -------- || +|| DESCRIPTION NEEDED. || +|| || +|| DEVELOPMENT HISTORY: || +|| -------------------- || +|| || +|| Date Author Change Id Release Description || +|| ---- ------ --------- ------- ----------- || +|| 13.10.2017 Patrick Vogler B87D120 V 0.1.0 source file created || +|| 26.11.2020 Patrick Vogler B87E7E4 V 0.1.0 Command line tool refac- || +|| tored. || +|| || +|| || +|| ------------------------------------------------------------------------------------------------------ || +|| || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are permitted || +|| provided that the following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of || +|| conditions and the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || +|| of conditions and the following disclaimer in the documentation and/or other materials || +|| provided with the distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED || +|| WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A || +|| PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR || +|| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT || +|| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS || +|| INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || +|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF || +|| ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*====================================================================================================================*/ +#ifndef BWC_CMDL_H +#define BWC_CMDL_H + + /********************************************************************************************************************\ + || _ _ _ ____ _ _ _ ___ ____ || + || | |\ | | | | | | \ |___ || + || | | \| |___ |___ |__| |__/ |___ || + || || + \********************************************************************************************************************/ + #include + + /********************************************************************************************************************\ + || _ _ ____ ____ ____ ____ ____ || + || |\/| |__| | |__/ | | [__ || + || | | | | |___ | \ |__| ___] || + || || + \********************************************************************************************************************/ + /*------------------------------------------------------------------------------------------------------------------*\ + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These macros define minimum and maximum operators as well as an operator used ! + ! to evaluate the size of an array. ! + ! ! + ! MACROS: ! + ! ------- ! + ! Name Description ! + ! ---- ----------- ! + ! MAX(x, y) - Returns the maximum value of ! + ! two values. ! + ! ! + ! MIN(x, y) - Returns the minimum value of ! + ! two values. ! + ! ! + ! GET_LEN(x) - Returns the size of an array. ! + ! ! + ! DEVELOPMENT HISTORY: ! + ! -------------------- ! + ! ! + ! Date Author Change Id Release Description ! + ! ---- ------ --------- ------- ----------- ! + ! 21.03.2018 Patrick Vogler B87D120 V 0.1.0 macros created ! + ! 16.09.2019 Patrick Vogler B87E7E4 V 0.1.0 Added GET_LEN(X) macro. ! + ! ! + \*------------------------------------------------------------------------------------------------------------------*/ + #define MAX(x, y) (((x) < (y))?(y):(x)) + #define MIN(x, y) (((x) > (y))?(y):(x)) + + /*------------------------------------------------------------------------------------------------------------------*\ + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These Constants define codestream markers used to create the embedded code- ! + ! stream. ! + ! ! + ! MACROS: ! + ! ------- ! + ! Name Description ! + ! ---- ----------- ! + ! SOC - Start of code-stream ! + ! SGI - Global data-set information ! + ! SGC - Global control parameters ! + ! SGR - Global register containing tile ! + ! bitstream size information ! + ! SAX - Auxiliary data-set information ! + ! TLM - Packet lengths: main header ! + ! PLM - Packet lengths: tile-part ! + ! PPM - Quantization default ! + ! COM - Comment ! + ! EOH - End of header ! + ! PLT - Packed packet headers: main header ! + ! PPT - Packed packet headers: tile-part ! + ! SOT - Start of tile ! + ! SOP - Start of packet ! + ! EPH - End of packet header ! + ! SOD - Start of data ! + ! EOC - End of code-stream ! + ! ! + ! DEVELOPMENT HISTORY: ! + ! -------------------- ! + ! ! + ! Date Author Change Id Release Description ! + ! ---- ------ --------- ------- ----------- ! + ! 01.12.2017 Patrick Vogler B87D120 V 0.1.0 macros created ! + ! ! + \*------------------------------------------------------------------------------------------------------------------*/ + #define SOC 0xFF50 + #define SGI 0xFF51 + #define SGC 0xFF52 + #define SAX 0xFF53 + #define TLM 0xFF54 + #define PLM 0xFF55 + #define PPM 0xFF56 + #define COM 0xFF57 + #define EOH 0xFF58 + #define PLT 0xFF60 + #define PPT 0xFF61 + #define SOT 0xFF90 + #define SOP 0xFF91 + #define EPH 0xFF92 + #define SOD 0xFF93 + #define EOC 0xFFFF + + /*------------------------------------------------------------------------------------------------------------------*\ + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These macros define flags used for codestream parsing. ! + ! ! + ! MACROS: ! + ! ------- ! + ! Name Description ! + ! ---- ----------- ! + ! CODESTREAM_OK - No errors detected in Codestream ! + ! ! + ! CODESTREAM_READ - Codestream has been fully read. ! + ! ! + ! DEVELOPMENT HISTORY: ! + ! -------------------- ! + ! ! + ! Date Author Change Id Release Description ! + ! ---- ------ --------- ------- ----------- ! + ! 01.08.2019 Patrick Vogler B87D120 V 0.1.0 macros created ! + ! ! + \*------------------------------------------------------------------------------------------------------------------*/ + #define CODESTREAM_OK 0x00 + #define CODESTREAM_READ 0x80 + + /*------------------------------------------------------------------------------------------------------------------*\ + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! These Constants define common error messages used throughout the bwc library. ! + ! ! + ! MACROS: ! + ! ------- ! + ! Name Description ! + ! ---- ----------- ! + ! CSTERROR - Codestream parser has encoun- ! + ! tered invalid marker. ! + ! ! + ! MEMERROR - Allocation has returned a NULL ! + ! pointer due to limited memory. ! + ! ! + ! RDERROR - Invalid number of bytes read ! + ! from file. ! + ! ! + ! WRTERROR - Invalid number of bytes writ- ! + ! ten to file. ! + ! ! + ! DEVELOPMENT HISTORY: ! + ! -------------------- ! + ! ! + ! Date Author Change Id Release Description ! + ! ---- ------ --------- ------- ----------- ! + ! 01.12.2017 Patrick Vogler B87D120 V 0.1.0 macros created ! + ! ! + \*------------------------------------------------------------------------------------------------------------------*/ + #define CSTERROR "o##########################################################o\n"\ + "| ERROR: Invalid Codestream |\n"\ + "o##########################################################o\n" + + #define MEMERROR "o##########################################################o\n"\ + "| ERROR: Out of Memory |\n"\ + "o##########################################################o\n" + + #define RDERROR "o##########################################################o\n"\ + "| ERROR: Invalid Number of Bytes Read from File. |\n"\ + "o##########################################################o\n" + + #define WRTERROR "o##########################################################o\n"\ + "| ERROR: Invalid Number of Bytes Written to File. |\n"\ + "o##########################################################o\n" + + #define GET_DIM(x) (sizeof(x)/sizeof(*(x))) + /********************************************************************************************************************\ + || ___ ____ ____ ____ _ _ _ ____ ___ ___ _ _ ___ ____ ____ || + || | \ |___ |__/ |__/ | | | |___ | \ | \_/ |__] |___ [__ || + || |__/ |___ | \ | \ | \/ |___ |__/ | | | |___ ___] || + || || + \********************************************************************************************************************/ + /*------------------------------------------------------------------------------------------------------------------*\ + ! DESCRIPTION: ! + ! ------------ ! + ! ! + ! This structure defines the attributes of a single argument supported by the bwc ! + ! command line tool. ! + ! ! + ! PARAMETERS: ! + ! ----------- ! + ! Name Type Description ! + ! ---- ---- ----------- ! + ! active char - Flag indicating if the argu- ! + ! ment is active. ! + ! ! + ! arg_long char - Long form of the argument name. ! + ! ! + ! arg_short char - Short form of the argument ! + ! name. ! + ! ! + ! arg_type char - Flag signaling if the argument ! + ! is optional. ! + ! ! + ! type char - Flag signaling the argument ! + ! type. ! + ! ! + ! usage char - A string of 24 characters de- ! + ! scribing the argument usage. ! + ! ! + ! definition char - A string of 1024 characters ! + ! containing the argument de- ! + ! scription. ! + ! ! + ! DEVELOPMENT HISTORY: ! + ! -------------------- ! + ! ! + ! Date Author Change Id Release Description ! + ! ---- ------ --------- ------- ----------- ! + ! 14.02.2019 Patrick Vogler B87D120 V 0.1.0 struct created ! + ! 26.11.2020 Patrick Vogler B87E7E4 V 0.1.0 clean up ! + ! ! + \*------------------------------------------------------------------------------------------------------------------*/ + typedef struct + { + char active; + char arg_long[25]; + char arg_short[3]; + char arg_type[4]; + char type[5]; + char usage[25]; + char definition[1024]; + } bwc_cmdl_args; + + /*------------------------------------------------------------------------------------------------------------------*\ + ! DESCRIPTION: ! + ! ------------ ! + ! This structure describes a linked list which stores all the arguments and their ! + ! attributes supplied to the command line tool by the user. ! + ! ! + ! PARAMETERS: ! + ! ----------- ! + ! Name Type Description ! + ! ---- ---- ----------- ! + ! hash unsigned int(64 bit) - Uniquely identifiable hash that ! + ! corresponds to the arg/opt name. ! + ! ! + ! count unsigned int(8 bit) - Counter that signifies the num- ! + ! ber of modifier values stored ! + ! in the linked list node. ! + ! ! + ! dim unsigned int(8 bit) - Dimension(s) for which the mod- ! + ! ifiers have been defined ! + ! ! + ! active char - Flag indicating if the arg/opt ! + ! is active. ! + ! ! + ! num_opt double* - Array of numerical modifier ! + ! values. ! + ! ! + ! lit_opt char** - Character array of literal mod- ! + ! ifier values. ! + ! ! + ! DEPENDENCIES: ! + ! ------------- ! + ! Name TYPE ! + ! ---- ---- ! + ! next opt* ! + ! ! + ! root opt* ! + ! ! + ! DEVELOPMENT HISTORY: ! + ! -------------------- ! + ! ! + ! Date Author Change Id Release Description ! + ! ---- ------ --------- ------- ----------- ! + ! 26.04.2019 Patrick Vogler B87D120 V 0.1.0 struct created ! + ! 26.11.2020 Patrick Vogler B87E7E4 V 0.1.0 clean up ! + ! ! + \*------------------------------------------------------------------------------------------------------------------*/ + typedef struct arg + { + uint64_t hash; + uint8_t count; + uint8_t dim; + char active; + double *num_opt; + char **lit_opt; + struct arg *next; + struct arg *root; + } bwc_cmdl_arg_node; +#endif \ No newline at end of file diff --git a/1-bwc/public_header.py b/1-bwc/public_header.py new file mode 100644 index 0000000..595ebd8 --- /dev/null +++ b/1-bwc/public_header.py @@ -0,0 +1,376 @@ +#*================================================================================================*# +#| |# +#| /$$$$$$$ /$$ /$$ /$$ /$$ |# +#| | $$__ $$|__/ | $$ /$ | $$| $$ |# +#| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ |# +#| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ |# +#| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ |# +#| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ |# +#| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ |# +#| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ |# +#| /$$ \ $$ | $$ |# +#| | $$$$$$/ | $$ |# +#| \______/ |__/ |# +#| |# +#| DESCRIPTION: |# +#| ------------ |# +#| |# +#| This file describes python script used to assemble the public header file for |# +#| the BigWhoop compression library. |# +#| |# +#| -------------------------------------------------------------------------------------------- |# +#| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart |# +#| |# +#| Redistribution and use in source and binary forms, with or without modification, are |# +#| permitted provided that the following conditions are met: |# +#| |# +#| (1) Redistributions of source code must retain the above copyright notice, this list of |# +#| conditions and the following disclaimer. |# +#| |# +#| (2) Redistributions in binary form must reproduce the above copyright notice, this list |# +#| of conditions and the following disclaimer in the documentation and/or other |# +#| materials provided with the distribution. |# +#| |# +#| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS |# +#| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |# +#| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |# +#| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |# +#| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |# +#| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |# +#| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |# +#| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |# +#| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |# +#| |# +#*================================================================================================*# +#**************************************************************************************************# +#| _ _ _ ___ ____ ____ ___ |# +#| | |\/| |__] | | |__/ | |# +#| | | | | |__| | \ | |# +#| |# +#**************************************************************************************************# +from argparse import ArgumentParser +from math import ceil, floor +from pathlib import Path + +import os +import re +import sys + +#-------------------------# +# DEFINE CONSTANTS: # +#-------------------------# +tab = " " +text_width = 100 +deliminator = tab + "/*" + (text_width - 4 - len(tab)) * "=" + "*/\n" +ubox = tab + "/" + (text_width - 2 - len(tab)) * "*" + "\\\n" +lbox = tab + "\\" + (text_width - 2 - len(tab)) * "*" + "/\n" +sbox = "||" + +#----------------------------------------------------------# +# Setup the argument parser for the public header script # +# and parse for the user defined OpenMP and Precision arg. # +#----------------------------------------------------------# +parser = ArgumentParser(description='Public Header Assembly Script') +parser.add_argument('-OMP', dest='OpenMP', action='store_const', + const=True, default=False, + help='OpenMP Parallelization') +parser.add_argument('-Single', dest='SinglePrecision', action='store_const', + const=True, default=False, + help='Compilation using Single Precision Encoder') + +args = parser.parse_args() + + +#----------------------------------------------------------# +# Setup the paths to the source and destination. # +#----------------------------------------------------------# +current_path = Path().absolute() +source = current_path.joinpath('include/library/private') +destination = current_path.joinpath('include/library/public') + +if os.path.isdir(destination) == False: + os.mkdir(destination) + +header_files = [f for f in os.listdir(source) if os.path.isfile(os.path.join(source, f))] +header_files.remove('prim_types_double.h') +header_files.remove('prim_types_single.h') +print(header_files) + +#----------------------------------------------------------# +# Create the I/O stream and write the bwc file header. # +#----------------------------------------------------------# +public_header = open(destination.joinpath('bwc.h'), 'w+') +public_header.write("/*================================================================================================*\\\n" + "|| ||\n" + "|| /$$$$$$$ /$$ /$$ /$$ /$$ ||\n" + "|| | $$__ $$|__/ | $$ /$ | $$| $$ ||\n" + "|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ ||\n" + "|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ ||\n" + "|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ ||\n" + "|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ ||\n" + "|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ ||\n" + "|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ ||\n" + "|| /$$ \ $$ | $$ ||\n" + "|| | $$$$$$/ | $$ ||\n" + "|| \______/ |__/ ||\n" + "|| ||\n" + "|| -------------------------------------------------------------------------------------------- ||\n" + "|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart ||\n" + "|| ||\n" + "|| Redistribution and use in source and binary forms, with or without modification, are ||\n" + "|| permitted provided that the following conditions are met: ||\n" + "|| ||\n" + "|| (1) Redistributions of source code must retain the above copyright notice, this list of ||\n" + "|| conditions and the following disclaimer. ||\n" + "|| ||\n" + "|| (2) Redistributions in binary form must reproduce the above copyright notice, this list ||\n" + "|| of conditions and the following disclaimer in the documentation and/or other ||\n" + "|| materials provided with the distribution. ||\n" + "|| ||\n" + "|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS ||\n" + "|| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ||\n" + "|| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ||\n" + "|| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ||\n" + "|| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ||\n" + "|| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ||\n" + "|| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR ||\n" + "|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, ||\n" + "|| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ||\n" + "|| ||\n" + "\*================================================================================================*/\n" + "#ifndef BWC_H\n" + "#define BWC_H\n") + +#----------------------------------------------------------# +# Generate the necessary includes for the bwc.h file. # +#----------------------------------------------------------# +title_length = 31 + +lspaces = ceil((text_width - 2*len(sbox) - title_length - len(tab))/2) +rspaces = floor((text_width - 2*len(sbox) - title_length - len(tab))/2) + +public_header.write(ubox + tab + sbox + lspaces * " " + "_ _ _ ____ _ _ _ ___ ____" + rspaces * " " + sbox + "\n" + + tab + sbox + lspaces * " " + "| |\ | | | | | | \ |___" + rspaces * " " + sbox + "\n" + + tab + sbox + lspaces * " " + "| | \| |___ |___ |__| |__/ |___" + rspaces * " " + sbox + "\n" + + tab + sbox + (text_width - 2*len(sbox) - len(tab)) * " " + "||\n" + lbox) + +public_header.write(tab + "#include \n" + tab + "#include \n\n") + +#----------------------------------------------------------# +# Ingest primitive type definitions from the corresponding # +# header files according to the user specified precision. # +#----------------------------------------------------------# +title_length = 62 + +lspaces = ceil((text_width - 2*len(sbox) - title_length - len(tab))/2) +rspaces = floor((text_width - 2*len(sbox) - title_length - len(tab))/2) + +public_header.write(ubox + tab + sbox + lspaces * " " + "___ ____ _ _ _ _ ___ _ _ _ ____ ___ _ _ ___ ____ ____" + rspaces * " " + "||\n" + + tab + sbox + lspaces * " " + "|__] |__/ | |\/| | | | | | |___ | \_/ |__] |___ [__ " + rspaces * " " + "||\n" + + tab + sbox + lspaces * " " + "| | \ | | | | | | \/ |___ | | | |___ ___]" + rspaces * " " + "||\n" + + tab + sbox + (text_width - 2*len(sbox) - len(tab)) * " " + "||\n" + lbox) + +if(args.SinglePrecision == True): + file = "prim_types_single.h" +else: + file = "prim_types_double.h" + +print_flag = False +with open(source.joinpath(file)) as f: + for line in f: + if("/*" in line and print_flag == 1): + break + if("typedef" in line or print_flag == 1): + print_flag = True + public_header.write(line) +f.close + +#----------------------------------------------------------# +# Ingest Macros with 'BWC_' prefix from all header files. # +#----------------------------------------------------------# +title_length = 29 + +lspaces = ceil((text_width - 2*len(sbox) - title_length - len(tab))/2) +rspaces = floor((text_width - 2*len(sbox) - title_length - len(tab))/2) + +public_header.write(ubox + tab + sbox + lspaces * " " + "_ _ ____ ____ ____ ____ ____" + rspaces * " " + "||\n" + + tab + sbox + lspaces * " " + "|\/| |__| | |__/ | | [__ " + rspaces * " " + "||\n" + + tab + sbox + lspaces * " " + "| | | | |___ | \ |__| ___]" + rspaces * " " + "||\n" + + tab + sbox + (text_width - 2*len(sbox) - len(tab)) * " " + "||\n" + lbox) + +with open(source.joinpath(file)) as f: + for line in f: + if("#define" in line): + if("MAXIMUM_NO_PASSES" in line or + "PREC_BIT" in line): + if("//" in line): + public_header.write((line.split('/', 1)[0]).rstrip() + '\n') + else: + public_header.write(line) +f.close + +printFlg = False +buff = "" +brktCnt = 0 + +for file in header_files: + with open(source.joinpath(file)) as f: + for line in f: + if("BWC_" in line): + if("ifndef" in line): + next(f) + elif("#define" in line and line[len(line) - len(line.lstrip())] != "/"): + while True: + if("//" in line): + buff = buff + (line.split('/', 1)[0]).rstrip() + '\n' + else: + buff = buff + line + if("\\" not in line): + public_header.write(buff+"\n") + buff = "" + break + line = next(f) + f.close +public_header.write("\n") + +#----------------------------------------------------------# +# Ingest enums with 'bwc_' prefix from all header files # +# excluding prim_types_****.h. # +#----------------------------------------------------------# +title_length = 42 + +lspaces = ceil((text_width - 2*len(sbox) - title_length - len(tab))/2) +rspaces = floor((text_width - 2*len(sbox) - title_length - len(tab))/2) + +public_header.write(ubox + tab + sbox + lspaces * " " + "____ ____ _ _ ____ ___ ____ _ _ ___ ____" + rspaces * " " + "||\n" + + tab + sbox + lspaces * " " + "| | | |\ | [__ | |__| |\ | | [__ " + rspaces * " " + "||\n" + + tab + sbox + lspaces * " " + "|___ |__| | \| ___] | | | | \| | ___]" + rspaces * " " + "||\n" + + tab + sbox + (text_width - 2*len(sbox) - len(tab)) * " " + "||\n" + lbox) + +delimFlg = False +buff = "" + +for file in header_files: + with open(source.joinpath(file)) as f: + for line in f: + if("typedef enum" in line): + while True: + buff = buff + (line.split('/', 1)[0]).rstrip() + '\n' + if("}" in line and ";" in line): + if("bwc_" in line): + if(delimFlg == True): + public_header.write(deliminator) + public_header.write(buff) + delimFlg = True + buff = "" + break + line = next(f) + f.close + +#----------------------------------------------------------# +# Ingest derived types with 'bwc_' prefix from all header # +# files excluding prim_types_****.h. # +#----------------------------------------------------------# +title_length = 64 + +lspaces = ceil((text_width - 2*len(sbox) - title_length - len(tab))/2) +rspaces = floor((text_width - 2*len(sbox) - title_length - len(tab))/2) + +public_header.write("\n") +public_header.write(ubox + tab + sbox + lspaces * " " + "___ ____ ____ ____ _ _ _ ____ ___ ___ _ _ ___ ____ ____" + rspaces * " " + "||\n" + + tab + sbox + lspaces * " " + "| \ |___ |__/ |__/ | | | |___ | \ | \_/ |__] |___ [__ " + rspaces * " " + "||\n" + + tab + sbox + lspaces * " " + "|__/ |___ | \ | \ | \/ |___ |__/ | | | |___ ___]" + rspaces * " " + "||\n" + + tab + sbox + (text_width - 2*len(sbox) - len(tab)) * " " + "||\n" + lbox) + +printFlg = False +delimFlg = False +preProcFlg = False +buff = "" +brktCnt = 0 + +for file in header_files: + with open(source.joinpath(file)) as f: + for line in f: + if("typedef struct" in line or + "typedef union" in line): + if("bwc_" in line): + printFlg = True + while True: + buff = buff + (line.split('/', 1)[0]).rstrip() + '\n' + if("{" in line): + brktCnt = brktCnt + 1 + if("}" in line): + brktCnt = brktCnt - 1 + if(brktCnt == 0): + if("bwc_" in line): + printFlg = True + break + line = next(f) + if (printFlg == True): + if(delimFlg == True): + public_header.write(deliminator) + public_header.write(buff) + delimFlg = True + buff = "" + + f.close + +#----------------------------------------------------------# +# Ingest public functions with 'bwc_' prefix from all # +# header files excluding prim_types_****.h. # +#----------------------------------------------------------# +title_length = 70 + +lspaces = ceil((text_width - 2*len(sbox) - title_length - len(tab))/2) +rspaces = floor((text_width - 2*len(sbox) - title_length - len(tab))/2) + +public_header.write("\n" + ubox + tab + sbox + lspaces * " " + "___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____" + rspaces * " " + "||\n" + + tab + sbox + lspaces * " " + "|__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ " + rspaces * " " + "||\n" + + tab + sbox + lspaces * " " + "| |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___]" + rspaces * " " + "||\n" + + tab + sbox + (text_width - 2*len(sbox) - len(tab)) * " " + "||\n" + lbox) + +public_header.write(tab + "#ifdef __cplusplus\n" + + tab + tab + "extern \"C\" {\n" + + tab + "#endif\n\n") + +files = os.listdir("include/library/private") +printFlg = False +ltab = 0 +tmp = "" +buff = "" + +for file in files: + with open(source.joinpath(file)) as f: + for line in f: + if("#if defined" in line): + line = next(f) + if("(" in line): + tmp = line[0:line.index('(')].strip() + tmp = tmp[tmp.rfind(' '):-1] + else: + tmp = "" + if("bwc_" in tmp and "!" not in line and "#if" not in line): + if("/*" in buff or "*/" in buff or "//" in buff): + buff = "" + + if(print_flag == True): + buff = deliminator + buff + else: + print_flag = True + + while True: + buff = buff + line[ltab:len(line)] + if(");" in line): + break + line = next(f) + + public_header.write(buff) + buff = line + f.close + +public_header.write("\n" + tab + "#ifdef __cplusplus\n" + + tab + tab + "}\n" + + tab + "#endif\n") + +public_header.write("#endif") +public_header.close \ No newline at end of file diff --git a/1-bwc/src/interfaces/fortran/bwc.F90 b/1-bwc/src/interfaces/fortran/bwc.F90 new file mode 100644 index 0000000..b71e98a --- /dev/null +++ b/1-bwc/src/interfaces/fortran/bwc.F90 @@ -0,0 +1,421 @@ +!*================================================================================================*! +!| |! +!| /$$$$$$$ /$$ /$$ /$$ /$$ |! +!| | $$__ $$|__/ | $$ /$ | $$| $$ |! +!| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ |! +!| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ |! +!| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ |! +!| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ |! +!| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ |! +!| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ |! +!| /$$ \ $$ | $$ |! +!| | $$$$$$/ | $$ |! +!| \______/ |__/ |! +!| |! +!| DESCRIPTION: |! +!| ------------ |! +!| |! +!| This file defines a Fortran interface for the Big Whoop compression library. |! +!| |! +!| -------------------------------------------------------------------------------------------- |! +!| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart |! +!| |! +!| Redistribution and use in source and binary forms, with or without modification, are |! +!| permitted provided that the following conditions are met: |! +!| |! +!| (1) Redistributions of source code must retain the above copyright notice, this list of |! +!| conditions and the following disclaimer. |! +!| |! +!| (2) Redistributions in binary form must reproduce the above copyright notice, this list |! +!| of conditions and the following disclaimer in the documentation and/or other |! +!| materials provided with the distribution. |! +!| |! +!| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS |! +!| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |! +!| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |! +!| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |! +!| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |! +!| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |! +!| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |! +!| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |! +!| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |! +!| |! +!*================================================================================================*! +module bwc + !************************************************************************************************! + !| _ _ _ ____ _ _ _ ___ ____ |! + !| | |\ | | | | | | \ |___ |! + !| | | \| |___ |___ |__| |__/ |___ |! + !| |! + !************************************************************************************************! + use, intrinsic :: iso_c_binding, only: C_PTR, C_INT64_T, C_INT32_T, C_INT16_T, C_INT8_T, & + C_INT, C_DOUBLE, C_CHAR, C_SIGNED_CHAR + IMPLICIT NONE + PRIVATE + + !************************************************************************************************! + !| ____ ____ _ _ ____ ___ ____ _ _ ___ ____ |! + !| | | | |\ | [__ | |__| |\ | | [__ |! + !| |___ |__| | \| ___] | | | | \| | ___] |! + !| |! + !************************************************************************************************! + ENUM, BIND(C) + enumerator :: bwc_dwt_9_7 = 0, & + bwc_dwt_5_3 = 1, & + bwc_dwt_haar = 2 + END ENUM + !*==============================================================================================*! + ENUM, BIND(C) + enumerator :: bwc_prog_LRCP = 0 + END ENUM + !*==============================================================================================*! + ENUM, BIND(C) + enumerator :: bwc_qt_none = 0, & + bwc_qt_derived = 1 + END ENUM + !*==============================================================================================*! + ENUM, BIND(C) + enumerator :: bwc_tile_sizeof = 0, & + bwc_tile_numbof = 1 + END ENUM + + !************************************************************************************************! + !| ___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ |! + !| |__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ |! + !| | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] |! + !| |! + !************************************************************************************************! + interface + function initialize_data_f(field, nX, nY, nZ, nTS, nPar, file_extension) result(data) & + BIND(C, NAME="bwc_initialize_data") + IMPORT + !*-----------------------*! + ! DEFINE POINTERS: ! + !*-----------------------*! + TYPE(C_PTR), VALUE :: field + TYPE(C_PTR) :: data + + !*-----------------------*! + ! DEFINE INT VARIABLES: ! + !*-----------------------*! + INTEGER(KIND=C_INT16_T), VALUE :: nX, nY, nZ + INTEGER(KIND=C_INT8_T), VALUE :: nTS, nPar + + !*-----------------------*! + ! DEFINE CHAR VARIABLES: ! + !*-----------------------*! + CHARACTER(KIND=C_CHAR) :: file_extension(*) + end function initialize_data_f + !*============================================================================================*! + subroutine add_param_f(data, name, sample, dim, precision) & + BIND(C, NAME="bwc_add_param") + IMPORT + !*-----------------------*! + ! DEFINE POINTERS: ! + !*-----------------------*! + TYPE(C_PTR), VALUE :: data + + !*-----------------------*! + ! DEFINE INT VARIABLES: ! + !*-----------------------*! + INTEGER(KIND=C_INT16_T), VALUE :: sample + INTEGER(KIND=C_INT8_T), VALUE :: precision + INTEGER(KIND=C_SIGNED_CHAR), VALUE :: dim + + !*-----------------------*! + ! DEFINE CHAR VARIABLES: ! + !*-----------------------*! + CHARACTER(KIND=C_CHAR) :: name(*) + end subroutine add_param_f + !*============================================================================================*! + subroutine get_data_f(data, buffer, size) & + BIND(C, NAME="bwc_get_data") + IMPORT + !*-----------------------*! + ! DEFINE POINTERS: ! + !*-----------------------*! + TYPE(C_PTR), VALUE :: data + TYPE(C_PTR), VALUE :: buffer + + !*-----------------------*! + ! DEFINE INT VARIABLES: ! + !*-----------------------*! + INTEGER(KIND=C_INT64_T), Value :: size + end subroutine get_data_f + !*============================================================================================*! + subroutine free_data_f(data) & + BIND(C, NAME="bwc_free_data") + IMPORT + !*-----------------------*! + ! DEFINE POINTERS: ! + !*-----------------------*! + TYPE(C_PTR), VALUE :: data + end subroutine free_data_f + !*============================================================================================*! + subroutine kill_compression_f(field) & + BIND(C, NAME="bwc_kill_compression") + IMPORT + !*-----------------------*! + ! DEFINE POINTERS: ! + !*-----------------------*! + TYPE(C_PTR), VALUE :: field + end subroutine kill_compression_f + !*============================================================================================*! + function initialize_field_f(data) result(field) & + BIND(C, NAME="bwc_initialize_field") + IMPORT + !*-----------------------*! + ! DEFINE POINTERS: ! + !*-----------------------*! + TYPE(C_PTR), VALUE :: data + TYPE(C_PTR) :: field + end function initialize_field_f + !*============================================================================================*! + subroutine set_error_resilience_f(field) & + BIND(C, NAME="bwc_set_error_resilience") + IMPORT + !*-----------------------*! + ! DEFINE POINTERS: ! + !*-----------------------*! + TYPE(C_PTR), VALUE :: field + end subroutine set_error_resilience_f + !*============================================================================================*! + subroutine set_quantization_style_f(field, quantization_style) & + BIND(C, NAME="bwc_set_quantization_style") + IMPORT + !*-----------------------*! + ! DEFINE POINTERS: ! + !*-----------------------*! + TYPE(C_PTR), VALUE :: field + + !*-----------------------*! + ! DEFINE INT VARIABLES: ! + !*-----------------------*! + INTEGER(KIND=C_INT), VALUE :: quantization_style + end subroutine set_quantization_style_f + !*============================================================================================*! + subroutine set_quantization_step_size_f(field, delta) & + BIND(C, NAME="bwc_set_quantization_step_size") + IMPORT + !*-----------------------*! + ! DEFINE POINTERS: ! + !*-----------------------*! + TYPE(C_PTR), VALUE :: field + + !*-----------------------*! + ! DEFINE FLOAT VARIABLES: ! + !*-----------------------*! + REAL(KIND=C_DOUBLE), VALUE :: delta + end subroutine set_quantization_step_size_f + !*============================================================================================*! + subroutine set_progression_f(field, progression) & + BIND(C, NAME="bwc_set_progression") + IMPORT + !*-----------------------*! + ! DEFINE POINTERS: ! + !*-----------------------*! + TYPE(C_PTR), VALUE :: field + + !*-----------------------*! + ! DEFINE INT VARIABLES: ! + !*-----------------------*! + INTEGER(KIND=C_INT), VALUE :: progression + end subroutine set_progression_f + !*============================================================================================*! + subroutine set_kernels_f(field, KernelX, KernelY, KernelZ, KernelTS) & + BIND(C, NAME="bwc_set_kernels") + IMPORT + !*-----------------------*! + ! DEFINE POINTERS: ! + !*-----------------------*! + TYPE(C_PTR), VALUE :: field + + !*-----------------------*! + ! DEFINE INT VARIABLES: ! + !*-----------------------*! + INTEGER(KIND=C_INT), VALUE :: KernelX, KernelY + INTEGER(KIND=C_INT), VALUE :: KernelZ, KernelTS + end subroutine set_kernels_f + !*============================================================================================*! + subroutine set_decomp_f(field, decompX, decompY, decompZ, decompTS) & + BIND(C, NAME="bwc_set_decomp") + IMPORT + !*-----------------------*! + ! DEFINE POINTERS: ! + !*-----------------------*! + TYPE(C_PTR), VALUE :: field + + !*-----------------------*! + ! DEFINE INT VARIABLES: ! + !*-----------------------*! + INTEGER(KIND=C_INT8_T), VALUE :: decompX, decompY + INTEGER(KIND=C_INT8_T), VALUE :: decompZ, decompTS + end subroutine set_decomp_f + !*============================================================================================*! + subroutine set_precincts_f(field, pX, pY, pZ, pTS) & + BIND(C, NAME="bwc_set_precincts") + IMPORT + !*-----------------------*! + ! DEFINE POINTERS: ! + !*-----------------------*! + TYPE(C_PTR), VALUE :: field + + !*-----------------------*! + ! DEFINE INT VARIABLES: ! + !*-----------------------*! + INTEGER(KIND=C_INT8_T), VALUE :: pX, pY + INTEGER(KIND=C_INT8_T), VALUE :: pZ, pTS + end subroutine set_precincts_f + !*============================================================================================*! + subroutine set_codeblocks_f(field, cbX, cbY, cbZ, cbTS) & + BIND(C, NAME="bwc_set_codeblocks") + IMPORT + !*-----------------------*! + ! DEFINE POINTERS: ! + !*-----------------------*! + TYPE(C_PTR), VALUE :: field + + !*-----------------------*! + ! DEFINE INT VARIABLES: ! + !*-----------------------*! + INTEGER(KIND=C_INT8_T), VALUE :: cbX, cbY + INTEGER(KIND=C_INT8_T), VALUE :: cbZ, cbTS + end subroutine set_codeblocks_f + !*============================================================================================*! + subroutine set_qm_f(field, Qm) & + BIND(C, NAME="bwc_set_qm") + IMPORT + !*-----------------------*! + ! DEFINE POINTERS: ! + !*-----------------------*! + TYPE(C_PTR), VALUE :: field + + !*-----------------------*! + ! DEFINE INT VARIABLES: ! + !*-----------------------*! + INTEGER(KIND=C_INT8_T), VALUE :: Qm + end subroutine set_qm_f + !*============================================================================================*! + subroutine set_tiles_f(field, tilesX, tilesY, tilesZ, tilesTS, instr) & + BIND(C, NAME="bwc_set_tiles") + IMPORT + !*-----------------------*! + ! DEFINE POINTERS: ! + !*-----------------------*! + TYPE(C_PTR), VALUE :: field + + !*-----------------------*! + ! DEFINE INT VARIABLES: ! + !*-----------------------*! + INTEGER(KIND=C_INT64_T), VALUE :: tilesX, tilesY, tilesZ + INTEGER(KIND=C_INT16_T), VALUE :: tilesTS + INTEGER(KIND=C_INT), VALUE :: instr + end subroutine set_tiles_f + !*============================================================================================*! + function create_compression_f(field, rate_control) result(error_flag) & + BIND(C, NAME="bwc_create_compression") + IMPORT + !*-----------------------*! + ! DEFINE POINTERS: ! + !*-----------------------*! + TYPE(C_PTR), VALUE :: field + + !*-----------------------*! + ! DEFINE INT VARIABLES: ! + !*-----------------------*! + INTEGER(KIND=C_INT8_T) :: error_flag + + !*-----------------------*! + ! DEFINE CHAR VARIABLES: ! + !*-----------------------*! + CHARACTER(KIND=C_CHAR) :: rate_control(*) + end function create_compression_f + !*============================================================================================*! + function compress_f(field, data) result(error_flag) & + BIND(C, NAME="bwc_compress") + IMPORT + !*-----------------------*! + ! DEFINE POINTERS: ! + !*-----------------------*! + TYPE(C_PTR), VALUE :: field + TYPE(C_PTR), VALUE :: data + + !*-----------------------*! + ! DEFINE INT VARIABLES: ! + !*-----------------------*! + INTEGER(KIND=C_INT8_T) :: error_flag + end function compress_f + !*============================================================================================*! + function create_decompression_f(data, layer) result(field) & + BIND(C, NAME="bwc_create_decompression") + IMPORT + !*-----------------------*! + ! DEFINE POINTERS: ! + !*-----------------------*! + TYPE(C_PTR) :: field + TYPE(C_PTR), VALUE :: data + + !*-----------------------*! + ! DEFINE INT VARIABLES: ! + !*-----------------------*! + INTEGER(KIND=C_INT8_T), VALUE :: layer + end function create_decompression_f + !*============================================================================================*! + function decompress_f(field, data) result(error_flag) & + BIND(C, NAME="bwc_decompress") + IMPORT + !*-----------------------*! + ! DEFINE POINTERS: ! + !*-----------------------*! + TYPE(C_PTR), VALUE :: field + TYPE(C_PTR), VALUE :: data + + !*-----------------------*! + ! DEFINE INT VARIABLES: ! + !*-----------------------*! + INTEGER(KIND=C_INT8_T) :: error_flag + end function decompress_f + end interface + + !************************************************************************************************! + !| _ _ _ ___ ____ ____ ____ ____ ____ ____ |! + !| | |\ | | |___ |__/ |___ |__| | |___ |! + !| | | \| | |___ | \ | | | |___ |___ |! + !| |! + !************************************************************************************************! + public :: bwc_dwt_9_7, & + bwc_dwt_5_3, & + bwc_dwt_haar + + public :: bwc_prog_LRCP + + public :: bwc_qt_none, & + bwc_qt_derived + + public :: bwc_tile_sizeof, & + bwc_tile_numbof + + public :: bwc_initialize_data, & + bwc_get_data, & + bwc_free_data + + public :: bwc_initialize_field, & + bwc_add_param, & + bwc_kill_compression + + public :: bwc_set_error_resilience, & + bwc_set_quantization_style, & + bwc_set_quantization_step_size, & + bwc_set_progression, & + bwc_set_kernels, & + bwc_set_decomp, & + bwc_set_precincts, & + bwc_set_codeblocks, & + bwc_set_qm, & + bwc_set_tiles, + + public :: bwc_create_compression, & + bwc_compress, & + bwc_create_decompression, & + bwc_decompress +end module bwc \ No newline at end of file diff --git a/1-bwc/src/interfaces/python/bwc.py b/1-bwc/src/interfaces/python/bwc.py new file mode 100644 index 0000000..8b3fd5c --- /dev/null +++ b/1-bwc/src/interfaces/python/bwc.py @@ -0,0 +1,214 @@ +#/=====================================================================================================================\# +#| |# +#| /$$$$$$$ /$$ /$$ /$$ /$$ |# +#| | $$__ $$|__/ | $$ /$ | $$| $$ |# +#| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ |# +#! | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ |# +#| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ |# +#| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ |# +#| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ |# +#| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ |# +#| /$$ \ $$ | $$ |# +#| | $$$$$$/ | $$ |# +#| \______/ |__/ |# +#| |# +#| DESCRIPTION: |# +#| ------------ |# +#| |# +#| This file defines a Python interface for the Big Whoop compression library |# +#| |# +#| FUNCTIONS: |# +#| ---------- |# +#| - bwc_free_field |# +#| - bwc_add_param |# +#| - bwc_set_tiles |# +#| - bwc_set_kernels |# +#| - bwc_set_decomp |# +#| - bwc_set_precincts |# +#| - bwc_set_codeblocks |# +#| - bwc_set_progression |# +#| - bwc_set_error_resilience |# +#| - bwc_set_quantization_style |# +#| - bwc_set_qm |# +#| - bwc_set_quantization_step_size |# +#| - bwc_set_memory_limit |# +#| - bwc_compress |# +#| - bwc_decompress |# +#| |# +#| |# +#| DEVELOPMENT HISTORY: |# +#| -------------------- |# +#| |# +#| Date Author Change Id Release Description |# +#| ---- ------ --------- ------- ----------- |# +#| 17.03.2021 Patrick Vogler B87D120 V 0.1.0 Python Module created |# +#| |# +#| |# +#| ------------------------------------------------------------------------------------------------------ |# +#| |# +#| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart |# +#| |# +#| Redistribution and use in source and binary forms, with or without modification, are permitted |# +#| provided that the following conditions are met: |# +#| |# +#| (1) Redistributions of source code must retain the above copyright notice, this list of |# +#| conditions and the following disclaimer. |# +#| |# +#| (2) Redistributions in binary form must reproduce the above copyright notice, this list |# +#| of conditions and the following disclaimer in the documentation and/or other materials |# +#| provided with the distribution. |# +#| |# +#| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED |# +#| WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |# +#| PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR |# +#| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |# +#| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |# +#| INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |# +#| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |# +#| ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |# +#| |# +#\=====================================================================================================================/# +#/=====================================================================================================================\# +#| _ _ _ ____ _ _ _ ___ ____ |# +#| | |\ | | | | | | \ |___ |# +#| | | \| |___ |___ |__| |__/ |___ |# +#| |# +#\=====================================================================================================================/# +import ctypes + +from numpy.ctypeslib import ndpointer +from enum import Enum + +libbwc = ctypes.cdll.LoadLibrary("../../../lib/libbwc.so") + +#/=====================================================================================================================\# +#| ____ ____ _ _ ____ ___ ____ _ _ ___ ____ |# +#| | | | |\ | [__ | |__| |\ | | [__ |# +#| |___ |__| | \| ___] | | | | \| | ___] |# +#| |# +#\=====================================================================================================================/# +class _const(): + class DWT(Enum): + CDF_9_7 = 0 + LEGALL_5_3 = 1 + HAAR = 2 + + class PROG(Enum): + LRCP = 0 + + class QT(object): + NONE = 0 + DERIVED = 1 + + class TILE(Enum): + SIZEOF = 0 + NUMBOF = 1 +const = _const() + +#/=====================================================================================================================\# +#| ___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ |# +#| |__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ |# +#| | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] |# +#| |# +#\=====================================================================================================================/# +def free_data(data): + fun = libbwc.bwc_free_data + fun.restype = None + fun.argtypes = [ctypes.c_void_p] + fun(data) +#=======================================================================================================================# +def initialize_data(data, nX, nY, nZ, nTS, nPar, file_extension): + fun = libbwc.bwc_initialize_data + fun.restype = ctypes.c_void_p + fun.argtypes = [ndpointer(ctypes.c_double, flags="C_CONTIGUOUS"), + ctypes.c_uint64, + ctypes.c_uint64, + ctypes.c_uint64, + ctypes.c_uint16, + ctypes.c_uint8, + ctypes.c_char_p] + return ctypes.c_void_p(fun(data, nX, nY, nZ, nTS, nPar, file_extension.encode('utf-8'))) +#=======================================================================================================================# +def get_data(data, buffer, size): + fun = libbwc.bwc_get_data + fun.restype = None + fun.argtypes = [ctypes.c_void_p, + ndpointer(ctypes.c_double, flags="C_CONTIGUOUS"), + ctypes.c_uint64] + fun(data, buffer, size) +#=======================================================================================================================# +def add_param(data, name, sample, dim, precision): + fun = libbwc.bwc_add_param + fun.restype = None + fun.argtypes = [ctypes.c_void_p, + ctypes.c_char_p, + ctypes.c_uint16, + ctypes.c_uint8, + ctypes.c_uint8] + fun(data, name.encode('utf-8'), sample, dim, precision) +#=======================================================================================================================# +def kill_compression(field): + fun = libbwc.bwc_kill_compression + fun.restype = None + fun.argtypes = [ctypes.c_void_p] + fun(field) +#=======================================================================================================================# +def initialize_field(data): + fun = libbwc.bwc_initialize_field + fun.restype = ctypes.c_void_p + fun.argtypes = [ctypes.c_void_p] + return ctypes.c_void_p(fun(data)) +#=======================================================================================================================# +def set_codeblocks(field, cbX, cbY, cbZ, cbTS): + fun = libbwc.bwc_set_codeblocks + fun.restype = None + fun.argtypes = [ctypes.c_void_p, ctypes.c_uint8, ctypes.c_uint8, ctypes.c_uint8, ctypes.c_uint8] + fun(field, cbX, cbY, cbZ, cbTS) +#=======================================================================================================================# +def set_decomp(field, decompX, decompY, decompZ, decompTS): + fun = libbwc.bwc_set_decomp + fun.restype = None + fun.argtypes = [ctypes.c_void_p, ctypes.c_uint8, ctypes.c_uint8, ctypes.c_uint8, ctypes.c_uint8] + fun(field, decompX, decompY, decompZ, decompTS) +#=======================================================================================================================# +def set_qm(field, Qm): + fun = libbwc.bwc_set_qm + fun.restype = None + fun.argtypes = [ctypes.c_void_p, ctypes.c_int8] + fun(field, Qm) +#=======================================================================================================================# +def set_tiles(field, tilesX, tilesY, tilesZ, tilesTS, instr): + fun = libbwc.bwc_set_tiles + fun.restype = None + fun.argtypes = [ctypes.c_void_p, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_char_p] + fun(field, tilesX, tilesY, tilesZ, tilesTS, instr.encode('utf-8')) +#=======================================================================================================================# +def set_precincts(field, pX, pY, pZ, pTS): + fun = libbwc.bwc_set_precincts + fun.restype = None + fun.argtypes = [ctypes.c_void_p, ctypes.c_uint8, ctypes.c_uint8, ctypes.c_uint8, ctypes.c_uint8] + fun(field, pX, pY, pZ, pTS) +#=======================================================================================================================# +def create_compression(field, rate_control): + fun = libbwc.bwc_create_compression + fun.restype = None + fun.argtypes = [ctypes.c_void_p, ctypes.c_char_p] + fun(field, rate_control.encode('utf-8')) +#=======================================================================================================================# +def compress(field, data): + fun = libbwc.bwc_compress + fun.restype = None + fun.argtypes = [ctypes.c_void_p, ctypes.c_void_p] + fun(field, data) +#=======================================================================================================================# +def create_decompression(field, data): + fun = libbwc.bwc_create_decompression + fun.restype = ctypes.c_void_p + fun.argtypes = [ctypes.c_void_p, ctypes.c_uint8] + return ctypes.c_void_p(fun(field, data)) +#=======================================================================================================================# +def decompress(field, data): + fun = libbwc.bwc_decompress + fun.restype = None + fun.argtypes = [ctypes.c_void_p, ctypes.c_void_p] + fun(field, data) \ No newline at end of file diff --git a/1-bwc/src/interfaces/reader/eas3.c b/1-bwc/src/interfaces/reader/eas3.c new file mode 100644 index 0000000..c09fa90 --- /dev/null +++ b/1-bwc/src/interfaces/reader/eas3.c @@ -0,0 +1,1544 @@ +/*==================================================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| FILE NAME: eas3.c || +|| || +|| || +|| DESCRIPTION: || +|| ------------ || +|| This file defines simple read and write functions used to access conforming eas3 datasets. || +|| || +|| FILE REFERENCES: || +|| ---------------- || +|| || +|| Name I/O Description || +|| ---- --- ----------- || +|| fp input/output - Numerical dataset stored in the EAS3 data format. || +|| || +|| || +|| PUBLIC FUNCTIONS: || +|| ----------------- || +|| - read_eas3 || +|| - write_eas3 || +|| || +|| DEVELOPMENT HISTORY: || +|| -------------------- || +|| || +|| Date Author Change Id Release Description Of Change || +|| ---- ------ --------- ------- --------------------- || +|| 20.6.2018 Patrick Vogler B87D120 V 0.1.0 source file created || +|| || +|| -------------------------------------------------------------------------------------------------------------------- || +|| || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are permitted provided that the || +|| following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of conditions and || +|| the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions || +|| and the following disclaimer in the documentation and/or other materials provided with the || +|| distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, || +|| INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE || +|| DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, || +|| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR || +|| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, || +|| WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE || +|| USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*==================================================================================================================================*/ + +/************************************************************************************************************\ +|| _ _ _ ____ _ _ _ ___ ____ || +|| | |\ | | | | | | \ |___ || +|| | | \| |___ |___ |__| |__/ |___ || +|| || +\************************************************************************************************************/ +#include +#include +#include +#include +#include + +#include "eas3.h" +#include "bwccmdl.h" + +/************************************************************************************************************\ +|| ___ ____ _ _ _ ____ ___ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || +|| |__] |__/ | | | |__| | |___ |___ | | |\ | | | | | | |\ | [__ || +|| | | \ | \/ | | | |___ | |__| | \| |___ | | |__| | \| ___] || +|| || +\************************************************************************************************************/ +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: uint32 bytes_used(bitstream *const stream) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is used to evaluate the number of bytes that have already been ! +! written to the allocated bitstream memory block. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! stream bitstream* - Structure that ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! unsigned int(32 bit) - Number of bites that have been written to the ! +! bitstream. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 13.05.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uint64 +bytes_used(bitstream const *const stream) +{ + if(stream->T == 0xFF) + { + return stream->L + 1; + } + else + { + return stream->L; + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: bitstream* bwc_init_stream(uchar* memory, uint32 size, char instr) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is used to initialize a bwc bitstream. For encoding, a null pointer ! +! is passed as a memory handle and the function will allocate a memory block with the ! +! specified stream size. For decoding, a valid memory handle, passed by the function ! +! caller, will be stored in the bitstream structure. The byte buffer counter t, ! +! stream size Lmax and size increment are initialized with their appropriate values. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! size unsigned int(32 bit) - Initial size of the bwc stream. ! +! ! +! memory unsigned char - Memory handle for the bwc stream memory ! +! block. ! +! ! +! instr char - Constant used to instruct the field ! +! initialization. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! bitstream* - Memory handle for the initialized bwc stream. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 19.06.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +bitstream* +init_stream(uchar* memory, uint32 size, char instr) +{ + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bitstream *stream; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(instr == 'c' || instr == 'd'); + + /*--------------------------------------------------------*\ + ! Allocate the bwc stream structure. ! + \*--------------------------------------------------------*/ + stream = calloc(1, sizeof(bitstream)); + if(!stream) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return NULL; + } + + /*--------------------------------------------------------*\ + ! Evaluate if a valid memory handle has been passed by the ! + ! function caller. ! + \*--------------------------------------------------------*/ + if(!memory) + { + /*--------------------------------------------------------*\ + ! If no valid memory handle has been passed, allocate a ! + ! memory block with the specifiec stream size. ! + \*--------------------------------------------------------*/ + stream->memory = calloc(size, sizeof(uchar)); + if(!stream->memory) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return NULL; + } + } + else + { + /*--------------------------------------------------------*\ + ! If a valid memory handle has been passed for decoding, ! + ! save the memory handle in the bwc stream structure. ! + \*--------------------------------------------------------*/ + stream->memory = memory; + } + + /*--------------------------------------------------------*\ + ! Initialize the byte buffer counter, stream size and size ! + ! increment for the current stream. ! + \*--------------------------------------------------------*/ + stream->t = (instr == 'c') ? 8 : 0; + stream->Lmax = size; + stream->size_incr = (uint64)(size / 2); + + /*--------------------------------------------------------*\ + ! Return the stream memory handle. ! + \*--------------------------------------------------------*/ + return stream; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void bwc_emit_chunck(bitstream *const stream, const uchar* string, const uint64 length) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is used to write an additional chunck of size length to a bwc bitstream. ! +! ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! stream bitstream* - Structure used to assemble a bwc bit- ! +! bitstream. ! +! ! +! chunck unsigned char* - Memory handle for a data block that is ! +! to be written to the bwc bitstream. ! +! ! +! size unsigned int(64 bit) - Size of the data block. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 22.06.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +emit_chunck(bitstream *const stream, const uchar* chunck, const uint64 size) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 Lreq; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(stream); + assert(chunck); + + /*--------------------------------------------------------*\ + ! Evaluate the memory block size if the current chunck of ! + ! data is written to the stream. ! + \*--------------------------------------------------------*/ + Lreq = (bytes_used(stream) + size); + + /*--------------------------------------------------------*\ + ! Check if the enough memory has been allocated for the ! + ! stream to store the additional data chunck. ! + \*--------------------------------------------------------*/ + if(Lreq > stream->Lmax) + { + /*--------------------------------------------------------*\ + ! If the stream is not large enough, check if this is due ! + ! to an error encountered in a previous writing operation ! + \*--------------------------------------------------------*/ + if(!stream->error) + { + /*--------------------------------------------------------*\ + ! If the error flag is not set, increase the stream size ! + ! until it is large enough to store the additional data ! + ! chunck. ! + \*--------------------------------------------------------*/ + while(Lreq > stream->Lmax) + { + stream->Lmax += stream->size_incr + size; + stream->size_incr = (uint64)(stream->Lmax / 2); + } + + /*--------------------------------------------------------*\ + ! Reallocate the stream data block. ! + \*--------------------------------------------------------*/ + stream->memory = realloc(stream->memory, stream->Lmax); + if(!stream->memory) + { + // memory allocation error + stream->error |= 1; + stream->Lmax = 0; + return; + } + } + else + { + /*--------------------------------------------------------*\ + ! Exit to function caller if error flag has been set. ! + \*--------------------------------------------------------*/ + return; + } + } + + /*--------------------------------------------------------*\ + ! Copy the additional data to the stream memory block. ! + \*--------------------------------------------------------*/ + memcpy(stream->memory + stream->L, chunck, size); + + /*--------------------------------------------------------*\ + ! Increment the number of bytes written to the stream with ! + ! the size of the newly added data chunck. ! + \*--------------------------------------------------------*/ + stream->L += size; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! stream bitstream* - Structure used to assemble a bwc bit- ! +! bitstream. ! +! ! +! size unsigned int(64 bit) - Size of the data block. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! uchar* - Data chunck requested by the function caller. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 22.06.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uchar* +get_chunck(bitstream *const stream, const uint64 size) +{ + /*-----------------------*\ + ! DEFINE CHAR VARIABLES: ! + \*-----------------------*/ + uchar *tmp; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(stream); + + /*--------------------------------------------------------*\ + ! Check if the number of bytes to be read from the stream ! + ! does not exceed the number of bytes still present in its ! + ! memory block. ! + \*--------------------------------------------------------*/ + if(bytes_used(stream) + size <= stream->Lmax) + { + /*--------------------------------------------------------*\ + ! Allocate a temporary array used to store the bytes that ! + ! are extracted from the stream. ! + \*--------------------------------------------------------*/ + tmp = calloc(size, sizeof(uchar)); + if(!tmp) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return NULL; + } + + /*--------------------------------------------------------*\ + ! Copy the bytes requested from the function caller from ! + ! the stream to the temporary data block. ! + \*--------------------------------------------------------*/ + memcpy(tmp, stream->memory + stream->L, size); + + /*--------------------------------------------------------*\ + ! Increment the number of bytes read from the bitstream. ! + \*--------------------------------------------------------*/ + stream->L += size; + + /*--------------------------------------------------------*\ + ! Return the temporary data block to the function caller. ! + \*--------------------------------------------------------*/ + return tmp; + } + else + { + /*--------------------------------------------------------*\ + ! If the requested block size exceeds the information left ! + ! in the bitstream, set the bitstream error flag and ! + ! return a NULL pointer. ! + \*--------------------------------------------------------*/ + stream->error |= 1; + return NULL; + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! - Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uchar +terminate_stream(bitstream *stream, bwc_stream *const packed_stream) +{ + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(stream); + + if(packed_stream) + { + if(stream->error) + { + return 1; + } + else if(stream->L != stream->Lmax) + { + stream->Lmax = stream->L; + stream->memory = realloc(stream->memory, stream->Lmax); + if(!stream->memory) + { + // memory allocation error + fprintf(stderr, MEMERROR); + stream->Lmax = 0; + return 1; + } + } + + packed_stream->memory = stream->memory; + packed_stream->access = stream->memory; + packed_stream->size = stream->L; + packed_stream->position = 0; + } + else + { + free(stream->memory); + } + + free(stream); + return 0; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! ! +! DESCRIPTION: ! +! ------------ ! +! This function converts the endianess of half, single or double precision values. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! value void* - Memory address of the parame- ! +! ter to be converted. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description ! +! ---- ------ --------- ------- ----------- ! +! 30.04.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! 21.11.2019 Patrick Vogler B87E7E4 V 0.1.0 functionality expanded ! +! to 32 bit integers ! +! 21.11.2019 Patrick Vogler B87E7E4 V 0.1.0 functionality expanded ! +! to 16 bit integers ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +endian_conversion(void *value, + uint8_t const accuracy) +{ + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(value); + + switch(accuracy) + { + case 2: + { + uint16_t *tmp = (uint16_t*)value; + + *tmp = (uint16_t)( *tmp << 8) | + (uint16_t)( *tmp >> 8); + break; + } + + case 4: + { + uint32_t *tmp = (uint32_t*)value; + + *tmp = (uint32_t)((*tmp << 8) & 0xFF00FF00) | + (uint32_t)((*tmp >> 8) & 0x00FF00FF); + + *tmp = (uint32_t)( *tmp << 16) | + (uint32_t)( *tmp >> 16); + break; + } + + case 8: + { + uint64_t *tmp = (uint64_t*)value; + + *tmp = (uint64_t)((*tmp << 8) & 0xFF00FF00FF00FF00ULL) | + (uint64_t)((*tmp >> 8) & 0x00FF00FF00FF00FFULL); + + *tmp = (uint64_t)((*tmp << 16) & 0xFFFF0000FFFF0000ULL) | + (uint64_t)((*tmp >> 16) & 0x0000FFFF0000FFFFULL); + + *tmp = (uint64_t)( *tmp << 32) | + (uint64_t)( *tmp >> 32); + break; + } + default: + { + break; + } + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: uchar read_eas3_header(bwc_data *const data) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function opens an eas3 file and checks it for its validity. Once the specified file ! +! has been verified, its header and flow field data is read and stored in the bwc_data ! +! structure. ! +! ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! filename char* - Defines the filename of the eas3 file ! +! that is to be opened and read. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! file - Defines a structure used to store all ! +! the relevant parameters and the data ! +! field of an eas3 file. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 20.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static uchar +read_eas3_header(bwc_data *const data) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 Lread; + uint64 i; + uint8 precision; + + /*-----------------------*\ + ! DEFINE CHAR VARIABLES: ! + \*-----------------------*/ + uchar *buffer_char; + char param_name[ATTRLEN + 1] = {}; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_inf *info; + bitstream *aux; + eas3_std_params params; + + /*-----------------------*\ + ! DEFINE FILE POINTER: ! + \*-----------------------*/ + FILE *fp; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(data); + + /*--------------------------------------------------------*\ + ! Save the file pointer and data info structure in tempo- ! + ! rary variables to make the code more readable. ! + \*--------------------------------------------------------*/ + fp = data->fp; + info = &data->info; + + /*--------------------------------------------------------*\ + ! Allocate the character buffer used to store chunks of ! + ! memory read from the specified file. ! + \*--------------------------------------------------------*/ + buffer_char = calloc(20, sizeof(uchar)); + if(!buffer_char) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + /*--------------------------------------------------------*\ + ! Read the first 20 bits of the specified file that store ! + ! the identifier of an eas3 file. ! + \*--------------------------------------------------------*/ + if(fread(buffer_char, sizeof(uchar) , 20, fp) != 20) + { + // invalid read + fprintf(stderr, RDERROR); + free(buffer_char); + return 1; + } + + /*--------------------------------------------------------*\ + ! Check if the identifier corresponds to a valid EAS3 file.! + ! If this is not the case, close the file pointer and exit ! + ! the bwc command-line tool. ! + \*--------------------------------------------------------*/ + if(!strstr((char*)buffer_char, "EAS3_I8R8")) + { + // invalid file type + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: Invalid EAS3 file format |\n"\ + "o##########################################################o\n"); + free(buffer_char); + return 1; + } + + /*--------------------------------------------------------*\ + ! Allocate the auxiliary information packed stream. ! + \*--------------------------------------------------------*/ + data->codestream.aux = calloc(1, sizeof(bwc_stream)); + if(!data->codestream.aux) + { + // memory allocation error + fprintf(stderr, MEMERROR); + free(buffer_char); + return 1; + } + + /*--------------------------------------------------------*\ + ! Initialize the stream for the auxiliary information mem- ! + ! ory block. The initial size of the auxiliary memory ! + ! block has been chosen arbitrarily and should be large ! + ! enough to prevent excessive reallocation. ! + \*--------------------------------------------------------*/ + aux = init_stream(NULL, AUX_SIZE, 'c'); + if(!aux) + { + // memory allocation error + fprintf(stderr, MEMERROR); + free(buffer_char); + return 1; + } + + /*--------------------------------------------------------*\ + ! Read the next 22 bytes from the specified file that re- ! + ! present the eas3 standard parameters. The information ! + ! is stored in the eas3_std_params structure. ! + \*--------------------------------------------------------*/ + if(fread(¶ms, sizeof(uint64), 22, fp) != 22) + { + // invalid read + fprintf(stderr, RDERROR); + free(buffer_char); + return 1; + } + + /*--------------------------------------------------------*\ + ! Check if the specified file is of the EAS3 type. ! + \*--------------------------------------------------------*/ + if(params.file_type == EAS2_TYPE) + { + // invalid file format + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: The EAS2 file format is not supported |\n"\ + "o##########################################################o\n"); + free(buffer_char); + return 1; + } + + /*--------------------------------------------------------*\ + ! Emit a file format hash to the aux stream to identify it ! + ! as a eas3 auxiliary information block. This hash can be ! + ! used to properly handle decompression into an eas3 file ! + ! or conversion to other file formats. ! + \*--------------------------------------------------------*/ + // emit_symbol(aux, hash("eas3"), 8); + + /*--------------------------------------------------------*\ + ! Emit the standard parameters to the auxiliary informa- ! + ! tion information memory block. ! + \*--------------------------------------------------------*/ + emit_chunck(aux, (uchar*)¶ms, 176); + + /*--------------------------------------------------------*\ + ! Convert the parameters required for the bwc compression ! + ! stage to little endian and store them in the file info ! + ! structure. ! + \*--------------------------------------------------------*/ + endian_conversion(¶ms.nzs, 8); + info->nTS = (uint16)params.nzs; + + endian_conversion(¶ms.npar, 8); + info->nPar = (uint8)params.npar; + + endian_conversion(¶ms.ndim1, 8); + info->nX = (uint64)params.ndim1; + + endian_conversion(¶ms.ndim2, 8); + info->nY = (uint64)params.ndim2; + + endian_conversion(¶ms.ndim3, 8); + info->nZ = (uint64)params.ndim3; + + endian_conversion(¶ms.accuracy, 8); + if(params.accuracy == 1) + { + precision = 4; + } + else if(params.accuracy == 2) + { + precision = 8; + } + else + { + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: The accuracy of the specified dataset is not sup- |\n"\ + "| ported by the compression algorithm. |\n"\ + "o##########################################################o\n"); + return 1; + } + + /*--------------------------------------------------------*\ + ! Convert the size parameters, used to load the rest of the! + ! header, to little endian. ! + \*--------------------------------------------------------*/ + endian_conversion(¶ms.size_time, 8); + endian_conversion(¶ms.size_parameter, 8); + endian_conversion(¶ms.size_dim1, 8); + endian_conversion(¶ms.size_dim2, 8); + endian_conversion(¶ms.size_dim3, 8); + endian_conversion(¶ms.udef_char_size, 8); + endian_conversion(¶ms.udef_int_size, 8); + endian_conversion(¶ms.udef_real_size, 8); + + /*--------------------------------------------------------*\ + ! Allocate the time step array. If successful, read the ! + ! timesteps from the file stream. ! + \*--------------------------------------------------------*/ + buffer_char = realloc(buffer_char, info->nTS * sizeof(uint64)); + if(!buffer_char) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + if(fread(buffer_char, sizeof(uint64), info->nTS, fp) != info->nTS) + { + // invalid read + fprintf(stderr, RDERROR); + free(buffer_char); + return 1; + } + + /*--------------------------------------------------------*\ + ! Emit the time step array to the auxiliary information ! + ! memory block. ! + \*--------------------------------------------------------*/ + emit_chunck(aux, buffer_char, info->nTS * sizeof(uint64)); + + /*--------------------------------------------------------*\ + ! Check if any attributes have been specified in the eas3 ! + ! file. ! + \*--------------------------------------------------------*/ + if(params.attribute_mode == EAS3_ALL_ATTR) + { + /*--------------------------------------------------------*\ + ! Allocate the buffer character array. If successful, read ! + ! the timestep attributes from the file stream. ! + \*--------------------------------------------------------*/ + buffer_char = realloc(buffer_char, info->nTS * ATTRLEN * sizeof(char)); + if(!buffer_char) + { + // memory allocation error + fprintf(stderr, MEMERROR); + free(buffer_char); + return 1; + } + + if(fread(buffer_char, sizeof(char), info->nTS * ATTRLEN, fp) != (info->nTS * ATTRLEN)) + { + // invalid read + fprintf(stderr, RDERROR); + free(buffer_char); + return 1; + } + + /*--------------------------------------------------------*\ + ! Emit the timestep attribute array to the auxiliary infor-! + ! mation memory block. ! + \*--------------------------------------------------------*/ + emit_chunck(aux, buffer_char, info->nTS * ATTRLEN * sizeof(char)); + + for(i = 0; i < info->nPar; ++i) + { + /*--------------------------------------------------------*\ + ! Read the parameter name from the file stream and add all ! + ! the necessary parameter information to the paramter ! + ! linked list. ! + \*--------------------------------------------------------*/ + if(fread(param_name, sizeof(char), ATTRLEN, fp) != ATTRLEN) + { + // invalid read + fprintf(stderr, RDERROR); + free(buffer_char); + return 1; + } + + bwc_add_param(data, param_name, precision); + + /*--------------------------------------------------------*\ + ! Read the parameter name from the file stream and add all ! + ! the necessary parameter information to the paramter ! + ! linked list. | + \*--------------------------------------------------------*/ + memset(param_name, 0, ATTRLEN + 1); + } + } + + /*--------------------------------------------------------*\ + ! Evaluate the number of bytes that remain to be read from ! + ! the eas3 file header. ! + \*--------------------------------------------------------*/ + Lread = 0; + Lread += (params.attribute_mode == EAS3_ALL_ATTR) ? 3 * ATTRLEN : 0; + Lread += (params.gmode_time > EAS3_NO_G) ? params.size_time * sizeof(uint64) : 0; + Lread += (params.gmode_param > EAS3_NO_G) ? params.size_parameter * sizeof(uint64) : 0; + Lread += (params.gmode_dim1 > EAS3_NO_G) ? params.size_dim1 * sizeof(uint64) : 0; + Lread += (params.gmode_dim2 > EAS3_NO_G) ? params.size_dim2 * sizeof(uint64) : 0; + Lread += (params.gmode_dim3 > EAS3_NO_G) ? params.size_dim3 * sizeof(uint64) : 0; + Lread += (params.udef_param == EAS3_ALL_UDEF) ? params.udef_char_size * sizeof(char) * UDEFLEN + + params.udef_int_size * sizeof(uint64) + + params.udef_real_size * sizeof(double) : 0; + + /*--------------------------------------------------------*\ + ! Reallocate the buffer character array to allow for the ! + ! storage of the remaining header bytes of the eas3 file. ! + \*--------------------------------------------------------*/ + buffer_char = realloc(buffer_char, Lread * sizeof(uchar)); + if(!buffer_char) + { + // memory allocation error + fprintf(stderr, MEMERROR); + free(buffer_char); + return 1; + } + + /*--------------------------------------------------------*\ + ! Read the remaining header bytes from the file stream. ! + \*--------------------------------------------------------*/ + if(fread(buffer_char, sizeof(uchar), Lread, fp) != Lread) + { + // invalid read + fprintf(stderr, RDERROR); + free(buffer_char); + return 1; + } + + /*--------------------------------------------------------*\ + ! Emit the remaining header information the the auxiliary ! + ! information stream. ! + \*--------------------------------------------------------*/ + emit_chunck(aux, buffer_char, Lread); + + /*--------------------------------------------------------*\ + ! Free the buffer character array. ! + \*--------------------------------------------------------*/ + free(buffer_char); + + /*--------------------------------------------------------*\ + ! Terminate the auxiliary information stream. If success- ! + ! ful, the address to the aux memory block stored is ! + ! stored in the file structure alongside its size. ! + \*--------------------------------------------------------*/ + if(terminate_stream(aux, data->codestream.aux)) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + return 0; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: uchar read_eas3_header(bwc_data *const data) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function opens an eas3 file and checks it for its validity. Once the specified file ! +! has been verified, its header and flow field data is read and stored in the bwc_data ! +! structure. ! +! ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! filename char* - Defines the filename of the eas3 file ! +! that is to be opened and read. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! file - Defines a structure used to store all ! +! the relevant parameters and the data ! +! field of an eas3 file. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 20.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static uchar +write_eas3_header(bwc_data *const data) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 Lwrite; + + /*-----------------------*\ + ! DEFINE CHAR VARIABLES: ! + \*-----------------------*/ + uchar *buffer_char; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_inf *info; + bitstream *aux; + eas3_std_params *params; + bwc_cmd_opts_ll *param; + + /*-----------------------*\ + ! DEFINE FILE POINTER: ! + \*-----------------------*/ + FILE *fp; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(data); + + /*--------------------------------------------------------*\ + ! Save the file pointer and data info structure in tempo- ! + ! rary variables to make the code more readable. ! + \*--------------------------------------------------------*/ + fp = data->fp; + info = &data->info; + + /*--------------------------------------------------------*\ + ! Write the valid EAS3 identifier to the specified file. ! + \*--------------------------------------------------------*/ + if(fwrite("EAS3_I8R8 ", sizeof(char), 20, fp) != 20) + { + // invalid read + fprintf(stderr, WRTERROR); + return 1; + } + + /*--------------------------------------------------------*\ + ! Initialize the auxiliary information stream. ! + \*--------------------------------------------------------*/ + aux = init_stream(data->codestream.aux->memory, + data->codestream.aux->size, 'd'); + + /*--------------------------------------------------------*\ + ! Get the standard parameters from the auxiliary informa- ! + ! memory block and write them to the file stream. ! + \*--------------------------------------------------------*/ + params = (eas3_std_params*)get_chunck(aux, 176); + + if(fwrite(params, sizeof(uint64), 22, fp) != 22) + { + // invalid read + fprintf(stderr, WRTERROR); + return 1; + } + + /*--------------------------------------------------------*\ + ! Convert the size parameters, used to write the rest of ! + ! the header, to little endian. ! + \*--------------------------------------------------------*/ + endian_conversion(¶ms->accuracy, 8); + endian_conversion(¶ms->size_time, 8); + endian_conversion(¶ms->size_parameter, 8); + endian_conversion(¶ms->size_dim1, 8); + endian_conversion(¶ms->size_dim2, 8); + endian_conversion(¶ms->size_dim3, 8); + endian_conversion(¶ms->udef_char_size, 8); + endian_conversion(¶ms->udef_int_size, 8); + endian_conversion(¶ms->udef_real_size, 8); + + /*--------------------------------------------------------*\ + ! Allocate the buffer character array. If successful, get ! + ! the timestep array from the auxiliary information block ! + ! and write it to the file stream. ! + \*--------------------------------------------------------*/ + buffer_char = get_chunck(aux, info->nTS * sizeof(uint64)); + if(!buffer_char) + { + // memory allocation error + fprintf(stderr, MEMERROR); + free(buffer_char); + return 1; + } + + if(fwrite(buffer_char, sizeof(uint64), info->nTS, fp) != info->nTS) + { + // invalid read + fprintf(stderr, WRTERROR); + free(buffer_char); + return 1; + } + free(buffer_char); + + /*--------------------------------------------------------*\ + ! Check if any attributes have been specified in the aux- ! + ! iliary information block. ! + \*--------------------------------------------------------*/ + if(params->attribute_mode == EAS3_ALL_ATTR) + { + /*--------------------------------------------------------*\ + ! Allocate the buffer character array. If successful, get ! + ! the timestep attribute array from the auxiliary informa- ! + ! tion block and write it to the file stream. ! + \*--------------------------------------------------------*/ + buffer_char = get_chunck(aux, info->nTS * ATTRLEN); + if(!buffer_char) + { + // memory allocation error + fprintf(stderr, MEMERROR); + free(buffer_char); + return 1; + } + + if(fwrite(buffer_char, sizeof(uchar), info->nTS * ATTRLEN, fp) != (info->nTS * ATTRLEN)) + { + // invalid read + fprintf(stderr, WRTERROR); + free(buffer_char); + return 1; + } + free(buffer_char); + + /*--------------------------------------------------------*\ + ! Loop through the parameter array and... ! + \*--------------------------------------------------------*/ + if(data->info.parameter) + { + param = data->info.parameter->root; + + while(param != NULL) + { + /*--------------------------------------------------------*\ + ! ... write the parameter name from the info structure to ! + ! the file stream. ! + \*--------------------------------------------------------*/ + if(fwrite(param->name, sizeof(char), ATTRLEN, fp) != ATTRLEN) + { + // invalid read + fprintf(stderr, WRTERROR); + free(buffer_char); + return 1; + } + + param = param -> next; + } + } + } + + /*--------------------------------------------------------*\ + ! Evaluate the number of bytes that remain to be read from ! + ! the auxiliary information block. ! + \*--------------------------------------------------------*/ + Lwrite = 0; + Lwrite += (params->attribute_mode == EAS3_ALL_ATTR) ? 3 * ATTRLEN : 0; + Lwrite += (params->gmode_time > EAS3_NO_G) ? params->size_time * sizeof(uint64) : 0; + Lwrite += (params->gmode_param > EAS3_NO_G) ? params->size_parameter * sizeof(uint64) : 0; + Lwrite += (params->gmode_dim1 > EAS3_NO_G) ? params->size_dim1 * sizeof(uint64) : 0; + Lwrite += (params->gmode_dim2 > EAS3_NO_G) ? params->size_dim2 * sizeof(uint64) : 0; + Lwrite += (params->gmode_dim3 > EAS3_NO_G) ? params->size_dim3 * sizeof(uint64) : 0; + Lwrite += (params->udef_param == EAS3_ALL_UDEF) ? params->udef_char_size * sizeof(char) * UDEFLEN + + params->udef_int_size * sizeof(uint64) + + params->udef_real_size * sizeof(double) : 0; + + /*--------------------------------------------------------*\ + ! Allocate the buffer character array. If successful, get ! + ! the remaining eas header bytes from the auxiliary infor- ! + ! mation block and write it to the file stream. ! + \*--------------------------------------------------------*/ + buffer_char = get_chunck(aux, Lwrite); + if(!buffer_char) + { + // memory allocation error + fprintf(stderr, MEMERROR); + free(buffer_char); + return 1; + } + + if(fwrite(buffer_char, sizeof(uchar), Lwrite, fp) != Lwrite) + { + // invalid read + fprintf(stderr, WRTERROR); + free(buffer_char); + return 1; + } + free(buffer_char); + + /*--------------------------------------------------------*\ + ! Free the auxiliary information memory block stream and ! + ! params structure. ! + \*--------------------------------------------------------*/ + free(aux); + free(params); + + return 0; +} + +/************************************************************************************************************\ +|| ___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || +|| |__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ || +|| | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] || +|| || +\************************************************************************************************************/ +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: bwc_data* read_eas3(const char* const filename) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function opens an eas3 file and checks it for its validity. Once the specified file ! +! has been verified, its header and flow field data is read and stored in the bwc_data ! +! structure. ! +! ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! filename char* - Defines the filename of the eas3 file ! +! that is to be opened and read. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! file - Defines a structure used to store all ! +! the relevant parameters and the data ! +! field of an eas3 file. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 20.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +bwc_data* +read_eas3(char *const filename) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 Lfield; + uint64 i; + uint32 root; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_data *data; + + /*--------------------------------------------------------*\ + ! Allocate the data structure. ! + \*--------------------------------------------------------*/ + data = calloc(1, sizeof(bwc_data)); + if(!data) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return NULL; + } + + /*--------------------------------------------------------*\ + ! Set the file identifier used to select the appropriate ! + ! write operation during decompression. ! + \*--------------------------------------------------------*/ + strncpy(data->info.f_ext, "eas", 4); + + /*--------------------------------------------------------*\ + ! Open the specified file for reading. If the file doesn't ! + ! exist, exit the bwc command-line tool. ! + \*--------------------------------------------------------*/ + if((data->fp = fopen(filename, "rb")) == NULL) + { + // error opening file + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: Could not open or read %-25s|\n"\ + "o##########################################################o\n", filename); + bwc_free_data(data); + return NULL; + } + + /*--------------------------------------------------------*\ + ! Parse the eas3 header and store the information in the ! + ! data structure. ! + \*--------------------------------------------------------*/ + if(read_eas3_header(data)) + { + //error reading eas3 header + bwc_free_data(data); + } + + /*--------------------------------------------------------*\ + ! Determine the size of the dataset present in the eas3 ! + ! file and store the information in the bwc_gl_data struc- ! + ! ture. ! + \*--------------------------------------------------------*/ + root = ftell(data->fp); + fseek(data->fp, 0L, SEEK_END); + Lfield = (ftell(data->fp) - root) / sizeof(double); + fseek(data->fp, root, SEEK_SET); + + /*--------------------------------------------------------*\ + ! Check if the file_size coincide with the specified dimen-! + ! sions, timesteps number of parameters or bitdepth speci- ! + ! fied in the eas3 file header. ! + \*--------------------------------------------------------*/ + if(Lfield != data->info.nX * data->info.nY * + data->info.nZ * data->info.nTS * + data->info.nPar) + { + // error in file size + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: Number of bytes present in the input file doesn't |\n"\ + "| coincide with the specified dimensions, timesteps |\n"\ + "| and number of parameters specified in the file |\n"\ + "| header. |\n"\ + "o##########################################################o\n"); + bwc_free_data(data); + return NULL; + } + + if(data->info.parameter->precision == 4) + { + /*--------------------------------------------------------*\ + ! Allocate the real field that will hold the numerical ! + ! dataset. ! + \*--------------------------------------------------------*/ + data->field.d = NULL; + data->field.f = calloc(Lfield, sizeof(float)); + if(!data->field.d) + { + // memory allocation error + fprintf(stderr, MEMERROR); + bwc_free_data(data); + return NULL; + } + + /*--------------------------------------------------------*\ + ! Read the flow field data from the specified eas3 file. ! + \*--------------------------------------------------------*/ + if(fread(data->field.f, sizeof(float), Lfield, data->fp) != Lfield) + { + // invalid read + fprintf(stderr, RDERROR); + bwc_free_data(data); + return NULL; + } + + /*--------------------------------------------------------*\ + ! Convert the flow field data read from the eas3 file from ! + ! big endian to little endian. ! + \*--------------------------------------------------------*/ + for(i = Lfield; i --> 0;) + { + endian_conversion(&data->field.f[i], 4); + } + } + else if(data->info.parameter->precision == 8) + { + /*--------------------------------------------------------*\ + ! Allocate the real field that will hold the numerical ! + ! dataset. ! + \*--------------------------------------------------------*/ + data->field.f = NULL; + data->field.d = calloc(Lfield, sizeof(double)); + if(!data->field.d) + { + // memory allocation error + fprintf(stderr, MEMERROR); + bwc_free_data(data); + return NULL; + } + + /*--------------------------------------------------------*\ + ! Read the flow field data from the specified eas3 file. ! + \*--------------------------------------------------------*/ + if(fread(data->field.d, sizeof(double), Lfield, data->fp) != Lfield) + { + // invalid read + fprintf(stderr, RDERROR); + bwc_free_data(data); + return NULL; + } + + /*--------------------------------------------------------*\ + ! Convert the flow field data read from the eas3 file from ! + ! big endian to little endian. ! + \*--------------------------------------------------------*/ + for(i = Lfield; i --> 0;) + { + endian_conversion(&data->field.d[i], 8); + } + } + + /*--------------------------------------------------------*\ + ! Close the file pointer and return the bwc_data structure ! + ! to the function caller. ! + \*--------------------------------------------------------*/ + fclose(data->fp); + data->fp = NULL; + return data; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: uchar write_eas3(bwc_data *const file, char *const filename) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function creates a valid eas3 file from the information stored in the bwc_data ! +! structure. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! filename char* - Defines the filename of the eas3 file ! +! that is to be opened and read. ! +! ! +! file bwc_data* - Defines a structure used to store all ! +! the relevant parameters and the data ! +! field of an eas3 file. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! uchar - Returns an unsigned char for error handling. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 20.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uchar +write_eas3(bwc_data *const data, char *const filename) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 Lfield; + uint64 i; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(data); + + /*--------------------------------------------------------*\ + ! Open the specified file for writing. If the file already ! + ! exist, discard its content. If the file cannot be creat- ! + ! ed, exit the bwc command-line tool. ! + \*--------------------------------------------------------*/ + if((data->fp = fopen(filename, "wb")) == NULL) + { + // error opening file + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: Could not open or write %-24s|\n"\ + "o##########################################################o\n", filename); + return 1; + } + + /*--------------------------------------------------------*\ + ! Write the eas3 header to the specified file. ! + \*--------------------------------------------------------*/ + if(write_eas3_header(data)) + { + //error reading eas3 header + return 1; + } + + + /*--------------------------------------------------------*\ + ! Calculate the size of the data field used for the endian ! + ! conversion and write operations. ! + \*--------------------------------------------------------*/ + Lfield = data->info.nX * data->info.nY * + data->info.nZ * data->info.nTS * data->info.nPar; + + if(data->info.parameter->precision == 4) + { + /*--------------------------------------------------------*\ + ! Convert the flow field data from big endian to endian. ! + \*--------------------------------------------------------*/ + for(i = Lfield; i --> 0;) + { + endian_conversion(&data->field.f[i], 4); + } + + /*--------------------------------------------------------*\ + ! Write the flow field data to the specified eas3 file. ! + \*--------------------------------------------------------*/ + if(fwrite(data->field.f, sizeof(float), Lfield, data->fp) != Lfield) + { + // invalid read + fprintf(stderr, WRTERROR); + return 1; + } + } + else if(data->info.parameter->precision == 8) + { + /*--------------------------------------------------------*\ + ! Convert the flow field data from big endian to endian. ! + \*--------------------------------------------------------*/ + for(i = Lfield; i --> 0;) + { + endian_conversion(&data->field.d[i], 8); + } + + /*--------------------------------------------------------*\ + ! Write the flow field data to the specified eas3 file. ! + \*--------------------------------------------------------*/ + if(fwrite(data->field.d, sizeof(double), Lfield, data->fp) != Lfield) + { + // invalid read + fprintf(stderr, WRTERROR); + return 1; + } + } + + /*--------------------------------------------------------*\ + ! Close the file pointer and return to the function caller.! + \*--------------------------------------------------------*/ + fclose(data->fp); + data->fp = NULL; + return 0; +} \ No newline at end of file diff --git a/1-bwc/src/library/CMakeLists.txt b/1-bwc/src/library/CMakeLists.txt new file mode 100755 index 0000000..d760a60 --- /dev/null +++ b/1-bwc/src/library/CMakeLists.txt @@ -0,0 +1,123 @@ +#*================================================================================================*# +#| |# +#| /$$$$$$$ /$$ /$$ /$$ /$$ |# +#| | $$__ $$|__/ | $$ /$ | $$| $$ |# +#| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ |# +#| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ |# +#| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ |# +#| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ |# +#| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ |# +#| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ |# +#| /$$ \ $$ | $$ |# +#| | $$$$$$/ | $$ |# +#| \______/ |__/ |# +#| |# +#| DESCRIPTION: |# +#| ------------ |# +#| |# +#| Defines the cmake script for the libbwc library. |# +#| |# +#| -------------------------------------------------------------------------------------------- |# +#| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart |# +#| |# +#| Redistribution and use in source and binary forms, with or without modification, are |# +#| permitted provided that the following conditions are met: |# +#| |# +#| (1) Redistributions of source code must retain the above copyright notice, this list of |# +#| conditions and the following disclaimer. |# +#| |# +#| (2) Redistributions in binary form must reproduce the above copyright notice, this list |# +#| of conditions and the following disclaimer in the documentation and/or other |# +#| materials provided with the distribution. |# +#| |# +#| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS |# +#| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |# +#| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |# +#| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |# +#| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |# +#| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |# +#| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |# +#| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |# +#| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |# +#| |# +#*================================================================================================*# +#----------------------------------------------------------# +# Assemble the public header for the BigWhoop library # +#----------------------------------------------------------# +set(PYTHON_ARGUMENT "") + +if("${CMAKE_BUILD_TYPE}" STREQUAL "Release") + if(OPENMP_FOUND) + set(PYTHON_ARGUMENT ${PYTHON_ARGUMENT} -OMP) + endif() +endif() + +if("${PREC}" STREQUAL "Single") + set(PYTHON_ARGUMENT ${PYTHON_ARGUMENT} -Single) +endif() + +execute_process(COMMAND python3 public_header.py ${PYTHON_ARGUMENT} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + +#----------------------------------------------------------# +# Set the linking type according to user choice and add # +# the library to the current project # +#----------------------------------------------------------# +if("${LINK}" STREQUAL "Static") + set(BWC_LINK "STATIC") +else() + set(BWC_LINK "SHARED") +endif() + +add_library(bwclib ${BWC_LINK} bitstream.c + libbwc.c + codestream.c + dwt.c + mq.c + tier1.c + tier2.c + tagtree.c) + +#----------------------------------------------------------# +# Set the target compile definition for the encoder/decod- # +# er bit precision. # +#----------------------------------------------------------# +if("${PREC}" STREQUAL "Single") + target_compile_definitions(bwclib PRIVATE -DBWC_SINGLE_PRECISION) +else() + target_compile_definitions(bwclib PRIVATE -DBWC_DOUBLE_PRECISION) +endif() + +#----------------------------------------------------------# +# Set the Version and SOVersion and define the public API # +# for the BigWhoop library. # +#----------------------------------------------------------# +set_target_properties(bwclib PROPERTIES VERSION ${BWC_VERSION} + SOVERSION ${BWC_VERSION_MAJOR} + PUBLIC_HEADER ${CMAKE_SOURCE_DIR}/include/library/public/bwc.h) + +#----------------------------------------------------------# +# Setup up the include directory for the BigWhoop library. # +#----------------------------------------------------------# +target_include_directories(bwclib PRIVATE ${CMAKE_SOURCE_DIR}/include/library/private + PUBLIC $ + $) + +#----------------------------------------------------------# +# Link the BigWhoop library to the math.h library. # +#----------------------------------------------------------# +target_link_libraries(bwclib PRIVATE m) + +#----------------------------------------------------------# +# Setup the install directories and target exporting for # +# config-file packaging. # +#----------------------------------------------------------# +install( TARGETS bwclib + EXPORT bwc-targets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + +#----------------------------------------------------------# +# Define the output name for the BigWhoop library. # +#----------------------------------------------------------# +set_property(TARGET bwclib PROPERTY OUTPUT_NAME bwc) \ No newline at end of file diff --git a/1-bwc/src/library/bitstream.c b/1-bwc/src/library/bitstream.c new file mode 100755 index 0000000..1618c87 --- /dev/null +++ b/1-bwc/src/library/bitstream.c @@ -0,0 +1,988 @@ +/*================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| DESCRIPTION: || +|| ------------ || +|| || +|| This file describes a set of functions that can be used to create, manipulate || +|| and terminate a bitstream. These functions facilitate the creation or reading || +|| of a compressed bwc codestream and can emit/extract information on a per bit, || +|| symbol (64-bit) or string basis. || +|| || +|| -------------------------------------------------------------------------------------------- || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are || +|| permitted provided that the following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of || +|| conditions and the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || +|| of conditions and the following disclaimer in the documentation and/or other || +|| materials provided with the distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS || +|| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF || +|| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE || +|| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, || +|| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF || +|| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) || +|| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || +|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, || +|| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*================================================================================================*/ +/************************************************************************************************************\ +|| _ _ _ ____ _ _ _ ___ ____ || +|| | |\ | | | | | | \ |___ || +|| | | \| |___ |___ |__| |__/ |___ || +|| || +\************************************************************************************************************/ +#include +#include +#include +#include + +#include "libbwc.h" + +/************************************************************************************************************\ +|| ___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || +|| |__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ || +|| | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] || +|| || +\************************************************************************************************************/ +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: uint32 bytes_used(bitstream *const stream) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is used to evaluate the number of bytes that have already been ! +! written to the allocated bitstream memory block. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! stream bitstream* - Structure that ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! unsigned int(32 bit) - Number of bites that have been written to the ! +! bitstream. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 13.05.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uint64 +bytes_used(bitstream const *const stream) +{ + if(stream->T == 0xFF) + { + return stream->L + 1; + } + else + { + return stream->L; + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: bitstream* bwc_init_stream(uchar* memory, uint32 size, char instr) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is used to initialize a bwc bitstream. For encoding, a null pointer ! +! is passed as a memory handle and the function will allocate a memory block with the ! +! specified stream size. For decoding, a valid memory handle, passed by the function ! +! caller, will be stored in the bitstream structure. The byte buffer counter t, ! +! stream size Lmax and size increment are initialized with their appropriate values. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! size unsigned int(32 bit) - Initial size of the bwc stream. ! +! ! +! memory unsigned char - Memory handle for the bwc stream memory ! +! block. ! +! ! +! instr char - Constant used to instruct the field ! +! initialization. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! bitstream* - Memory handle for the initialized bwc stream. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 19.06.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +bitstream* +init_stream(uchar* memory, uint32 size, char instr) +{ + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bitstream *stream; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(instr == 'c' || instr == 'd'); + + /*--------------------------------------------------------*\ + ! Allocate the bwc stream structure. ! + \*--------------------------------------------------------*/ + stream = calloc(1, sizeof(bitstream)); + if(!stream) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return NULL; + } + + /*--------------------------------------------------------*\ + ! Evaluate if a valid memory handle has been passed by the ! + ! function caller. ! + \*--------------------------------------------------------*/ + if(!memory) + { + /*--------------------------------------------------------*\ + ! If no valid memory handle has been passed, allocate a ! + ! memory block with the specifiec stream size. ! + \*--------------------------------------------------------*/ + stream->memory = calloc(size, sizeof(uchar)); + if(!stream->memory) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return NULL; + } + } + else + { + /*--------------------------------------------------------*\ + ! If a valid memory handle has been passed for decoding, ! + ! save the memory handle in the bwc stream structure. ! + \*--------------------------------------------------------*/ + stream->memory = memory; + } + + /*--------------------------------------------------------*\ + ! Initialize the byte buffer counter, stream size and size ! + ! increment for the current stream. ! + \*--------------------------------------------------------*/ + stream->t = (instr == 'c') ? 8 : 0; + stream->Lmax = size; + stream->size_incr = (uint64)(size / 2); + + /*--------------------------------------------------------*\ + ! Return the stream memory handle. ! + \*--------------------------------------------------------*/ + return stream; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void bwc_emit_chunck(bitstream *const stream, const uchar* string, const uint64 length) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is used to write an additional chunck of size length to a bwc bitstream. ! +! ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! stream bitstream* - Structure used to assemble a bwc bit- ! +! bitstream. ! +! ! +! chunck unsigned char* - Memory handle for a data block that is ! +! to be written to the bwc bitstream. ! +! ! +! size unsigned int(64 bit) - Size of the data block. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 22.06.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +emit_chunck(bitstream *const stream, const uchar* chunck, const uint64 size) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 Lreq; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(stream); + assert(chunck); + + /*--------------------------------------------------------*\ + ! Evaluate the memory block size if the current chunck of ! + ! data is written to the stream. ! + \*--------------------------------------------------------*/ + Lreq = (bytes_used(stream) + size); + + /*--------------------------------------------------------*\ + ! Check if the enough memory has been allocated for the ! + ! stream to store the additional data chunck. ! + \*--------------------------------------------------------*/ + if(Lreq > stream->Lmax) + { + /*--------------------------------------------------------*\ + ! If the stream is not large enough, check if this is due ! + ! to an error encountered in a previous writing operation ! + \*--------------------------------------------------------*/ + if(!stream->error) + { + /*--------------------------------------------------------*\ + ! If the error flag is not set, increase the stream size ! + ! until it is large enough to store the additional data ! + ! chunck. ! + \*--------------------------------------------------------*/ + while(Lreq > stream->Lmax) + { + stream->Lmax += stream->size_incr + size; + stream->size_incr = (uint64)(stream->Lmax / 2); + } + + /*--------------------------------------------------------*\ + ! Reallocate the stream data block. ! + \*--------------------------------------------------------*/ + stream->memory = realloc(stream->memory, stream->Lmax); + if(!stream->memory) + { + // memory allocation error + stream->error |= 1; + stream->Lmax = 0; + return; + } + } + else + { + /*--------------------------------------------------------*\ + ! Exit to function caller if error flag has been set. ! + \*--------------------------------------------------------*/ + return; + } + } + + /*--------------------------------------------------------*\ + ! Copy the additional data to the stream memory block. ! + \*--------------------------------------------------------*/ + memcpy(stream->memory + stream->L, chunck, size); + + /*--------------------------------------------------------*\ + ! Increment the number of bytes written to the stream with ! + ! the size of the newly added data chunck. ! + \*--------------------------------------------------------*/ + stream->L += size; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! stream bitstream* - Structure used to assemble a bwc bit- ! +! bitstream. ! +! ! +! symbol unsigned int(64 bit) - Symbol that is to be written to the bwc ! +! bitstream. ! +! ! +! size unsigned int(8 bit) - Number of significant bytes in the ! +! symbol. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 22.06.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +emit_symbol(bitstream *const stream, const uint64 symbol, const uint8 size) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint8 byte; + int8 i; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(stream); + + /*--------------------------------------------------------*\ + ! Check if the enough memory has been allocated for the ! + ! stream to store the additional symbol. ! + \*--------------------------------------------------------*/ + if((bytes_used(stream) + size) > stream->Lmax) + { + /*--------------------------------------------------------*\ + ! If the stream is not large enough, check if this is due ! + ! to an error encountered in a previous writing operation ! + \*--------------------------------------------------------*/ + if(!stream->error) + { + /*--------------------------------------------------------*\ + ! If the error flag is not set, increment the stream size ! + ! to store the additional symbol. ! + \*--------------------------------------------------------*/ + stream->Lmax += stream->size_incr; + stream->size_incr = (uint64)(stream->Lmax / 2); + + /*--------------------------------------------------------*\ + ! Reallocate the stream data block. ! + \*--------------------------------------------------------*/ + stream->memory = realloc(stream->memory, stream->Lmax); + if(!stream->memory) + { + // memory allocation error + stream->error |= 1; + stream->Lmax = 0; + return; + } + } + else + { + /*--------------------------------------------------------*\ + ! Exit to function caller if error flag has been set. ! + \*--------------------------------------------------------*/ + return; + } + } + + /*--------------------------------------------------------*\ + ! Copy the additional symbol to the stream memory block ! + ! one byte at a time and Increment the number of bytes ! + ! written to the stream. ! + \*--------------------------------------------------------*/ + for(i = size; i --> 0;) + { + byte = (uint8)((symbol >> (8 * i)) & 0xFF); + stream->memory[stream->L++] = (uchar)byte; + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void bwc_emit_bit(bitstream *const stream, const uint64 bit) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! stream bitstream* - Structure used to assemble a bwc bit- ! +! bitstream. ! +! ! +! bit unsigned int(64 bit) - Bit that is to be written to the bwc ! +! bitstream. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 22.06.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +emit_bit(bitstream *const stream, const uint64 bit) +{ + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(stream); + + /*--------------------------------------------------------*\ + ! Decrement the bit buffer counter. ! + \*--------------------------------------------------------*/ + stream->t--; + + /*--------------------------------------------------------*\ + ! If the bit is significant, store the information at the ! + ! appropriate position in the bit buffer. ! + \*--------------------------------------------------------*/ + if(bit) + { + stream->T |= (1 << stream->t); + } + + /*--------------------------------------------------------*\ + ! Check the bit buffer counter to see if the bit buffer is ! + ! full. ! + \*--------------------------------------------------------*/ + if(!stream->t) + { + /*--------------------------------------------------------*\ + ! Check if the enough memory has been allocated for the ! + ! stream to store the additional byte. ! + \*--------------------------------------------------------*/ + if(bytes_used(stream) + 1 > stream->Lmax) + { + /*--------------------------------------------------------*\ + ! If the stream is not large enough, check if this is due ! + ! to an error encountered in a previous writing operation ! + \*--------------------------------------------------------*/ + if(!stream->error) + { + /*--------------------------------------------------------*\ + ! If the error flag is not set, increment the stream size ! + ! to store the additional byte. ! + \*--------------------------------------------------------*/ + stream->Lmax += stream->size_incr; + stream->size_incr = (uint64)(stream->Lmax / 2); + + /*--------------------------------------------------------*\ + ! Reallocate the stream data block. ! + \*--------------------------------------------------------*/ + stream->memory = realloc(stream->memory, stream->Lmax); + if(!stream->memory) + { + // memory allocation error + stream->error |= 1; + stream->Lmax = 0; + return; + } + } + else + { + /*--------------------------------------------------------*\ + ! Exit to function caller if error flag has been set. ! + \*--------------------------------------------------------*/ + return; + } + } + + /*--------------------------------------------------------*\ + ! Copy the additional byte to the stream memory block and ! + ! increment the number of bytes written to the stream. ! + \*--------------------------------------------------------*/ + stream->memory[stream->L++] = (uchar)stream->T; + + /*--------------------------------------------------------*\ + ! Reset the byte buffer counter. If the current buffer has ! + ! a value of 255, limit the counter to 7 bits to ensure ! + ! that the range FFFF to FF80 is reserved for the code- ! + ! stream markers. ! + \*--------------------------------------------------------*/ + if(stream->T == 0xFF) + { + stream->t = 7; + } + else + { + stream->t = 8; + } + + /*--------------------------------------------------------*\ + ! Reset the byte buffer. ! + \*--------------------------------------------------------*/ + stream->T = 0; + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! stream bitstream* - Structure used to assemble a bwc bit- ! +! bitstream. ! +! ! +! size unsigned int(64 bit) - Size of the data block. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! uchar* - Data chunck requested by the function caller. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 22.06.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uchar* +get_chunck(bitstream *const stream, const uint64 size) +{ + /*-----------------------*\ + ! DEFINE CHAR VARIABLES: ! + \*-----------------------*/ + uchar *tmp; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(stream); + + /*--------------------------------------------------------*\ + ! Check if the number of bytes to be read from the stream ! + ! does not exceed the number of bytes still present in its ! + ! memory block. ! + \*--------------------------------------------------------*/ + if(bytes_used(stream) + size <= stream->Lmax) + { + /*--------------------------------------------------------*\ + ! Allocate a temporary array used to store the bytes that ! + ! are extracted from the stream. ! + \*--------------------------------------------------------*/ + tmp = calloc(size, sizeof(uchar)); + if(!tmp) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return NULL; + } + + /*--------------------------------------------------------*\ + ! Copy the bytes requested from the function caller from ! + ! the stream to the temporary data block. ! + \*--------------------------------------------------------*/ + memcpy(tmp, stream->memory + stream->L, size); + + /*--------------------------------------------------------*\ + ! Increment the number of bytes read from the bitstream. ! + \*--------------------------------------------------------*/ + stream->L += size; + + /*--------------------------------------------------------*\ + ! Return the temporary data block to the function caller. ! + \*--------------------------------------------------------*/ + return tmp; + } + else + { + /*--------------------------------------------------------*\ + ! If the requested block size exceeds the information left ! + ! in the bitstream, set the bitstream error flag and ! + ! return a NULL pointer. ! + \*--------------------------------------------------------*/ + stream->error |= 1; + return NULL; + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! stream bitstream* - Structure used to assemble a bwc bit- ! +! bitstream. ! +! ! +! size unsigned int(8 bit) - Number of significant bytes in the ! +! symbol. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! uchar* - Symbol requested by the function caller. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! - Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uint64 +get_symbol(bitstream *const stream, const uint8 size) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 symbol; + uint8 byte; + int8 i; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(stream); + + /*--------------------------------------------------------*\ + ! Check if the number of bytes to be read from the stream ! + ! does not exceed the number of bytes still present in its ! + ! memory block. ! + \*--------------------------------------------------------*/ + if(bytes_used(stream) + size <= stream->Lmax) + { + /*--------------------------------------------------------*\ + ! Extract the requested information from the bitstream one ! + ! byte at a time. Adjust the number of bytes read from the ! + ! stream accordingly. ! + \*--------------------------------------------------------*/ + for(i = size, symbol = 0; i --> 0;) + { + byte = (uint8)stream->memory[stream->L++]; + symbol |= ((uint64)byte << (i * 8)); + } + + /*--------------------------------------------------------*\ + ! Return the symbol to the function caller. ! + \*--------------------------------------------------------*/ + return symbol; + } + else + { + /*--------------------------------------------------------*\ + ! If the requested block size exceeds the information left ! + ! in the bitstream, set the bitstream error flag and ! + ! return zero. ! + \*--------------------------------------------------------*/ + stream->error |= 1; + return 0; + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! - Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uchar +get_bit(bitstream *const stream) +{ + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(stream); + + if(!stream->t) + { + if(stream->L == stream->Lmax) + { + return 1; + } + if(stream->T == 0xFF) + { + stream->t = 7; + } + else + { + stream->t = 8; + } + stream->T = (uint16)stream->memory[stream->L++]; + } + stream->t--; + return ((stream->T & (1 << stream->t)) >> stream->t); +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! - Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +flush_stream(bitstream *const stream) +{ + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(stream); + + /*--------------------------------------------------------*\ + ! Check the if the bit buffer contains information. ! + \*--------------------------------------------------------*/ + if(stream->t != 8) + { + /*--------------------------------------------------------*\ + ! Check if the enough memory has been allocated for the ! + ! stream to store the additional byte. ! + \*--------------------------------------------------------*/ + if((bytes_used(stream) + 1) > stream->Lmax) + { + /*--------------------------------------------------------*\ + ! If the stream is not large enough, check if this is due ! + ! to an error encountered in a previous writing operation ! + \*--------------------------------------------------------*/ + if(!stream->error) + { + /*--------------------------------------------------------*\ + ! If the error flag is not set, increment the stream size ! + ! to store the additional byte. ! + \*--------------------------------------------------------*/ + stream->Lmax += stream->size_incr; + stream->size_incr = (uint64)(stream->Lmax / 2); + + /*--------------------------------------------------------*\ + ! Reallocate the stream data block. ! + \*--------------------------------------------------------*/ + stream->memory = realloc(stream->memory, stream->Lmax); + if(!stream->memory) + { + // memory allocation error + stream->error |= 1; + stream->Lmax = 0; + return; + } + } + else + { + /*--------------------------------------------------------*\ + ! Exit to function caller if error flag has been set. ! + \*--------------------------------------------------------*/ + return; + } + } + + /*--------------------------------------------------------*\ + ! Copy the additional byte to the stream memory block and ! + ! increment the number of bytes written to the stream. ! + \*--------------------------------------------------------*/ + stream->memory[stream->L++] = (uchar)stream->T; + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! - Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uchar +terminate_stream(bitstream *stream, bwc_stream *const packed_stream) +{ + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(stream); + + if(packed_stream) + { + if(stream->error) + { + return 1; + } + else if(stream->L != stream->Lmax) + { + stream->Lmax = stream->L; + stream->memory = realloc(stream->memory, stream->Lmax); + if(!stream->memory) + { + // memory allocation error + fprintf(stderr, MEMERROR); + stream->Lmax = 0; + return 1; + } + } + + packed_stream->memory = stream->memory; + packed_stream->access = stream->memory; + packed_stream->size = stream->L; + packed_stream->position = 0; + } + else + { + free(stream->memory); + } + + free(stream); + return 0; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void release_packed_stream(bwc_stream *stream) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is used to release all the information stored in a packed bitstream ! +! and reset the parameters for another (de)compression run. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! stream bwc_stream - Packed bitstream used to store parts of ! +! the bwc codestream. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 22.06.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +release_packed_stream(bwc_stream *stream) +{ + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(stream); + + /*--------------------------------------------------------*\ + ! Free the data block of the packed bitstream. ! + \*--------------------------------------------------------*/ + free(stream->memory); + + /*--------------------------------------------------------*\ + ! Reset all the packed stream parameters. ! + \*--------------------------------------------------------*/ + stream->access = NULL; + stream->position = 0; + stream->size = 0; +} \ No newline at end of file diff --git a/1-bwc/src/library/codestream.c b/1-bwc/src/library/codestream.c new file mode 100755 index 0000000..ca96310 --- /dev/null +++ b/1-bwc/src/library/codestream.c @@ -0,0 +1,1786 @@ +/*================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| DESCRIPTION: || +|| ------------ || +|| || +|| This file describes a set of function that can be used to create and manipulate || +|| a BigWhoop Codestream. They facilitate the assembly and parsing of the main || +|| header and tile bitsreams as well as read and write functions used to access || +|| conforming bwc datasets. || +|| || +|| -------------------------------------------------------------------------------------------- || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are || +|| permitted provided that the following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of || +|| conditions and the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || +|| of conditions and the following disclaimer in the documentation and/or other || +|| materials provided with the distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS || +|| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF || +|| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE || +|| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, || +|| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF || +|| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) || +|| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || +|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, || +|| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*================================================================================================*/ +/************************************************************************************************************\ +|| _ _ _ ____ _ _ _ ___ ____ || +|| | |\ | | | | | | \ |___ || +|| | | \| |___ |___ |__| |__/ |___ || +|| || +\************************************************************************************************************/ +#include +#include +#include +#include + +#include "libbwc.h" +#include "bitstream.h" +#include "codestream.h" +#include "tier2.h" + +/************************************************************************************************************\ +|| ___ ____ _ _ _ ____ ___ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || +|| |__] |__/ | | | |__| | |___ |___ | | |\ | | | | | | |\ | [__ || +|| | | \ | \/ | | | |___ | |__| | \| |___ | | |__| | \| ___] || +|| || +\************************************************************************************************************/ +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! ! +! RETURN VALUE: ! +! ------------- ! +! - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! - Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static uchar +can_read(bitstream *const stream, const uint64 length) +{ + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(stream); + assert(length); + + return (stream->L + length > stream->Lmax) ? 0 : 1; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void codestream_write_header(bitstream *const stream, bwc_field *const field) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is writes the main header, including the end of header (EOH) marker seg- ! +! ment to the bwc codestream. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! stream bitstream* - Structure used to assemble a bwc bit- ! +! bitstream. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! uchar - Returns an unsigned char for error handling. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 12.07.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +codestream_write_header(bitstream *const stream, bwc_field *const field) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint32 t; + uint16 Leoh; + uint8 p; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_gl_inf *info; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(stream); + assert(field); + + /*--------------------------------------------------------*\ + ! Save the global as well as the subband control and info ! + ! structure to temporary variables to make the code more ! + ! readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + info = field->info; + + /*--------------------------------------------------------*\ + ! Calculate the size of the end of header (EOH) maker seg- ! + ! ment - excluding the EOH marker. ! + \*--------------------------------------------------------*/ + Leoh = 2 + (control->nTiles * info->nPar * 2 * PREC_BYTE); + + /*--------------------------------------------------------*\ + ! Emit the portion of the main header already created by ! + ! the bwc_create_compression function. ! + \*--------------------------------------------------------*/ + emit_chunck(stream, control->header.memory, control->header.size); + + /*--------------------------------------------------------*\ + ! Emit the end of header (EOH) marker and EOH marker seg- ! + ! ment size Leoh. ! + \*--------------------------------------------------------*/ + emit_symbol(stream, EOH, 2); + emit_symbol(stream, Leoh, 2); + + /*--------------------------------------------------------*\ + ! Loop through all tile parameters and... ! + \*--------------------------------------------------------*/ + for(t = 0; t < control->nTiles; ++t) + { + for(p = 0; p < info->nPar; ++p) + { + /*--------------------------------------------------------*\ + ! ...emit the maximum and minimum parameter value to the ! + ! header stream. ! + \*--------------------------------------------------------*/ + emit_symbol(stream, *(uint64 *)&field->tile[t].parameter[p].info.parameter_min, PREC_BYTE); + emit_symbol(stream, *(uint64 *)&field->tile[t].parameter[p].info.parameter_max, PREC_BYTE); + + /*--------------------------------------------------------*\ + ! Reset the maximum and minimum parameter value in the ! + ! parameter structure. ! + \*--------------------------------------------------------*/ + field->tile[t].parameter[p].info.parameter_max = -FLT_MAX; + field->tile[t].parameter[p].info.parameter_min = FLT_MAX; + } + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: uchar sequence_packets(bwc_field *const field, bwc_field *const field) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! tile bwc_tile* - Structure defining a bwc tile. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! uchar - Returns an unsigned char for error handling. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 13.06.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static uchar +sequence_packets(bwc_field *const field, bwc_tile *const tile) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 tile_size, idx; + uint32 j, p; + int32 r; + uint8 l; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_gl_inf *info; + bwc_resolution *resolution; + bwc_packet **packet_sequence; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(tile); + + /*--------------------------------------------------------*\ + ! Save the global control and info as well as the packet ! + ! sequence structure to temporary variables to make the ! + ! code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + info = field->info; + + packet_sequence = tile->packet_sequence; + + switch(control->progression) + { + case bwc_prog_LRCP: + { + for(l = 0, tile_size = 0, idx = 0; l < control->nLayers; ++l) + { + for(r = 0; r < control->nDecomp + 1; ++r) + { + for(j = 0; j < info->nPar; ++j) + { + resolution = &tile->parameter[j].resolution[r]; + + for(p = 0; p < resolution->control.number_of_precincts; ++p, ++idx) + { + packet_sequence[idx] = &resolution->packet[l * resolution->control.number_of_precincts + p]; + tile_size += resolution->packet[l * resolution->control.number_of_precincts + p].size; + + if(control->error_resilience) + { + tile_size += 6; + } + } + } + } + } + break; + } + case bwc_prog_RLCP: + { + for(r = 0, tile_size = 0, idx = 0; r < control->nDecomp + 1; ++r) + { + for(l = 0; l < control->nLayers; ++l) + { + for(j = 0; j < info->nPar; ++j) + { + resolution = &tile->parameter[j].resolution[r]; + + for(p = 0; p < resolution->control.number_of_precincts; ++p, ++idx) + { + packet_sequence[idx] = &resolution->packet[l * resolution->control.number_of_precincts + p]; + tile_size += resolution->packet[l * resolution->control.number_of_precincts + p].size; + + if(control->error_resilience) + { + tile_size += 6; + } + } + } + } + } + break; + } + case bwc_prog_RPCL: + { + for(l = 0, tile_size = 0, idx = 0; l < control->nLayers; ++l) + { + for(r = 0; r < control->nDecomp + 1; ++r) + { + for(j = 0; j < info->nPar; ++j) + { + resolution = &tile->parameter[j].resolution[r]; + + for(p = 0; p < resolution->control.number_of_precincts; ++p, ++idx) + { + packet_sequence[idx] = &resolution->packet[l * resolution->control.number_of_precincts + p]; + tile_size += resolution->packet[l * resolution->control.number_of_precincts + p].size; + + if(control->error_resilience) + { + tile_size += 6; + } + } + } + } + } + break; + } + case bwc_prog_PCRL: + { + for(l = 0, tile_size = 0, idx = 0; l < control->nLayers; ++l) + { + for(r = 0; r < control->nDecomp + 1; ++r) + { + for(j = 0; j < info->nPar; ++j) + { + resolution = &tile->parameter[j].resolution[r]; + + for(p = 0; p < resolution->control.number_of_precincts; ++p, ++idx) + { + packet_sequence[idx] = &resolution->packet[l * resolution->control.number_of_precincts + p]; + tile_size += resolution->packet[l * resolution->control.number_of_precincts + p].size; + + if(control->error_resilience) + { + tile_size += 6; + } + } + } + } + } + break; + } + case bwc_prog_CPRL: + { + for(l = 0, tile_size = 0, idx = 0; l < control->nLayers; ++l) + { + for(r = 0; r < control->nDecomp + 1; ++r) + { + for(j = 0; j < info->nPar; ++j) + { + resolution = &tile->parameter[j].resolution[r]; + + for(p = 0; p < resolution->control.number_of_precincts; ++p, ++idx) + { + packet_sequence[idx] = &resolution->packet[l * resolution->control.number_of_precincts + p]; + tile_size += resolution->packet[l * resolution->control.number_of_precincts + p].size; + + if(control->error_resilience) + { + tile_size += 6; + } + } + } + } + } + break; + } + default: + { + return 1; + } + } + + tile->control.body_size = tile_size; + return 0; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: uchar sequence_packets(bwc_field *const field, bwc_field *const field) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! tile bwc_tile* - Structure defining a bwc tile. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! uchar - Returns an unsigned char for error handling. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 13.06.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +assemble_tile(bwc_field *const field, bwc_tile *const tile, bitstream *const stream) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 packet_index; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_packet *packet; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert(tile); + assert(stream); + + /*--------------------------------------------------------*\ + ! Save the global control and info as well as the packet ! + ! sequence structure to temporary variables to make the ! + ! code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + + emit_symbol(stream, SOT, 2); + emit_symbol(stream, 14, 2); + emit_symbol(stream, tile->info.tile_index, 4); + emit_symbol(stream, tile->control.body_size, 8); + emit_symbol(stream, SOD, 2); + + for(packet_index = 0; packet_index < tile->control.nPackets; ++packet_index) + { + packet = tile->packet_sequence[packet_index]; + + if(control->error_resilience) + { + emit_symbol(stream, SOP, 2); + emit_symbol(stream, 4, 2); + emit_symbol(stream, packet_index % 0x100000000, 4); + } + + if(packet->header.memory) + { + emit_chunck(stream, packet->header.memory, packet->header.size); + + if(control->error_resilience) + { + emit_symbol(stream, EPH, 2); + } + + release_packed_stream(&packet->header); + } + + if(packet->body.memory) + { + emit_chunck(stream, packet->body.memory, packet->body.size); + + release_packed_stream(&packet->body); + } + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! - Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +bwc_field* +parse_main_header(bwc_data *const data,bitstream *const stream) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 buff_long, buffX, buffY, buffZ, buffTS; + uint64 nX, nY, nZ; + uint32 buff; + uint32 bitrate; + uint32 Lsax; + uint32 mantissa, exponent; + uint32 t; + uint16 CSsgc; + uint16 Linf, Lctr, Lcom, Leoh, Lunk; + uint16 marker; + uint16 nTS; + uint8 dim; + uint8 index, l; + uint8 samp; + uint8 nPar, p; + uint8 codec_prec, precision; + + /*-----------------------*\ + ! DEFINE CHAR VARIABLES: ! + \*-----------------------*/ + char* buffer_char; + char status; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_field *field; + bwc_gl_ctrl *control; + bwc_gl_inf *info; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(data); + assert(stream); + + /*--------------------------------------------------------*\ + ! Save the data info structure to a temporary variable to ! + ! make the code more readable. ! + \*--------------------------------------------------------*/ + info = &data->info; + + status = CODESTREAM_OK; + index = 0; + + while(!(status & CODESTREAM_ERROR) && can_read(stream, 2)) + { + marker = (uint16)get_symbol(stream, 2); + if(marker < 0xFF00) + { + // Invalid Codestream + fprintf(stderr, CSERROR); + status |= CODESTREAM_ERROR; + } + + switch(marker) + { + case SOC: + { + if(index != 0) + { + // Invalid Codestream + fprintf(stderr, CSERROR); + status |= CODESTREAM_ERROR; + } + break; + } + + case SGI: + { + if(index != 1 && !can_read(stream, 2)) + { + // Invalid Codestream + fprintf(stderr, CSERROR); + status |= CODESTREAM_ERROR; + break; + } + + Linf = (uint16)get_symbol(stream, 2); + if(!can_read(stream, Linf - 2)) + { + // Invalid Codestream + fprintf(stderr, CSERROR); + status |= CODESTREAM_ERROR; + break; + } + + info->nX = nX = get_symbol(stream, 8); + info->nY = nY = get_symbol(stream, 8); + info->nZ = nZ = get_symbol(stream, 8); + info->nTS = nTS = (uint16)get_symbol(stream, 2); + info->nPar = nPar = (uint8)get_symbol(stream, 1); + info->precision = codec_prec = (uint8)get_symbol(stream, 1); + + buffer_char = (char*)get_chunck(stream, 10); + strncpy(info->f_ext, buffer_char, sizeof(buffer_char)/sizeof(*buffer_char)); + free(buffer_char); + + for(p = 0; p < nPar; ++p) + { + buffer_char = (char*)get_chunck(stream, 24); + precision = (uint8)get_symbol(stream, 1); + + bwc_add_param(data, buffer_char, precision); + + free(buffer_char); + } + + field = bwc_initialize_field(data); + if(!field) + { + status |= CODESTREAM_ERROR; + break; + } + + /*--------------------------------------------------------*\ + ! Save the global control and info structure to temporary ! + ! variables to make the code more readable. ! + \*--------------------------------------------------------*/ + info = field->info = &data->info; + control = &field->control; + + status |= CODESTREAM_SGI_READ; + break; + } + + case SGC: + { + if(index != 2 && !can_read(stream, 2)) + { + // Invalid Codestream + fprintf(stderr, CSERROR); + bwc_kill_compression(field); + status |= CODESTREAM_ERROR; + break; + } + + Lctr = (uint16)get_symbol(stream, 2); + + if(!can_read(stream, Lctr - 2)) + { + // Invalid Codestream + fprintf(stderr, CSERROR); + bwc_kill_compression(field); + status |= CODESTREAM_ERROR; + break; + } + + CSsgc = (uint16)get_symbol(stream, 2); + + + buff_long = get_symbol(stream, 1); + if(CSsgc & (0x01 << 0)) + { + bwc_set_error_resilience(field); + } + + buff_long = get_symbol(stream, 1); + + if(CSsgc & (0x01 << 1)) + { + bwc_set_quant_style(field, (bwc_quant_st)buff_long); + } + + buff_long = get_symbol(stream, 1); + + exponent = (uint32)get_symbol(stream, 1); + mantissa = (uint32)get_symbol(stream, 2); + if(CSsgc & (0x01 << 2)) + { + control->qt_exponent = exponent; + control->qt_mantissa = mantissa; + } + + buff_long = get_symbol(stream, 1); + if(CSsgc & (0x01 << 3)) + { + bwc_set_progression(field, (uint8)buff_long); + } + + buff_long = get_symbol(stream, 1); + if(CSsgc & (0x01 << 4)) + { + bwc_set_kernels(field, (uint8)(0x03 & (buff_long >> 6)), (uint8)(0x03 & (buff_long >> 4)), + (uint8)(0x03 & (buff_long >> 2)), (uint8)(0x03 & buff_long)); + } + + buff_long = get_symbol(stream, 4); + if(CSsgc & (0x01 << 5)) + { + bwc_set_decomp(field, (uint8)(0xFF & (buff_long >> 24)), (uint8)(0xFF & (buff_long >> 16)), + (uint8)(0xFF & (buff_long >> 8)), (uint8)(0xFF & buff_long)); + } + + buff_long = get_symbol(stream, 2); + if(CSsgc & (0x01 << 6)) + { + bwc_set_precincts(field, (uint8)(0x0F & (buff_long >> 8)), (uint8)(0x0F & (buff_long >> 12)), + (uint8)(0x0F & buff_long), (uint8)(0x0F & (buff_long >> 4))); + } + + buff_long = get_symbol(stream, 4); + if(CSsgc & (0x01 << 7)) + { + bwc_set_codeblocks(field, (uint8)(0xFF & (buff_long >> 24)), (uint8)(0xFF & (buff_long >> 16)), + (uint8)(0xFF & (buff_long >> 8)), (uint8)(0xFF & buff_long)); + } + + buff_long = get_symbol(stream, 1); + if(CSsgc & (0x01 << 8)) + { + bwc_set_qm(field, (uint8)buff_long); + } + + buffX = get_symbol(stream, 8); + buffY = get_symbol(stream, 8); + buffZ = get_symbol(stream, 8); + buffTS = get_symbol(stream, 2); + if(CSsgc & (0x01 << 9)) + { + bwc_set_tiles(field, buffX, buffY, buffZ, (uint16)buffTS, bwc_tile_sizeof); + } + + control->nLayers = get_symbol(stream, 1); + control->bitrate = calloc(control->nLayers, sizeof(float)); + if(!control->bitrate) + { + // memory allocation error + fprintf(stderr, MEMERROR); + bwc_kill_compression(field); + status|= CODESTREAM_ERROR; + break; + } + + for(l = 0; l < control->nLayers; ++l) + { + bitrate = (uint32)get_symbol(stream, 4); + control->bitrate[l] = *(float *)&bitrate; + } + + create_field(field); + if(!field) + { + bwc_kill_compression(field); + status |= CODESTREAM_ERROR; + break; + } + + status |= CODESTREAM_SGC_READ; + break; + } + + case SAX: + { + if(index <= 2 && !can_read(stream, 4)) + { + // Invalid Codestream + fprintf(stderr, CSERROR); + bwc_kill_compression(field); + status |= CODESTREAM_ERROR; + break; + } + + Lsax = (uint32)get_symbol(stream, 4); + if(!can_read(stream, Lsax - 4)) + { + // Invalid Codestream + fprintf(stderr, CSERROR); + bwc_kill_compression(field); + status |= CODESTREAM_ERROR; + break; + } + + data->codestream.aux = calloc(1, sizeof(bwc_stream)); + if(!data->codestream.aux) + { + // memory allocation error + fprintf(stderr, MEMERROR); + bwc_kill_compression(field); + status |= CODESTREAM_ERROR; + break; + } + + data->codestream.aux->memory = get_chunck(stream, Lsax - 4); + data->codestream.aux->size = Lsax - 4; + + status |= CODESTREAM_SAX_READ; + break; + } + + case COM: + { + if(index <= 2 && !can_read(stream, 2)) + { + // Invalid Codestream + fprintf(stderr, CSERROR); + bwc_kill_compression(field); + status |= CODESTREAM_ERROR; + break; + } + + Lcom = (uint16)get_symbol(stream, 2); + if(!can_read(stream, Lcom - 2)) + { + // Invalid Codestream + fprintf(stderr, CSERROR); + bwc_kill_compression(field); + status |= CODESTREAM_ERROR; + break; + } + + data->codestream.com = calloc(1, sizeof(bwc_stream)); + if(!data->codestream.com) + { + // memory allocation error + fprintf(stderr, MEMERROR); + bwc_kill_compression(field); + status |= CODESTREAM_ERROR; + break; + } + + data->codestream.com->memory = get_chunck(stream, Lcom - 2); + data->codestream.com->size = Lcom -2; + + status |= CODESTREAM_ERROR; + break; + } + + case EOH: + { + if((status & CODESTREAM_SGI_READ) && (status & CODESTREAM_SGC_READ)) + { + if(index <= 2 && !can_read(stream, 2)) + { + // Invalid Codestream + fprintf(stderr, CSERROR); + bwc_kill_compression(field); + status |= CODESTREAM_ERROR; + break; + } + + Leoh = (uint16)get_symbol(stream, 2); + if(!can_read(stream, Leoh - 2)) + { + // Invalid Codestream + fprintf(stderr, CSERROR); + bwc_kill_compression(field); + status |= CODESTREAM_ERROR; + break; + } + + if(codec_prec == 8) + { + /*--------------------------------------------------------*\ + ! Loop through all tile parameters and... ! + \*--------------------------------------------------------*/ + for(t = 0; t < control->nTiles; ++t) + { + for(p = 0; p < info->nPar; ++p) + { + /*--------------------------------------------------------*\ + ! ...get the maximum and minimum parameter value to the ! + ! header stream. ! + \*--------------------------------------------------------*/ + buff_long = get_symbol(stream, sizeof(double)); + field->tile[t].parameter[p].info.parameter_min = (bwc_float)*(double*)&buff_long; + + buff_long = get_symbol(stream, sizeof(double)); + field->tile[t].parameter[p].info.parameter_max = (bwc_float)*(double*)&buff_long; + } + } + } + else if(codec_prec == 4) + { + /*--------------------------------------------------------*\ + ! Loop through all tile parameters and... ! + \*--------------------------------------------------------*/ + for(t = 0; t < control->nTiles; ++t) + { + for(p = 0; p < info->nPar; ++p) + { + /*--------------------------------------------------------*\ + ! ...get the maximum and minimum parameter value to the ! + ! header stream. ! + \*--------------------------------------------------------*/ + buff = get_symbol(stream, sizeof(float)); + field->tile[t].parameter[p].info.parameter_min = (bwc_float)*(float*)&buff; + + buff = get_symbol(stream, sizeof(float)); + field->tile[t].parameter[p].info.parameter_max = (bwc_float)*(float*)&buff; + } + } + } + return field; + } + else + { + // Invalid Codestream + fprintf(stderr, CSERROR); + bwc_kill_compression(field); + status |= CODESTREAM_ERROR; + } + break; + } + + default: + { + if(!can_read(stream, 2)) + { + // Invalid Codestream + fprintf(stderr, CSERROR); + bwc_kill_compression(field); + status |= CODESTREAM_ERROR; + break; + } + + Lunk = (uint16)get_symbol(stream, 2); + if(!can_read(stream, Lcom - 2)) + { + // Invalid Codestream + fprintf(stderr, CSERROR); + bwc_kill_compression(field); + status |= CODESTREAM_ERROR; + break; + } + + stream->L += Lunk - 2; + break; + } + } + index++; + } + return NULL; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: uchar sequence_packets(bwc_field *const field, bwc_field *const field) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! tile bwc_tile* - Structure defining a bwc tile. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! uchar - Returns an unsigned char for error handling. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 13.06.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static uchar +parse_tile(bwc_field *const field, bitstream *const stream) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 body_size; + uint64 packet_index; + uint64 buf; + uint32 L; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_packet *packet; + bwc_tile *tile; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert(stream); + + /*--------------------------------------------------------*\ + ! Save the global control and info as well as the packet ! + ! sequence structure to temporary variables to make the ! + ! code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + + if(!can_read(stream, 2)) + { + // Invalid Codestream + fprintf(stderr, CSERROR); + return 1; + } + + L = (uint16)get_symbol(stream, 2); + + if(!can_read(stream, L - 2)) + { + // Invalid Codestream + fprintf(stderr, CSERROR); + return 1; + } + + buf = (uint32)get_symbol(stream, 4); + if(buf >= control->nTiles) + { + // Invalid Codestream + fprintf(stderr, CSERROR); + return 1; + } + + tile = &field->tile[buf]; + tile->control.body_size = + body_size = (uint64)get_symbol(stream, 8); + + if(SOD != (uint16)get_symbol(stream, 2)) + { + // Invalid Codestream + fprintf(stderr, CSERROR); + return 1; + } + else + { + /*--------------------------------------------------------*\ + ! Sequence the packets according to the user specified op- ! + ! tion. ! + \*--------------------------------------------------------*/ + if(sequence_packets(field, tile)) + { + return 1; + } + + packet_index = 0; + + while((body_size != 0) && can_read(stream, body_size) && packet_index < tile->control.nPackets) + { + if(SOP == (uint16)get_symbol(stream, 2)) + { + if(!can_read(stream, 6)) + { + //Invalid Codestream + fprintf(stderr, CSERROR); + return 1; + } + + if(4 != (uint16)get_symbol(stream, 2)) + { + //Invalid Codestream + fprintf(stderr, CSERROR); + return 1; + } + + buf = (uint32)get_symbol(stream, 4); + + body_size -= 8; + } + else + { + rewind_stream(stream, 2); + } + + packet = tile->packet_sequence[packet_index++]; + + packet->header.memory = get_access(stream); + + if(parse_packet(field, tile, packet, body_size)) + { + return 1; + } + + forward_stream(stream, packet->size); + + body_size -= packet->size; + } + } + return 0; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! - Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static uchar +parse_body(bwc_field *const field, bitstream *const stream) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint16 Lunk; + uint16 marker; + + /*-----------------------*\ + ! DEFINE CHAR VARIABLES: ! + \*-----------------------*/ + char status; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + + status = CODESTREAM_OK; + + while(!(status & CODESTREAM_ERROR) && can_read(stream, 2)) + { + marker = (uint16)get_symbol(stream, 2); + if(marker < 0xFF00) + { + // Invalid Codestream + fprintf(stderr, CSERROR); + status |= CODESTREAM_ERROR; + } + + switch(marker) + { + case SOT: + { + if(parse_tile(field, stream)) + { + status |= CODESTREAM_ERROR; + } + break; + } + + case EOC: + { + return 0; + break; + } + + case SOC: + case SGI: + case SGC: + case SAX: + case COM: + case EOH: + { + // Invalid Codestream + fprintf(stderr, CSERROR); + status |= CODESTREAM_ERROR; + + break; + } + + default: + { + if(!can_read(stream, 2)) + { + // Invalid Codestream + fprintf(stderr, CSERROR); + bwc_kill_compression(field); + status |= CODESTREAM_ERROR; + break; + } + + Lunk = (uint16)get_symbol(stream, 2); + if(!can_read(stream, Lunk - 2)) + { + // Invalid Codestream + fprintf(stderr, CSERROR); + bwc_kill_compression(field); + status |= CODESTREAM_ERROR; + break; + } + + stream->L += Lunk - 2; + break; + } + } + } + return 0; +} +/************************************************************************************************************\ +|| ___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || +|| |__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ || +|| | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] || +|| || +\************************************************************************************************************/ +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! - Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uchar +assemble_main_header(bwc_field *const field) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 size; + uint16 Linf, Lctr; + uint8 p, l; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_gl_inf *info; + bwc_tile *tile; + bwc_parameter *parameter; + bitstream *stream; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + + /*--------------------------------------------------------*\ + ! Save the global as well as the subband control and info ! + ! structure to temporary variables to make the code more ! + ! readable. ! + \*--------------------------------------------------------*/ + info = field->info; + control = &field->control; + + tile = &field->tile[0]; + + parameter = &tile->parameter[0]; + + Linf = 40 + info->nPar * 25; + Lctr = 50 + control->nLayers * 4; + + size = 6 + Linf + Lctr; + + stream = init_stream(NULL, size, 'c'); + if(!stream) + { + // memory allocation error + return 1; + } + + emit_symbol(stream, SOC, 2); + emit_symbol(stream, SGI, 2); + emit_symbol(stream, Linf, 2); + emit_symbol(stream, info->nX, 8); + emit_symbol(stream, info->nY, 8); + emit_symbol(stream, info->nZ, 8); + emit_symbol(stream, info->nTS, 2); + emit_symbol(stream, info->nPar, 1); + emit_symbol(stream, info->precision, 1); + emit_chunck(stream, (uchar*)info->f_ext, 10); + + for(p = 0; p < info->nPar; ++p) + { + emit_chunck(stream, (uchar*)parameter[p].info.name, 24); + emit_symbol(stream, parameter[p].info.precision, 1); + } + + emit_symbol(stream, SGC, 2); + emit_symbol(stream, Lctr, 2); + + emit_symbol(stream, control->CSsgc, 2); + + emit_symbol(stream, control->error_resilience, 1); + + emit_symbol(stream, control->quantization_style, 1); + emit_symbol(stream, control->guard_bits, 1); + + emit_symbol(stream, control->qt_exponent, 1); + emit_symbol(stream, control->qt_mantissa, 2); + + emit_symbol(stream, control->progression, 1); + emit_symbol(stream, control->KernelX << 6 | control->KernelY << 4 | + control->KernelZ << 2 | control->KernelTS, 1); + + emit_symbol(stream, control->decompX, 1); + emit_symbol(stream, control->decompY, 1); + emit_symbol(stream, control->decompZ, 1); + emit_symbol(stream, control->decompTS, 1); + + emit_symbol(stream, control->precSizeY << 4 | control->precSizeX, 1); + emit_symbol(stream, control->precSizeTS << 4 | control->precSizeZ, 1); + + emit_symbol(stream, control->cbX, 1); + emit_symbol(stream, control->cbY, 1); + emit_symbol(stream, control->cbZ, 1); + emit_symbol(stream, control->cbTS, 1); + + emit_symbol(stream, control->Qm, 1); + + emit_symbol(stream, control->tileSizeX, 8); + emit_symbol(stream, control->tileSizeY, 8); + emit_symbol(stream, control->tileSizeZ, 8); + emit_symbol(stream, control->tileSizeTS, 2); + + emit_symbol(stream, control->nLayers, 1); + + for(l = 0; l < control->nLayers; ++l) + { + emit_symbol(stream, *(uint32 *)&control->bitrate[l], 4); + } + + if(terminate_stream(stream, &control->header)) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + return 0; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! - Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uchar +codestream_write_aux(bwc_stream *const header, bwc_stream *const aux) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint32 Laux; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bitstream *stream; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(header); + assert(aux); + + stream = init_stream(header->memory, header->size, 'c'); + if(!stream) + { + // memory allocation error + return 1; + } + + Laux = aux->size + 4; + + stream->L = stream->Lmax; + stream->Lmax += Laux + 2; + stream->memory = realloc(stream->memory, stream->Lmax); + if(!stream->memory) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + emit_symbol(stream, SAX, 2); + emit_symbol(stream, Laux, 4); + emit_chunck(stream, aux->memory, aux->size); + + if(terminate_stream(stream, header)) + { + // memory allocation error + return 1; + } + + return 0; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! - Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uchar +codestream_write_com(bwc_stream *const header, bwc_stream *const com) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint16 Lcom; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bitstream *stream; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(header); + assert(com); + + stream = init_stream(header->memory, header->size, 'c'); + if(!stream) + { + // memory allocation error + return 1; + } + + Lcom = com->size + 2; + + stream->L = stream->Lmax; + stream->Lmax += Lcom + 2; + stream->memory = realloc(stream->memory, stream->Lmax); + if(!stream->memory) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + emit_symbol(stream, COM, 2); + emit_symbol(stream, Lcom, 2); + emit_chunck(stream, com->memory, com->size); + + if(terminate_stream(stream, header)) + { + // memory allocation error + return 1; + } + + return 0; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: bwc_stream* assemble_codestream(bwc_field *const field) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! bwc_stream* - Packed stream containing the compressed data set. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 13.06.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +bwc_stream* +assemble_codestream(bwc_field *const field) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 i, size; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_tile *tile; + bitstream *stream; + bwc_stream *packed_stream; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + + /*--------------------------------------------------------*\ + ! Save the global control and info structure to temporary ! + ! variables to make the code more readable and initialize ! + ! the final codestream size with the number of header ! + ! bytes. ! + \*--------------------------------------------------------*/ + control = &field->control; + size = control->header.size; + + /*--------------------------------------------------------*\ + ! Walk through the tile structure and assemble the packed ! + ! data stream. ! + \*--------------------------------------------------------*/ + for(i = 0; i < control->nTiles; ++i) + { + /*--------------------------------------------------------*\ + ! Save the tile structure in a temporary variable to make ! + ! the code more readable. ! + \*--------------------------------------------------------*/ + tile = &field->tile[i]; + + /*--------------------------------------------------------*\ + ! Sequence the packets according to the user specified op- ! + ! tion and iterate the size of the codestream. ! + \*--------------------------------------------------------*/ + if(sequence_packets(field, tile)) + { + return NULL; + } + + size += tile->control.header_size + tile->control.body_size; + } + + /*--------------------------------------------------------*\ + ! Initialize the final codestream and emit the header ! + ! bytes. ! + \*--------------------------------------------------------*/ + stream = init_stream(NULL, size, 'c'); + codestream_write_header(stream, field); + + /*--------------------------------------------------------*\ + ! Walk through the tile structure and assemble the packed ! + ! data stream. ! + \*--------------------------------------------------------*/ + for(i = 0; i < control->nTiles; ++i) + { + /*--------------------------------------------------------*\ + ! Save the tile structure in a temporary variable to make ! + ! the code more readable. ! + \*--------------------------------------------------------*/ + tile = &field->tile[i]; + + assemble_tile(field, tile, stream); + } + + emit_symbol(stream, EOC, 2); + + packed_stream = calloc(1, sizeof(bwc_stream)); + if(!packed_stream) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return NULL; + } + + if(terminate_stream(stream, packed_stream)) + { + return NULL; + } + else + { + return packed_stream; + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: uchar parse_codestream(bwc_field *const field, bitstream *const stream) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! stream bitstream* - Structure used to assemble a bwc bit- ! +! bitstream. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! uchar - Returns an unsigned char for error handling. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 05.08.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +bwc_field* +parse_codestream(bwc_data *const data, uint8 const layer) +{ + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_field *field; + bitstream *stream; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(data); + + /*--------------------------------------------------------*\ + ! Initialize a bitstream used to parse the packed code- ! + ! stream. ! + \*--------------------------------------------------------*/ + stream = init_stream(data->codestream.data->memory, + data->codestream.data->size, 'd'); + + /*--------------------------------------------------------*\ + ! Parse the main header and set up the field structure for ! + ! the current decompression run. ! + \*--------------------------------------------------------*/ + field = parse_main_header(data, stream); + if(!field) + { + return NULL; + } + + /*--------------------------------------------------------*\ + ! Initialize the useLayer option to decompress the entire ! + ! codestream. ! + \*--------------------------------------------------------*/ + field->control.useLayer = field->control.nLayers - 1; + + /*--------------------------------------------------------*\ + ! Check if the layer index supplied by the function caller ! + ! is valid. ! + \*--------------------------------------------------------*/ + if(layer < field->control.nLayers && layer > 0) + { + /*--------------------------------------------------------*\ + ! Amend the use layer variable in the global control struc-! + ! ture. ! + \*--------------------------------------------------------*/ + field->control.useLayer = layer; + } + + /*--------------------------------------------------------*\ + ! Parse the rest of the compressed codestream and load the ! + ! body into the field structure. ! + \*--------------------------------------------------------*/ + if(parse_body(field, stream)) + { + bwc_kill_compression(field); + return NULL; + } + + /*--------------------------------------------------------*\ + ! Free the bitstream used to parse the codestream and re- ! + ! turn the field structure to the function caller. ! + \*--------------------------------------------------------*/ + free(stream); + + return field; +} \ No newline at end of file diff --git a/1-bwc/src/library/dwt.c b/1-bwc/src/library/dwt.c new file mode 100755 index 0000000..5b94bc6 --- /dev/null +++ b/1-bwc/src/library/dwt.c @@ -0,0 +1,2648 @@ +/*================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| DESCRIPTION: || +|| ------------ || +|| || +|| This file describes a set of functions that can be used to performe the forward/ || +|| inverse discrete wavelet transform on 1- to 4-dimensional IEEE 754 data-sets. || +|| For more information please refere to JPEG2000 by D. S. Taubman and M. W. || +|| Marcellin. || +|| || +|| -------------------------------------------------------------------------------------------- || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are || +|| permitted provided that the following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of || +|| conditions and the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || +|| of conditions and the following disclaimer in the documentation and/or other || +|| materials provided with the distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS || +|| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF || +|| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE || +|| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, || +|| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF || +|| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) || +|| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || +|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, || +|| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*================================================================================================*/ + +/************************************************************************************************************\ +|| _ _ _ ____ _ _ _ ___ ____ || +|| | |\ | | | | | | \ |___ || +|| | | \| |___ |___ |__| |__/ |___ || +|| || +\************************************************************************************************************/ +#include +#include +#include +#include +#include + +#include "constants.h" +#include "macros.h" +#include "types.h" +#include "dwt.h" + +/************************************************************************************************************\ +|| ____ _ _ ___ ____ ____ _ _ ____ _ _ _ ____ ____ _ ____ ___ _ ____ ____ || +|| |___ \/ | |___ |__/ |\ | |__| | | | |__| |__/ | |__| |__] | |___ [__ || +|| |___ _/\_ | |___ | \ | \| | | |___ \/ | | | \ | | | |__] |___ |___ ___] || +|| || +\************************************************************************************************************/ +double DWT_ENERGY_GAIN_LUT[3][2 * MAX_DECOMP_LEVELS + 2]; + +/************************************************************************************************************\ +|| ___ ____ _ _ _ ____ ___ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || +|| |__] |__/ | | | |__| | |___ |___ | | |\ | | | | | | |\ | [__ || +|| | | \ | \/ | | | |___ | |__| | \| |___ | | |__| | \| ___] || +|| || +\************************************************************************************************************/ +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: uint8 get_max_taps(bwc_gl_ctrl *const control) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function returns the rounded up maximum half length of the specified wavelet filter. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! dwt_filter bwc_dwt_filter - Specifies the wavelet kernels used for ! +! spatial decomposition. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! uint8 - Specifies the rounded up maximum half-length of a wavelet fil- ! +! ter. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 22.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static uint8 +get_filter_taps(bwc_dwt_filter dwt_filter) +{ + /*--------------------------------------------------------*\ + ! Emit the rounded up maximum half-length of the specified ! + ! wavelet filter. ! + \*--------------------------------------------------------*/ + switch(dwt_filter) + { + case bwc_dwt_9_7: + { + return 4; + } + case bwc_dwt_5_3: + { + return 2; + } + case bwc_dwt_haar: + { + return 1; + } + default: + { + assert(0); + return 0; + } + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void fill_forward_buffer(bwc_sample *const data, bwc_sample *const working_buffer, ! +! ------------ uint64 res0, ! +! uint64 res1, ! +! uint64 increment) ! +! ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is used to fill the working buffer with the appropriate flow field data for ! +! the forward one dimensional wavelet transform. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! data bwc_sample* - Pointer to the flow field data of the ! +! current tile parameter. ! +! ! +! working_buffer bwc_sample* - Working buffer used to store flow field ! +! data for the one dimensional dwt. ! +! ! +! res0 unsigned int(64 bit) - Starting point for the current resolu- ! +! tion and dimension. ! +! ! +! res1 unsigned int(64 bit) - End point for the current resolution ! +! and dimension. ! +! ! +! increment unsigned int(64 bit) - Data increment for strided memory ac- ! +! cess. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 24.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +fill_forward_buffer(bwc_sample *const data, bwc_sample *const working_buffer, uint64 res0, uint64 res1, uint64 increment) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 i, j; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(data); + assert(working_buffer); + + /*--------------------------------------------------------*\ + ! Copy the strided memory for the current resolution and ! + ! dimension from the tile parameter buffer to the working ! + ! buffer for the one dimensional wavelet transform. ! + \*--------------------------------------------------------*/ + for(i = 0, j = 0; i < res1 - res0; ++i) + { + working_buffer[i] = data[j]; + j += increment; + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void fill_inverse_buffer(bwc_sample *const data, bwc_sample *const working_buffer, ! +! ------------ uint64 res0, ! +! uint64 res1, ! +! uint64 increment) ! +! ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is used to fill the working buffer with the appropriate flow field data for ! +! the inverse one dimensional wavelet transform. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! data bwc_sample* - Pointer to the flow field data of the ! +! current tile parameter. ! +! ! +! working_buffer bwc_sample* - Working buffer used to store flow field ! +! data for the one dimensional dwt. ! +! ! +! res0 unsigned int(64 bit) - Starting point for the current resolu- ! +! tion and dimension. ! +! ! +! res1 unsigned int(64 bit) - End point for the current resolution ! +! and dimension. ! +! ! +! increment unsigned int(64 bit) - Data increment for strided memory ac- ! +! cess. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 24.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +fill_inverse_buffer(bwc_sample *const data, bwc_sample *const working_buffer, uint64 res0, uint64 res1, uint64 increment) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + int64 i, length, half_length; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_sample *lowband, *highband; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(data); + assert(working_buffer); + + /*--------------------------------------------------------*\ + ! Calculate the length and half_length of the buffer. ! + \*--------------------------------------------------------*/ + length = res1 - res0; + half_length = (res0 % 2) ? length >> 1 : (length + 1) >> 1; + + /*--------------------------------------------------------*\ + ! Associate the data pointers to the starting point of the ! + ! low- and highband. ! + \*--------------------------------------------------------*/ + lowband = data; + highband = data + half_length * increment; + + /*--------------------------------------------------------*\ + ! Check if the starting point is odd. ! + \*--------------------------------------------------------*/ + if((res0 % 2) == 0) + { + /*--------------------------------------------------------*\ + ! Loop over the lowband wavelet coefficients in the tile ! + ! parameter memory and interleave them into the working ! + ! buffer. ! + \*--------------------------------------------------------*/ + for(i = 0; i < half_length; ++i) + { + working_buffer[i << 1].f = lowband->f; + lowband += increment; + } + + /*--------------------------------------------------------*\ + ! Decrease the half length in case of an odd resolution ! + ! length to account for the half-length - 1 number of ! + ! highband wavelet coefficients. ! + \*--------------------------------------------------------*/ + if(length % 2) --half_length; + + /*--------------------------------------------------------*\ + ! Loop over the highband wavelet coefficients in the tile ! + ! parameter memory and interleave them into the working ! + ! buffer. ! + \*--------------------------------------------------------*/ + for(i = 0; i < half_length; ++i) + { + working_buffer[(i << 1) + 1].f = highband->f; + highband += increment; + } + } + else + { + /*--------------------------------------------------------*\ + ! Loop over the lowband wavelet coefficients in the tile ! + ! parameter memory and interleave them into the working ! + ! buffer. ! + \*--------------------------------------------------------*/ + for(i = 0; i < half_length; ++i) + { + working_buffer[i << 1].f = lowband->f; + lowband += increment; + } + + /*--------------------------------------------------------*\ + ! Increase the half length in case of an even resolution ! + ! length to account for the half-length + 1 number of ! + ! highband wavelet coefficients. ! + \*--------------------------------------------------------*/ + if(length % 2) ++half_length; + + /*--------------------------------------------------------*\ + ! Loop over the highband wavelet coefficients in the tile ! + ! parameter memory and interleave them into the working ! + ! buffer. ! + \*--------------------------------------------------------*/ + for(i = 0; i < half_length; ++i) + { + working_buffer[(i << 1) + 1].f = highband->f; + highband += increment; + } + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void whole_point_symmetric_extend(bwc_sample *const working_buffer, uint64 res0, ! +! ------------ uint64 res1, ! +! uint8 nTaps) ! +! ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is used to fill the boundary values of the working buffer with appropriate ! +! flow field data using a symmetric whole point extension: ! +! ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ! +! |___|___|___||_A_|_B_|_C_|_D_|_E_| ... |_V_|_W_|_X_|_Y_|_Z_||___|___|___| ! +! | ! +! | ! +! \|/ ! +! ___ ___ ___ ___ ___ ___ ___ ___ V ___ ___ ___ ___ ___ ___ ___ ___ ! +! |_E_|_C_|_B_||_A_|_B_|_C_|_D_|_E_| ... |_V_|_W_|_X_|_Y_|_Z_||_Y_|_X_|_W_| ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! working_buffer bwc_sample* - Working buffer used to store flow field ! +! data for the one dimensional dwt. ! +! ! +! res0 unsigned int(64 bit) - Starting point for the current resolu- ! +! tion and dimension. ! +! ! +! res1 unsigned int(64 bit) - End point for the current resolution ! +! and dimension. ! +! ! +! nTaps unsigned int(8 bit) - Maximum half length of a wavelet filter.! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 25.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +whole_point_symmetric_extend(bwc_sample *const working_buffer, uint64 res0, uint64 res1, uint8 nTaps) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 i, length; + int64 j, min, max; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(working_buffer); + + length = res1 - res0; + + if(nTaps < length) + { + for(i = 0; i < nTaps; ++i) + { + working_buffer[i - nTaps] = working_buffer[nTaps - i]; + working_buffer[length + i] = working_buffer[length - (i + 2)]; + } + } + else + { + min = nTaps; + max = nTaps + length - 1; + + for(i = 0; i < nTaps; ++i) + { + j = i; + + while (j < min || j > max) + { + if(j < min) j = (min << 1) - j; + else j = (max << 1) - j; + } + working_buffer[i - nTaps] = working_buffer[j - nTaps]; + + j = i + length + nTaps; + + while (j < min || j > max) + { + if(j < min) j = (min << 1) - j; + else j = (max << 1) - j; + } + working_buffer[i + length] = working_buffer[j - nTaps]; + } + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void forward_9x7_CDF_wavelet_transform(bwc_sample *const working_buffer, uint64 res0, ! +! ------------ uint64 res1) ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function applies the forward (9-7) Cohen-Daubechies-Feauveau wavelet transform on the ! +! data samples stored in the working buffer. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! working_buffer bwc_sample* - Working buffer used to store flow field ! +! data for the one dimensional dwt. ! +! ! +! res0 unsigned int(64 bit) - Starting point for the current resolu- ! +! tion and dimension. ! +! ! +! res1 unsigned int(64 bit) - End point for the current resolution ! +! and dimension. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 25.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +forward_9x7_CDF_wavelet_transform(bwc_sample *const working_buffer, uint64 res0, uint64 res1) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + int64 i, length; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(working_buffer); + + length = res1 - res0; + + /*--------------------------------------------------------*\ + ! Perform the first predictor step on the odd samples. ! + \*--------------------------------------------------------*/ + for(i = -3; i < length + 3; i += 2) + { + working_buffer[i].f += ALPHA * (working_buffer[i - 1].f + working_buffer[i + 1].f); + } + + /*--------------------------------------------------------*\ + ! Perform the first update step on the even samples. ! + \*--------------------------------------------------------*/ + for(i = -2; i < length + 2; i += 2) + { + working_buffer[i].f += BETA * (working_buffer[i - 1].f + working_buffer[i + 1].f); + } + + /*--------------------------------------------------------*\ + ! Perform the second predictor and scaling step on the odd ! + ! samples. ! + \*--------------------------------------------------------*/ + for(i = -1; i < length + 1; i += 2) + { + working_buffer[i].f += GAMMA * (working_buffer[i - 1].f + working_buffer[i + 1].f); + working_buffer[i].f = KAPPA_H * working_buffer[i].f; + } + + /*--------------------------------------------------------*\ + ! Perform the second update and scaling step on the even ! + ! samples. The delta coefficient has been modified to ! + ! account for the scaling step on the even samples. ! + \*--------------------------------------------------------*/ + for(i = 0; i < length; i += 2) + { + working_buffer[i].f += DELTA * (working_buffer[i - 1].f + working_buffer[i + 1].f); + working_buffer[i].f = KAPPA_L * working_buffer[i].f; + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void inverse_9x7_CDF_wavelet_transform(bwc_sample *const working_buffer, uint64 res0, ! +! ------------ uint64 res1) ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function applies the inverse (9-7) Cohen-Daubechies-Feauveau wavelet transform on the ! +! data samples stored in the working buffer. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! working_buffer bwc_sample* - Working buffer used to store flow field ! +! data for the one dimensional dwt. ! +! ! +! res0 unsigned int(64 bit) - Starting point for the current resolu- ! +! tion and dimension. ! +! ! +! res1 unsigned int(64 bit) - End point for the current resolution ! +! and dimension. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 25.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +inverse_9x7_CDF_wavelet_transform(bwc_sample *const working_buffer, uint64 res0, uint64 res1) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + int64 i, length; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(working_buffer); + + length = res1 - res0; + + /*--------------------------------------------------------*\ + ! Perform the second update and scaling step on the even ! + ! samples. The delta coefficient has been modified to ! + ! account for the scaling step on the even samples. ! + \*--------------------------------------------------------*/ + for(i = -4; i < length + 4; i += 2) + { + working_buffer[i].f = KAPPA_H * working_buffer[i].f; + working_buffer[i].f -= DELTA * (working_buffer[i - 1].f + working_buffer[i + 1].f); + } + + /*--------------------------------------------------------*\ + ! Perform the second predictor and scaling step on the odd ! + ! samples. ! + \*--------------------------------------------------------*/ + for(i = -5; i < length + 3; i += 2) + { + working_buffer[i].f = KAPPA_L * working_buffer[i].f; + working_buffer[i].f -= GAMMA * (working_buffer[i - 1].f + working_buffer[i + 1].f); + } + + /*--------------------------------------------------------*\ + ! Perform the first update step on the even samples. ! + \*--------------------------------------------------------*/ + for(i = -4; i < length + 2; i += 2) + { + working_buffer[i].f -= BETA * (working_buffer[i - 1].f + working_buffer[i + 1].f); + } + + /*--------------------------------------------------------*\ + ! Perform the first predictor step on the odd samples. ! + \*--------------------------------------------------------*/ + for(i = -3; i < length + 1; i += 2) + { + working_buffer[i].f -= ALPHA * (working_buffer[i - 1].f + working_buffer[i + 1].f); + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void forward_5x3_LeGall_wavelet_transform(bwc_sample *const working_buffer, uint64 res0, ! +! ------------ uint64 res1) ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function applies the forward (5-3) LeGall wavelet transform on the data samples stored ! +! in the working buffer. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! working_buffer bwc_sample* - Working buffer used to store flow field ! +! data for the one dimensional dwt. ! +! ! +! res0 unsigned int(64 bit) - Starting point for the current resolu- ! +! tion and dimension. ! +! ! +! res1 unsigned int(64 bit) - End point for the current resolution ! +! and dimension. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 25.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +forward_5x3_LeGall_wavelet_transform(bwc_sample *const working_buffer, uint64 res0, uint64 res1) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + int64 i, length; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(working_buffer); + + length = res1 - res0; + + /*--------------------------------------------------------*\ + ! Perform the predictor step on the odd samples. ! + \*--------------------------------------------------------*/ + for(i = -1; i < length + 1; i += 2) + { + working_buffer[i].f -= (working_buffer[i - 1].f + working_buffer[i + 1].f) / 2; + } + + /*--------------------------------------------------------*\ + ! Perform the update step on the even samples. ! + \*--------------------------------------------------------*/ + for(i = 0; i < length; i += 2) + { + working_buffer[i].f += (working_buffer[i - 1].f + working_buffer[i + 1].f + 2) / 4; + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void inverse_5x3_LeGall_wavelet_transform(bwc_sample *const working_buffer, uint64 res0, ! +! ------------ uint64 res1) ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function applies the inverse (5-3) LeGall wavelet transform on the data samples stored ! +! in the working buffer. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! working_buffer bwc_sample* - Working buffer used to store flow field ! +! data for the one dimensional dwt. ! +! ! +! res0 unsigned int(64 bit) - Starting point for the current resolu- ! +! tion and dimension. ! +! ! +! res1 unsigned int(64 bit) - End point for the current resolution ! +! and dimension. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 25.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +inverse_5x3_LeGall_wavelet_transform(bwc_sample *const working_buffer, uint64 res0, uint64 res1) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + int64 i, length; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(working_buffer); + + length = res1 - res0; + + /*--------------------------------------------------------*\ + ! Perform the update step on the even samples. ! + \*--------------------------------------------------------*/ + for(i = -2; i < length + 1; i += 2) + { + working_buffer[i].f -= (working_buffer[i - 1].f + working_buffer[i + 1].f + 2) / 4; + } + + /*--------------------------------------------------------*\ + ! Perform the predictor step on the odd samples. ! + \*--------------------------------------------------------*/ + for(i = -1; i < length; i += 2) + { + working_buffer[i].f += (working_buffer[i - 1].f + working_buffer[i + 1].f) / 2; + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void forward_Haar_wavelet_transform(bwc_sample *const working_buffer, uint64 res0, ! +! ------------ uint64 res1) ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function applies the forward Haar wavelet transform on the data samples stored in the ! +! working buffer. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! working_buffer bwc_sample* - Working buffer used to store flow field ! +! data for the one dimensional dwt. ! +! ! +! res0 unsigned int(64 bit) - Starting point for the current resolu- ! +! tion and dimension. ! +! ! +! res1 unsigned int(64 bit) - End point for the current resolution ! +! and dimension. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 25.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +forward_Haar_wavelet_transform(bwc_sample *const working_buffer, uint64 res0, uint64 res1) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + int64 i, length; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(working_buffer); + + length = res1 - res0; + + /*--------------------------------------------------------*\ + ! Perform the predictor step on the odd samples. ! + \*--------------------------------------------------------*/ + for(i = 1; i < length; i += 2) + { + working_buffer[i].f -= working_buffer[i - 1].f; + } + + /*--------------------------------------------------------*\ + ! Perform the update step on the even samples. ! + \*--------------------------------------------------------*/ + for(i = 0; i < length; i += 2) + { + working_buffer[i].f += working_buffer[i + 1].f / 2; + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void inverse_Haar_wavelet_transform(bwc_sample *const working_buffer, uint64 res0, ! +! ------------ uint64 res1) ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function applies the inverse Haar wavelet transform on the data samples stored in the ! +! working buffer. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! working_buffer bwc_sample* - Working buffer used to store flow field ! +! data for the one dimensional dwt. ! +! ! +! res0 unsigned int(64 bit) - Starting point for the current resolu- ! +! tion and dimension. ! +! ! +! res1 unsigned int(64 bit) - End point for the current resolution ! +! and dimension. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 25.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +inverse_Haar_wavelet_transform(bwc_sample *const working_buffer, uint64 res0, uint64 res1) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + int64 i, length; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(working_buffer); + + length = res1 - res0; + + /*--------------------------------------------------------*\ + ! Perform the update step on the even samples. ! + \*--------------------------------------------------------*/ + for(i = 0; i < length; i += 2) + { + working_buffer[i].f -= working_buffer[i + 1].f / 2; + } + + /*--------------------------------------------------------*\ + ! Perform the predictor step on the odd samples. ! + \*--------------------------------------------------------*/ + for(i = 1; i < length; i += 2) + { + working_buffer[i].f += working_buffer[i - 1].f; + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void buffer_flush_forward(bwc_sample *const data, bwc_sample *const working_buffer, ! +! ------------ uint64 res0, ! +! uint64 res1, ! +! uint64 increment) ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function creates the low- and highbands in the tile parameter after a one dimensional ! +! wavelet transform by copying the coefficients in the working buffer to their appropriate ! +! position in the tile parameter memory. In case of an odd length working buffer there are ! +! half_length + 1 lowband coefficients present in the buffer memory. Therefore, this func- ! +! tion loops through half_length - 1 wavelet coefficients and handles the last (two) coeffi- ! +! cient(s) separately. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! working_buffer bwc_sample* - Working buffer used to store flow field ! +! data for the one dimensional dwt. ! +! ! +! res0 unsigned int(64 bit) - Starting point for the current resolu- ! +! tion and dimension. ! +! ! +! res1 unsigned int(64 bit) - End point for the current resolution ! +! and dimension. ! +! ! +! increment unsigned int(64 bit) - Data increment for strided memory ac- ! +! cess. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 25.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +buffer_flush_forward(bwc_sample *const data, bwc_sample *const working_buffer, uint64 res0, uint64 res1, uint64 increment) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + int64 i, length, half_length; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_sample *lowband, *highband; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(data); + assert(working_buffer); + + /*--------------------------------------------------------*\ + ! Calculate the length and half_length of the buffer. ! + \*--------------------------------------------------------*/ + length = res1 - res0; + half_length = (res0 % 2) ? length >> 1 : (length + 1) >> 1; + + /*--------------------------------------------------------*\ + ! Associate the data pointers to the starting point of the ! + ! low- and highband. ! + \*--------------------------------------------------------*/ + lowband = data; + highband = data + half_length * increment; + + /*--------------------------------------------------------*\ + ! In case of an odd starting point copy the first highband ! + ! coefficient from the working buffer. ! + \*--------------------------------------------------------*/ + if(res0 % 2) + { + highband->f = working_buffer[-1].f; + highband += increment; + } + + /*--------------------------------------------------------*\ + ! Loop over the interleaved values in the working buffer ! + ! and fill the high- and lowbands in the tile parameter ! + ! memory. ! + \*--------------------------------------------------------*/ + for(i = 0; i < half_length - 1; ++i) + { + lowband->f = working_buffer[i << 1].f; + highband->f = working_buffer[(i << 1) + 1].f; + lowband += increment; + highband += increment; + } + + /*--------------------------------------------------------*\ + ! Copy the remaining lowband coefficient in case of an odd ! + ! length working buffer. ! + \*--------------------------------------------------------*/ + if(res1 % 2) + { + lowband->f = working_buffer[i << 1].f; + } + + /*--------------------------------------------------------*\ + ! Copy the remaining high- and lowband coefficient in case ! + ! of an even length working buffer. ! + \*--------------------------------------------------------*/ + else + { + lowband->f = working_buffer[i << 1].f; + highband->f = working_buffer[(i << 1) + 1].f; + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void buffer_flush_inverse(bwc_sample *const data, bwc_sample *const working_buffer, ! +! ------------ uint64 res0, ! +! uint64 res1, ! +! uint64 increment) ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function copies the decompressed flow field data for the current resolution level from ! +! the working buffer to the tile parameter memory. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! working_buffer bwc_sample* - Working buffer used to store flow field ! +! data for the one dimensional dwt. ! +! ! +! res0 unsigned int(64 bit) - Starting point for the current resolu- ! +! tion and dimension. ! +! ! +! res1 unsigned int(64 bit) - End point for the current resolution ! +! and dimension. ! +! ! +! increment unsigned int(64 bit) - Data increment for strided memory ac- ! +! cess. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 25.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +buffer_flush_inverse(bwc_sample *const data, bwc_sample *const working_buffer, uint64 res0, uint64 res1, uint64 increment) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + int64 i, j, length; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_sample *memory; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(data); + assert(working_buffer); + + /*--------------------------------------------------------*\ + ! Associate the data pointer to the starting point of the ! + ! tile parameter resolution. ! + \*--------------------------------------------------------*/ + memory = data; + + /*--------------------------------------------------------*\ + ! Calculate the length of the buffer. ! + \*--------------------------------------------------------*/ + length = res1 - res0; + + /*--------------------------------------------------------*\ + ! In case of an odd starting point copy the first sample ! + ! to the tile parameter memory. ! + \*--------------------------------------------------------*/ + if(res0 % 2) + { + memory->f = working_buffer[-1].f; + memory += increment; + length--; + } + + /*--------------------------------------------------------*\ + ! Copy the decompressed flow field data from the working ! + ! buffer to the strided tile parameter memory for the ! + ! current resolution level. ! + \*--------------------------------------------------------*/ + for(i = 0, j = 0; i < length; ++i) + { + memory[j].f = working_buffer[i].f; + j += increment; + } +} +/************************************************************************************************************\ +|| ___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || +|| |__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ || +|| | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] || +|| || +\************************************************************************************************************/ +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: int initialize_gain_lut() ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function calculates the energy gain factor Gb for the one dimensional, dyadic tree ! +! structured CDF-(9/7), LeGall-(5/3) and Haar wavelet transform with 5 levels. The energy ! +! gain factors are calculated according to equation (4.39) from JPEG2000 by David S. Taubman ! +! and Michael W. Marcellin (p. 193): ! +! ! +! s_L1[n] = g0[n], s_H1[n] = h0[n], ! +! s_Ld[n] = ∑(s_Ld-1[k]*g0[n-2k], k), s_Hd[n] = ∑(s_Hd-1[k]*g0[n-2k], k). ! +! ! +! The energy gain factors are stored in their corresponding lookup tables and used to calcu- ! +! late the energy gain for the multi dimensional wavelet transforms according to equation ! +! (4.40) from JPEG2000 by David S. Taubman and Michael W. Marcellin (p.193): ! +! ! +! s_LLD[n1,n2] = s_LD[n1] * s_LD[n2] => G_LLD = G_LD * G_LD ! +! s_HLD[n1,n2] = s_LD[n1] * s_HD[n2] => G_HLD = G_LD * G_HD ! +! s_LHD[n1,n2] = s_HD[n1] * s_LD[n2] => G_LHD = G_HD * G_LD ! +! s_HHD[n1,n2] = s_HD[n1] * s_HD[n2] => G_HHD = G_HD * G_HD ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! uchar - Error flag used to determine wether the LUT initialization ! +! was successful. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 21.03.2017 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uchar +initialize_gain_lut() +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + int32 l,m; + int8 i,j,k; + int8 Length_FB, Length_Gb; + + /*-----------------------*\ + ! DEFINE FLOAT VARIABLES: ! + \*-----------------------*/ + double *buff1, *buff2, *temp; + double *LUT; + + /*-----------------------*\ + ! DEFINE INT CONSTANTS: ! + \*-----------------------*/ + static const int* Length; + static const int DWT_HAAR_FILTER_LENGTH[2] = {2,2}; + static const int DWT_5X3_FILTER_LENGTH[2] = {1,2}; + static const int DWT_9X7_FILTER_LENGTH[2] = {3,4}; + + /*-----------------------*\ + ! DEFINE FLOAT CONSTANTS: ! + \*-----------------------*/ + const double* filter_taps; + + static const double DWT_HAAR_FILTER[2][5] = {{DWT_HAAR_H1, DWT_HAAR_H0, 0, 0, 0}, + {DWT_HAAR_G1, DWT_HAAR_G0, 0, 0, 0}}; + static const double DWT_5X3_FILTER[2][5] = {{DWT_5X3_H1, DWT_5X3_H0, 0, 0, 0}, + {DWT_5X3_G2, DWT_5X3_G1, DWT_5X3_G0, 0, 0}}; + static const double DWT_9X7_FILTER[2][5] = {{DWT_9X7_H3, DWT_9X7_H2, DWT_9X7_H1, DWT_9X7_H0, 0}, + {DWT_9X7_G4, DWT_9X7_G3, DWT_9X7_G2, DWT_9X7_G1, DWT_9X7_G0}}; + + /*--------------------------------------------------------*\ + ! Allocate memory for the work buffers used to calculate ! + ! the energy gain factors. ! + \*--------------------------------------------------------*/ + buff1 = calloc(512, sizeof(double)); + buff2 = calloc(512, sizeof(double)); + if (!buff1 || !buff2) + { + // memory allocation error + fprintf(stderr, MEMERROR); + free(buff1); + free(buff2); + return 1; + } + + /*--------------------------------------------------------*\ + ! Initialize the lookup tables for the CDF-(9/7), LeGall- ! + ! (5/3) and Haar wavelet transform by setting the energy ! + ! gain factor for level zero to one. ! + \*--------------------------------------------------------*/ + DWT_ENERGY_GAIN_LUT[bwc_dwt_9_7][0] = DWT_ENERGY_GAIN_LUT[bwc_dwt_9_7][MAX_DECOMP_LEVELS + 1] = 1.0f; + DWT_ENERGY_GAIN_LUT[bwc_dwt_5_3][0] = DWT_ENERGY_GAIN_LUT[bwc_dwt_5_3][MAX_DECOMP_LEVELS + 1] = 1.0f; + DWT_ENERGY_GAIN_LUT[bwc_dwt_haar][0] = DWT_ENERGY_GAIN_LUT[bwc_dwt_haar][MAX_DECOMP_LEVELS + 1] = 1.0f; + + /*--------------------------------------------------------*\ + ! Loop through the symmetric wavelet filter banks and as- ! + ! semble their respective energy gain factor lookup table. ! + \*--------------------------------------------------------*/ + for(i = 0; i < 2; i++) + { + /*--------------------------------------------------------*\ + ! Assign the Lookup Table (LUT), Length and filter_taps ! + ! pointer to their respective wavelet kernel and set the ! + ! filter_bank (Length_FB) and work buffer (Length_Gb) ! + ! length to the corresponding low-pass synthesis filter ! + ! length. ! + \*--------------------------------------------------------*/ + if(i == 0) + { + LUT = &DWT_ENERGY_GAIN_LUT[bwc_dwt_9_7][1]; + Length = &DWT_9X7_FILTER_LENGTH[0]; + Length_FB = Length_Gb = Length[0]; + filter_taps = &DWT_9X7_FILTER[0][0]; + } + else if(i == 1) + { + LUT = &DWT_ENERGY_GAIN_LUT[bwc_dwt_5_3][1]; + Length = &DWT_5X3_FILTER_LENGTH[0]; + Length_FB = Length_Gb = Length[0]; + filter_taps = &DWT_5X3_FILTER[0][0]; + } + /*--------------------------------------------------------*\ + ! Loop through the low- and high-pass synthesis filter ! + ! banks of the corresponding wavelet kernel. ! + \*--------------------------------------------------------*/ + for(j = 0; j < 2; j++) + { + /*--------------------------------------------------------*\ + ! Initialize work buffer 1 with the low-pass filter for ! + ! the low-pass energy gain factor, or the high-pass filter ! + ! for the high-pass energy gain factor. ! + \*--------------------------------------------------------*/ + for(k = 0; k < Length_Gb + 1; ++k) + { + buff1[k] = buff1[2*Length_Gb-k] = filter_taps[k+5*j]; + } + /*--------------------------------------------------------*\ + ! Calculate the energy gain factor for the first decomp. ! + ! level by evaluating the square norm of work buffer 1. ! + \*--------------------------------------------------------*/ + for(k = 0; k < (2 * Length_Gb + 1); ++k) + { + LUT[0] += buff1[k] * buff1[k]; + } + /*--------------------------------------------------------*\ + ! Loop through the remaining decomposition levels. ! + \*--------------------------------------------------------*/ + for(k = 1; k < MAX_DECOMP_LEVELS; ++k) + { + /*--------------------------------------------------------*\ + ! Assemble the low- or high-pass synthesis sequence for ! + ! decomposition level i in work buffer 2. ! + \*--------------------------------------------------------*/ + for(l = 0; l < (2 * Length_Gb + 1); ++l) + { + buff2[2 * l + Length_FB] += buff1[l] * filter_taps[Length_FB]; + for(m = 0; m < Length_FB; ++m) + { + buff2[2 * l + m] += buff1[l] * filter_taps[m]; + buff2[2 * l + (2*Length_FB-m)] += buff1[l] * filter_taps[m]; + } + } + /*--------------------------------------------------------*\ + ! Assign the memory of work buffer 2 to work buffer 1 and ! + ! vice versa. Set work buffer 2 to 0 and reevaluate the ! + ! length of work buffer 1. ! + \*--------------------------------------------------------*/ + temp = buff1; + buff1 = buff2; + buff2 = temp; + memset(buff2, 0, 512 * sizeof(double)); + Length_Gb = 2* Length_Gb + Length_FB; + /*--------------------------------------------------------*\ + ! Calculate the energy gain factor for decomposition level ! + ! i by evaluating the square norm of work buffer 1. ! + \*--------------------------------------------------------*/ + for(l = 0; l < (2 * Length_Gb + 1); ++l) + { + LUT[k] += buff1[l] * buff1[l]; + } + } + /*--------------------------------------------------------*\ + ! Advance the LUT Pointer to the memory reserved for the ! + ! high-pass energy gain factor and set the length of work ! + ! buffer 1 to the corresponding high-pass filter length. ! + \*--------------------------------------------------------*/ + LUT += MAX_DECOMP_LEVELS + 1; + Length_Gb = Length[1]; + } + /*--------------------------------------------------------*\ + ! Set work buffer 1 to 0. ! + \*--------------------------------------------------------*/ + memset(buff1, 0, 512 * sizeof(double)); + } + + /*--------------------------------------------------------*\ + ! Loop through the asymmetric wavelet filter banks and as- ! + ! semble their respective energy gain factor lookup table. ! + \*--------------------------------------------------------*/ + for(i = 0; i < 1; ++i) + { + /*--------------------------------------------------------*\ + ! Initialize work buffer 1 with the low-pass filter for ! + ! the low-pass energy gain factor, or the high-pass filter ! + ! for the high-pass energy gain factor. ! + \*--------------------------------------------------------*/ + if(i == 0) + { + LUT = &DWT_ENERGY_GAIN_LUT[bwc_dwt_haar][1]; + Length = &DWT_HAAR_FILTER_LENGTH[0]; + Length_FB = Length_Gb = Length[0]; + filter_taps = &DWT_HAAR_FILTER[0][0]; + } + /*--------------------------------------------------------*\ + ! Loop through the low- and high-pass synthesis filter ! + ! banks of the corresponding wavelet kernel. ! + \*--------------------------------------------------------*/ + for(j = 0; j < 2; ++j) + { + /*--------------------------------------------------------*\ + ! Initialize work buffer 1 with the low-pass filter for ! + ! the low-pass energy gain factor, or the high-pass filter ! + ! for the high-pass energy gain factor. ! + \*--------------------------------------------------------*/ + for(k = 0; k < Length_Gb; ++k) + { + buff1[k] = filter_taps[k+5*j]; + } + /*--------------------------------------------------------*\ + ! Calculate the energy gain factor for the first decomp. ! + ! level by evaluating the square norm of work buffer 1. ! + \*--------------------------------------------------------*/ + for(k = 0; k < Length_Gb; ++k) + { + LUT[0] += buff1[k] * buff1[k]; + } + /*--------------------------------------------------------*\ + ! Loop through the remaining decomposition levels. ! + \*--------------------------------------------------------*/ + for(k = 1; k < MAX_DECOMP_LEVELS; ++k) + { + /*--------------------------------------------------------*\ + ! Assemble the low- or high-pass synthesis sequence for ! + ! decomposition level i in work buffer 2. ! + \*--------------------------------------------------------*/ + for(l = 0; l < Length_Gb; ++l) + { + for(m = 0; m < Length_FB; m++) + { + buff2[2 * l + m] += buff1[l] * filter_taps[m]; + } + } + /*--------------------------------------------------------*\ + ! Assign the memory of work buffer 2 to work buffer 1 and ! + ! vice versa. Set work buffer 2 to 0 and reevaluate the ! + ! length of work buffer 1. ! + \*--------------------------------------------------------*/ + temp = buff1; + buff1 = buff2; + buff2 = temp; + memset(buff2, 0, 512 * sizeof(double)); + Length_Gb = Length_Gb * Length_FB; + /*--------------------------------------------------------*\ + ! Calculate the energy gain factor for decomposition level ! + ! i by evaluating the square norm of work buffer 1. ! + \*--------------------------------------------------------*/ + for(l = 0; l < Length_Gb; ++l) + { + LUT[k] += buff1[l] * buff1[l]; + } + } + /*--------------------------------------------------------*\ + ! Calculate the energy gain factor for decomposition level ! + ! i by evaluating the square norm of work buffer 1. ! + \*--------------------------------------------------------*/ + LUT += MAX_DECOMP_LEVELS + 1; + Length_Gb = Length[1]; + } + /*--------------------------------------------------------*\ + ! Set work buffer 1 to 0. ! + \*--------------------------------------------------------*/ + memset(buff1, 0, 512 * sizeof(double)); + } + /*--------------------------------------------------------*\ + ! Free work buffer 1 and 2 and exit the subroutine. ! + \*--------------------------------------------------------*/ + free(buff1); + free(buff2); + return 0; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: bwc_float get_dwt_energy_gain(bwc_field *const field, uchar highband_flag, uint16 level) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function evaluates the energy gain factor according to the the specified decom- ! +! position level. For decomposition levels larger than MAX_DECOMP_LEVELS the filter gain ! +! for the extra levels is approximated by multiplying the energy gain factor by 2. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! highband_flag uchar - Defines the subband for which Gb is ! +! calculated. ! +! ! +! level uint16 - Defines the decomposition level for ! +! which Gb is calculated ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! double - Energy gain factor for two dimensional tree-structured subband ! +! transforms. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 13.04.2017 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +bwc_float +get_dwt_energy_gain(bwc_field *const field, uchar highband_flag, uint16 level) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + int8 level_X, level_Y, level_Z; + int8 level_TS; + + /*-----------------------*\ + ! DEFINE FLOAT VARIABLES: ! + \*-----------------------*/ + double Gb = 1.0f; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert(level <= field->control.nDecomp + 1); + assert(highband_flag <= DIM_ALL); + + /*--------------------------------------------------------*\ + ! Save the global control structure to a temporary varia- ! + ! ble to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + + /*--------------------------------------------------------*\ + ! Evaluate the number of decompositions in each temporal & ! + ! spatial directions according to the the global decompo - ! + ! sition level for which the energy gain factor is calcu- ! + ! lated for. ! + \*--------------------------------------------------------*/ + level_X = (level > control->decompX ) ? control->decompX : level; + level_Y = (level > control->decompY ) ? control->decompY : level; + level_Z = (level > control->decompZ ) ? control->decompZ : level; + level_TS = (level > control->decompTS) ? control->decompTS : level; + + /*--------------------------------------------------------*\ + ! Multiply the energy gain factor with the filter gain of ! + ! the wavelet kernel applied along the X-axis. For decom- ! + ! position levels larger than MAX_DECOMP_LEVELS the energy ! + ! gain for the extra levels is approximated by multiplying ! + ! it by 2. ! + \*--------------------------------------------------------*/ + if(level_X != 0) + { + while(level_X > MAX_DECOMP_LEVELS) + { + Gb *= 2.0f; + level_X--; + } + + Gb *= DWT_ENERGY_GAIN_LUT[control->KernelX][level_X + ((highband_flag & DIM_X) * (MAX_DECOMP_LEVELS + 1))]; + } + + /*--------------------------------------------------------*\ + ! Multiply the energy gain factor with the filter gain of ! + ! the wavelet kernel applied along the Y-axis. For decom- ! + ! position levels larger than MAX_DECOMP_LEVELS the energy ! + ! gain for the extra levels is approximated by multiplying ! + ! it by 2. ! + \*--------------------------------------------------------*/ + if(level_Y != 0) + { + while(level_Y > MAX_DECOMP_LEVELS) + { + Gb *= 2.0f; + level_Y--; + } + + Gb *= DWT_ENERGY_GAIN_LUT[control->KernelY][level_Y + (((highband_flag & DIM_Y) >> 1) * (MAX_DECOMP_LEVELS + 1))]; + } + + /*--------------------------------------------------------*\ + ! Multiply the energy gain factor with the filter gain of ! + ! the wavelet kernel applied along the Z-axis. For decom- ! + ! position levels larger than MAX_DECOMP_LEVELS the energy ! + ! gain for the extra levels is approximated by multiplying ! + ! it by 2. ! + \*--------------------------------------------------------*/ + if(level_Z != 0) + { + while(level_Z > MAX_DECOMP_LEVELS) + { + Gb *= 2.0f; + level_Z--; + } + + Gb *= DWT_ENERGY_GAIN_LUT[control->KernelZ][level_Z + (((highband_flag & DIM_Z) >> 2) * (MAX_DECOMP_LEVELS + 1))]; + } + + /*--------------------------------------------------------*\ + ! Multiply the energy gain factor with the filter gain of ! + ! the wavelet kernel applied along the TS-axis. For decom- ! + ! position levels larger than MAX_DECOMP_LEVELS the energy ! + ! gain for the extra levels is approximated by multiplying ! + ! it by 2. ! + \*--------------------------------------------------------*/ + if(level_TS != 0) + { + while(level_TS > MAX_DECOMP_LEVELS) + { + Gb *= 2.0f; + level_TS--; + } + + Gb *= DWT_ENERGY_GAIN_LUT[control->KernelTS][level_TS + (((highband_flag & DIM_TS) >> 3) * (MAX_DECOMP_LEVELS + 1))]; + } + return (bwc_float)Gb; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: uchar forward_discrete_wavelet_transform(bwc_field *const field, ! +! -------------- bwc_parameter *const parameter) ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function performs the forward discrete wavelet transform on the current tile param- ! +! eter. After loading the flow field samples for a row, column or spatial/temporal slice ! +! into a working buffer, a boundary extension operation is performed to ensure an approp. ! +! sample base. The working buffer is then transform using the wavelet kernel selected for ! +! the spatial or temporal dimension, sorted into high- and low-frequency samples and flushed ! +! back into the tile parameter memory block. This operation is performed for every row, ! +! column and spatial/temporal slice for nDecomp number of decomposition levels. ! +! ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! parameter bwc_parameter* - Structure defining a bwc parameter. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! uchar - Returns an unsigned char for error handling. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 13.04.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uchar +forward_wavelet_transform(bwc_field *const field, bwc_parameter *const parameter) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 incr_X, incr_Y, incr_Z; + uint64 rX0, rY0, rZ0; + uint64 rX1, rY1, rZ1; + uint64 width, height, depth; + uint64 x, y, z; + uint32 buff_size; + int16 i; + uint16 incr_TS; + uint16 rTS0; + uint16 rTS1; + uint16 dt; + uint16 t; + uint8 id; + uint8 filter_tapsX, filter_tapsY, filter_tapsZ; + uint8 filter_tapsTS; + uint8 level; + uint8 nThreads; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_param_inf *param_info; + bwc_sample *data, *working_buffer; + bwc_sample **memory; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert(parameter); + + /*-----------------------*\ + ! DEFINE FUNCTION PTR: ! + \*-----------------------*/ + void (*forward_wavelet_transform[3])(bwc_sample*, uint64, uint64) = {forward_9x7_CDF_wavelet_transform, + forward_5x3_LeGall_wavelet_transform, + forward_Haar_wavelet_transform}; + + void (*boundary_extension[3])(bwc_sample *, uint64, uint64, uint8) = {whole_point_symmetric_extend, + whole_point_symmetric_extend, + NULL}; + + /*--------------------------------------------------------*\ + ! Save the global control and parameter info structure to ! + ! temporary variables to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + param_info = ¶meter->info; + + /*--------------------------------------------------------*\ + ! Calculate the width, height, depth and temporal size dt ! + ! of the current tile parameter. ! + \*--------------------------------------------------------*/ + width = param_info->X1 - param_info->X0; + height = param_info->Y1 - param_info->Y0; + depth = param_info->Z1 - param_info->Z0; + dt = param_info->TS1 - param_info->TS0; + + /*--------------------------------------------------------*\ + ! Calculate the increments used to fill the working buffer ! + ! for the spacial/temporal wavelet transformation. ! + \*--------------------------------------------------------*/ + incr_X = 1; + incr_Y = width; + incr_Z = width * height; + incr_TS = width * height * depth; + + /*--------------------------------------------------------*\ + ! Evaluate the filter taps for the spatial and temporal ! + ! wavelet filters. Additionally, the filter taps are in- ! + ! creased by 2 to account for an increase in highband ! + ! coefficients in case of an odd-length dataset. ! + \*--------------------------------------------------------*/ + filter_tapsX = get_filter_taps(control->KernelX) + 2; + filter_tapsY = get_filter_taps(control->KernelY) + 2; + filter_tapsZ = get_filter_taps(control->KernelZ) + 2; + filter_tapsTS = get_filter_taps(control->KernelTS) + 2; + + /*--------------------------------------------------------*\ + ! Evaluate the number of threads for the current compres- ! + ! sion run and the buffer size for the current tile param- ! + ! eter. ! + \*--------------------------------------------------------*/ + #if defined (_OPENMP) + nThreads = omp_get_max_threads(); + #else + nThreads = 1; + #endif + + buff_size = MAX(MAX(width, height), MAX(depth, dt)) + 2 * + MAX(MAX(filter_tapsX, filter_tapsY), + MAX(filter_tapsZ, filter_tapsTS)); + + /*--------------------------------------------------------*\ + ! Allocate the memory array and memory blocks for the ! + ! working buffer for each OpenMP thread. In case of a ! + ! serial run only one memory block will be allocated. ! + \*--------------------------------------------------------*/ + memory = calloc(nThreads, sizeof(bwc_sample*)); + if(!memory) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + for(i = 0; i < nThreads; ++i) + { + memory[i] = calloc(buff_size, sizeof(bwc_sample)); + if(!memory[i]) + { + // memory allocation error + fprintf(stderr, MEMERROR); + for(i--; i > 0; --i) + { + free(memory[i]); + } + free(memory); + return 1; + } + } + + /*--------------------------------------------------------*\ + ! Walk through all decomposition levels and apply the 1D ! + ! wavelet transform along the spatial and temporal dimen- ! + ! sions specified in the control structure. ! + \*--------------------------------------------------------*/ + #if defined(_OPENMP) + #pragma omp parallel private(data, id, level, working_buffer, rX0, rX1, rY0, rY1, rZ0, rZ1, rTS0, rTS1) + #endif + { + /*--------------------------------------------------------*\ + ! Evaluate the id of the current OpenMP thread. In case of ! + ! a serial run the thread id is set to 0. ! + \*--------------------------------------------------------*/ + #if defined (_OPENMP) + id = omp_get_thread_num(); + #else + id = 0; + #endif + + for(level = 0; level < control->nDecomp; ++level) + { + /*--------------------------------------------------------*\ + ! Save the resolution starting and end points to a tempo- ! + ! rary variable to make the code more readable. ! + \*--------------------------------------------------------*/ + rX0 = (uint64)parameter->resolution[control->nDecomp - level].info.X0; + rX1 = (uint64)parameter->resolution[control->nDecomp - level].info.X1; + rY0 = (uint64)parameter->resolution[control->nDecomp - level].info.Y0; + rY1 = (uint64)parameter->resolution[control->nDecomp - level].info.Y1; + rZ0 = (uint64)parameter->resolution[control->nDecomp - level].info.Z0; + rZ1 = (uint64)parameter->resolution[control->nDecomp - level].info.Z1; + rTS0 = (uint16)parameter->resolution[control->nDecomp - level].info.TS0; + rTS1 = (uint16)parameter->resolution[control->nDecomp - level].info.TS1; + + if(level < control->decompX && (rX1 - rX0) > 1) + { + /*--------------------------------------------------------*\ + ! Associate the working buffer pointer to the allocated ! + ! memory block. The working buffer points to the appropri- ! + ! ate starting point in the memory block, accounting for ! + ! the taps of the wavelet kernel selected for the first ! + ! spatial dimension. ! + \*--------------------------------------------------------*/ + working_buffer = &memory[id][filter_tapsX]; + + /*--------------------------------------------------------*\ + ! Adjust the working buffer pointer in case of an odd ! + ! length column starting point. ! + \*--------------------------------------------------------*/ + if(rX0 % 2) + { + ++working_buffer; + } + + /*--------------------------------------------------------*\ + ! Walk trough all the temporal and spatial slices as well ! + ! as rows. ! + \*--------------------------------------------------------*/ + #if defined(_OPENMP) + #pragma omp for collapse(3) + #endif + for(t = 0; t < (rTS1 - rTS0); ++t) + { + for(z = 0; z < (rZ1 - rZ0); ++z) + { + for(y = 0; y < (rY1 - rY0); ++y) + { + /*--------------------------------------------------------*\ + ! Advance the data pointer to the next column. ! + \*--------------------------------------------------------*/ + data = parameter->data + y * incr_Y + z * incr_Z + t * incr_TS; + + /*--------------------------------------------------------*\ + ! In the event that the current column and resolution only ! + ! encompasses 1 value, the sample will remain unaltered. ! + ! In case of an odd starting point the sample will be ! + ! doubled. ! + \*--------------------------------------------------------*/ + if((rX1 - rX0) == 1) + { + if(rX0 & 2) + { + data[0].f *= 2; + } + continue; + } + + /*--------------------------------------------------------*\ + ! Fill the working buffer with the y-th tile parameter ! + ! column. ! + \*--------------------------------------------------------*/ + fill_forward_buffer(data, &memory[id][filter_tapsX], rX0, rX1, incr_X); + + /*--------------------------------------------------------*\ + ! Apply the boundary extension on the working buffer ap- ! + ! propriate to the specified wavelet kernel. ! + \*--------------------------------------------------------*/ + boundary_extension[control->KernelX](&memory[id][filter_tapsX], rX0, rX1, filter_tapsX); + + /*--------------------------------------------------------*\ + ! Perform the forward wavelet transform on the current ! + ! column. ! + \*--------------------------------------------------------*/ + forward_wavelet_transform[control->KernelX](working_buffer, rX0, rX1); + + /*--------------------------------------------------------*\ + ! Copy the interleaved wavelet coefficients from the work- ! + ! ing buffer to the tile parameter memory. ! + \*--------------------------------------------------------*/ + buffer_flush_forward(data, working_buffer, rX0, rX1, incr_X); + } + } + } + } + + if(level < control->decompY && (rY1 - rY0) > 1) + { + /*--------------------------------------------------------*\ + ! Associate the working buffer pointer to the allocated ! + ! memory block. The working buffer points to the appropri- ! + ! ate starting point in the memory block, accounting for ! + ! for the taps of the wavelet kernel selected for the ! + ! second spatial dimension. ! + \*--------------------------------------------------------*/ + working_buffer = &memory[id][filter_tapsY]; + + /*--------------------------------------------------------*\ + ! Adjust the working buffer pointer in case of an odd ! + ! length row starting point. ! + \*--------------------------------------------------------*/ + if(rY0 % 2) + { + working_buffer++; + } + + /*--------------------------------------------------------*\ + ! Walk trough all the temporal and spatial slices as well ! + ! as columns. ! + \*--------------------------------------------------------*/ + #if defined(_OPENMP) + #pragma omp for collapse(3) + #endif + for(t = 0; t < (rTS1 - rTS0); ++t) + { + for(z = 0; z < (rZ1 - rZ0); ++z) + { + for(x = 0; x < (rX1 - rX0); ++x) + { + /*--------------------------------------------------------*\ + ! Advance the data pointer to the next row. ! + \*--------------------------------------------------------*/ + data = parameter->data + x * incr_X + z * incr_Z + t * incr_TS; + + /*--------------------------------------------------------*\ + ! In the event that the current row and resolution only ! + ! encompasses 1 value, the sample will remain unaltered. ! + ! In case of an odd starting point the sample will be ! + ! doubled. ! + \*--------------------------------------------------------*/ + if((rY1 - rY0) == 1) + { + if(rY0 & 2) + { + data[0].f *= 2; + } + continue; + } + + /*--------------------------------------------------------*\ + ! Fill the working buffer with the x-th tile parameter ! + ! row. ! + \*--------------------------------------------------------*/ + fill_forward_buffer(data, &memory[id][filter_tapsY], rY0, rY1, incr_Y); + + /*--------------------------------------------------------*\ + ! Apply the boundary extension on the working buffer ap- ! + ! propriate to the specified wavelet kernel. ! + \*--------------------------------------------------------*/ + boundary_extension[control->KernelY](&memory[id][filter_tapsY], rY0, rY1, filter_tapsY); + + /*--------------------------------------------------------*\ + ! Perform the forward wavelet transform on the current ! + ! row. ! + \*--------------------------------------------------------*/ + forward_wavelet_transform[control->KernelY](working_buffer, rY0, rY1); + + /*--------------------------------------------------------*\ + ! Copy the interleaved wavelet coefficients from the work- ! + ! ing buffer to the tile parameter memory. ! + \*--------------------------------------------------------*/ + buffer_flush_forward(data, working_buffer, rY0, rY1, incr_Y); + } + } + } + } + + if(level < control->decompZ && (rZ1 - rZ0) > 1) + { + /*--------------------------------------------------------*\ + ! Associate the working buffer pointer to the allocated ! + ! memory block. The working buffer points to the appropri- ! + ! ate starting point in the memory block, accounting for ! + ! for the taps of the wavelet kernel selected for the ! + ! third spatial dimension. ! + \*--------------------------------------------------------*/ + working_buffer = &memory[id][filter_tapsZ]; + + /*--------------------------------------------------------*\ + ! Adjust the working buffer pointer in case of an odd ! + ! length starting point of the spatial slice. ! + \*--------------------------------------------------------*/ + if(rZ0 % 2) + { + working_buffer++; + } + + /*--------------------------------------------------------*\ + ! Walk trough all the temporal slices, rows and columns. ! + \*--------------------------------------------------------*/ + #if defined(_OPENMP) + #pragma omp for collapse(3) + #endif + for(t = 0; t < (rTS1 - rTS0); ++t) + { + for(y = 0; y < (rY1 - rY0); ++y) + { + for(x = 0; x < (rX1 - rX0); ++x) + { + /*--------------------------------------------------------*\ + ! Advance the data pointer to the next spatial slice. ! + \*--------------------------------------------------------*/ + data = parameter->data + x * incr_X + y * incr_Y + t * incr_TS; + + /*--------------------------------------------------------*\ + ! In the event that the current slice and resolution only ! + ! encompasses 1 value, the sample will remain unaltered. ! + ! In case of an odd starting point the sample will be ! + ! doubled. ! + \*--------------------------------------------------------*/ + if((rZ1 - rZ0) == 1) + { + if(rZ0 & 2) + { + data[0].f *= 2; + } + continue; + } + + /*--------------------------------------------------------*\ + ! Fill the working buffer with the x-th spatial tile para- ! + ! meter slice. ! + \*--------------------------------------------------------*/ + fill_forward_buffer(data, &memory[id][filter_tapsZ], rZ0, rZ1, incr_Z); + + /*--------------------------------------------------------*\ + ! Apply the boundary extension on the working buffer ap- ! + ! propriate to the specified wavelet kernel. ! + \*--------------------------------------------------------*/ + boundary_extension[control->KernelZ](&memory[id][filter_tapsZ], rZ0, rZ1, filter_tapsZ); + + /*--------------------------------------------------------*\ + ! Perform the forward wavelet transform on the current ! + ! spatial slice. ! + \*--------------------------------------------------------*/ + forward_wavelet_transform[control->KernelZ](working_buffer, rZ0, rZ1); + + /*--------------------------------------------------------*\ + ! Copy the interleaved wavelet coefficients from the work- ! + ! ing buffer to the tile parameter memory. ! + \*--------------------------------------------------------*/ + buffer_flush_forward(data, working_buffer, rZ0, rZ1, incr_Z); + } + } + } + } + + if(level < control->decompTS && (rTS1 - rTS0) > 1) + { + /*--------------------------------------------------------*\ + ! Associate the working buffer pointer to the allocated ! + ! memory block. The working buffer points to the appropri- ! + ! ate starting point in the memory block, accounting for ! + ! for the taps of the wavelet kernel selected for the ! + ! temporal dimension. ! + \*--------------------------------------------------------*/ + working_buffer = &memory[id][filter_tapsTS]; + + /*--------------------------------------------------------*\ + ! Adjust the working buffer pointer in case of an odd ! + ! length starting point of the temporal slice. ! + \*--------------------------------------------------------*/ + if(rTS0 % 2) + { + working_buffer++; + } + + /*--------------------------------------------------------*\ + ! Walk trough all the spatial slices, rows and columns. ! + \*--------------------------------------------------------*/ + #if defined(_OPENMP) + #pragma omp for collapse(3) + #endif + for(z = 0; z < (rZ1 - rZ0); ++z) + { + for(y = 0; y < (rY1 - rY0); ++y) + { + for(x = 0; x < (rX1 - rX0); ++x) + { + /*--------------------------------------------------------*\ + ! Advance the data pointer to the next temporal slice. ! + \*--------------------------------------------------------*/ + data = parameter->data + x * incr_X + y * incr_Y + z * incr_Z; + + /*--------------------------------------------------------*\ + ! In the event that the current slice and resolution only ! + ! encompasses 1 value, the sample will remain unaltered. ! + ! In case of an odd starting point the sample will be ! + ! doubled. ! + \*--------------------------------------------------------*/ + if((rTS1 - rTS0) == 1) + { + if(rTS0 & 2) + { + data[0].f *= 2; + } + continue; + } + + /*--------------------------------------------------------*\ + ! Fill the working buffer with the x-th temporal tile para-! + ! meter slice. ! + \*--------------------------------------------------------*/ + fill_forward_buffer(data, &memory[id][filter_tapsTS], rTS0, rTS1, incr_TS); + + /*--------------------------------------------------------*\ + ! Apply the boundary extension on the working buffer ap- ! + ! propriate to the specified wavelet kernel. ! + \*--------------------------------------------------------*/ + boundary_extension[control->KernelTS](&memory[id][filter_tapsTS], rTS0, rTS1, filter_tapsTS); + + /*--------------------------------------------------------*\ + ! Perform the forward wavelet transform on the current ! + ! temporal slice. ! + \*--------------------------------------------------------*/ + forward_wavelet_transform[control->KernelTS](working_buffer, rTS0, rTS1); + + /*--------------------------------------------------------*\ + ! Copy the interleaved wavelet coefficients from the work- ! + ! ing buffer to the tile parameter memory. ! + \*--------------------------------------------------------*/ + buffer_flush_forward(data, working_buffer, rTS0, rTS1, incr_TS); + } + } + } + } + } + } + + /*--------------------------------------------------------*\ + ! Deallocate the memory array and memory blocks. ! + \*--------------------------------------------------------*/ + for(i = 0; i < nThreads; ++i) + { + free(memory[i]); + } + free(memory); + + return 0; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: uchar inverse_discrete_wavelet_transform(bwc_field *const field, ! +! -------------- bwc_parameter *const parameter) ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function performs the inverse discrete wavelet transform on the current tile param- ! +! eter. After loading the interweaved wavelet coefficients for a row, column or spatial/ ! +! temporal slice into a working buffer, a boundary extension operation is performed to ! +! ensure an appropriate sample base. The working buffer is then transform using the wave- ! +! let kernel selected for the spatial or temporal dimension and flushed back into the tile ! +! parameter memory block. This operation is performed for every row, column and spatial/ ! +! temporal slice for nDecomp number of decomposition levels. ! +! ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! parameter bwc_parameter* - Structure defining a bwc parameter. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! uchar - Returns an unsigned char for error handling. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 13.04.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uchar +inverse_wavelet_transform(bwc_field *const field, bwc_parameter *const parameter) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 incr_X, incr_Y, incr_Z; + uint64 rX0, rY0, rZ0; + uint64 rX1, rY1, rZ1; + uint64 width, height, depth; + uint64 x, y, z; + uint32 buff_size; + int16 i; + uint16 incr_TS; + uint16 rTS0; + uint16 rTS1; + uint16 dt; + uint16 t; + uint8 id; + uint8 filter_tapsX, filter_tapsY, filter_tapsZ; + uint8 filter_tapsTS; + uint8 level; + uint8 nThreads; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_param_inf *param_info; + bwc_sample *data, *working_buffer; + bwc_sample **memory; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert(parameter); + + /*-----------------------*\ + ! DEFINE FUNCTION PTR: ! + \*-----------------------*/ + void (*inverse_wavelet_transform[3])(bwc_sample*, uint64, uint64) = {inverse_9x7_CDF_wavelet_transform, + inverse_5x3_LeGall_wavelet_transform, + inverse_Haar_wavelet_transform}; + + void (*boundary_extension[3])(bwc_sample *, uint64, uint64, uint8) = {whole_point_symmetric_extend, + whole_point_symmetric_extend, + NULL}; + + /*--------------------------------------------------------*\ + ! Save the global control and parameter info structure to ! + ! temporary variables to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + param_info = ¶meter->info; + + /*--------------------------------------------------------*\ + ! Calculate the width, height, depth and temporal size dt ! + ! of the current tile parameter. ! + \*--------------------------------------------------------*/ + width = param_info->X1 - param_info->X0; + height = param_info->Y1 - param_info->Y0; + depth = param_info->Z1 - param_info->Z0; + dt = param_info->TS1 - param_info->TS0; + + /*--------------------------------------------------------*\ + ! Calculate the increments used to fill the working buffer ! + ! for the spacial/temporal wavelet transforms. ! + \*--------------------------------------------------------*/ + incr_X = 1; + incr_Y = width; + incr_Z = width * height; + incr_TS = width * height * depth; + + /*--------------------------------------------------------*\ + ! Evaluate the filter taps for the spatial and temporal ! + ! wavelet filters. Additionally, the filter taps are in- ! + ! creased by 2 to account for an increase in highband ! + ! coefficients in case of an odd-length dataset. ! + \*--------------------------------------------------------*/ + filter_tapsX = get_filter_taps(control->KernelX) + 2; + filter_tapsY = get_filter_taps(control->KernelY) + 2; + filter_tapsZ = get_filter_taps(control->KernelZ) + 2; + filter_tapsTS = get_filter_taps(control->KernelTS) + 2; + + /*--------------------------------------------------------*\ + ! Evaluate the number of threads for the current compres- ! + ! sion run and the buffer size for the current tile param- ! + ! eter. ! + \*--------------------------------------------------------*/ + #if defined (_OPENMP) + nThreads = omp_get_max_threads(); + #else + nThreads = 1; + #endif + + buff_size = MAX(MAX(width, height), MAX(depth, dt)) + 2 * + MAX(MAX(filter_tapsX, filter_tapsY), + MAX(filter_tapsZ, filter_tapsTS)); + + /*--------------------------------------------------------*\ + ! Allocate the memory array and memory blocks for the ! + ! working buffer of each OpenMP thread. In case of a ! + ! serial run only one memory block will be allocated. ! + \*--------------------------------------------------------*/ + memory = calloc(nThreads, sizeof(bwc_sample*)); + if(!memory) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + for(i = 0; i < nThreads; ++i) + { + memory[i] = calloc(buff_size, sizeof(bwc_sample)); + if(!memory[i]) + { + // memory allocation error + fprintf(stderr, MEMERROR); + for(i--; i > 0; --i) + { + free(memory[i]); + } + free(memory); + return 1; + } + } + + /*--------------------------------------------------------*\ + ! Walk through all decomposition levels and apply the 1D ! + ! wavelet transform along the spatial and temporal dimen- ! + ! sions specified in the control structure. ! + \*--------------------------------------------------------*/ + #if defined(_OPENMP) + #pragma omp parallel private(data, id, level, working_buffer, rX0, rX1, rY0, rY1, rZ0, rZ1, rTS0, rTS1) + #endif + { + /*--------------------------------------------------------*\ + ! Evaluate the id of the current OpenMP thread. In case of ! + ! a serial run the thread id is set to 1. ! + \*--------------------------------------------------------*/ + #if defined (_OPENMP) + id = omp_get_thread_num(); + #else + id = 0; + #endif + + for(level = control->nDecomp; level --> 0;) + { + /*--------------------------------------------------------*\ + ! Save the resolution starting and end points to a tempo- ! + ! rary variable to make the code more readable. ! + \*--------------------------------------------------------*/ + rX0 = (uint64)parameter->resolution[control->nDecomp - level].info.X0; + rX1 = (uint64)parameter->resolution[control->nDecomp - level].info.X1; + rY0 = (uint64)parameter->resolution[control->nDecomp - level].info.Y0; + rY1 = (uint64)parameter->resolution[control->nDecomp - level].info.Y1; + rZ0 = (uint64)parameter->resolution[control->nDecomp - level].info.Z0; + rZ1 = (uint64)parameter->resolution[control->nDecomp - level].info.Z1; + rTS0 = (uint16)parameter->resolution[control->nDecomp - level].info.TS0; + rTS1 = (uint16)parameter->resolution[control->nDecomp - level].info.TS1; + + if(level < control->decompTS && (rTS1 - rTS0) > 1) + { + /*--------------------------------------------------------*\ + ! Associate the working buffer pointer to the allocated ! + ! memory block. The working buffer points to the appropri- ! + ! ate starting point in the memory block, accounting for ! + ! the taps of the wavelet kernel selected for the temporal ! + ! dimension. ! + \*--------------------------------------------------------*/ + working_buffer = &memory[id][filter_tapsTS]; + + /*--------------------------------------------------------*\ + ! Adjust the working buffer pointer in case of an odd ! + ! length starting point of the temporal slice. ! + \*--------------------------------------------------------*/ + if(rTS0 % 2) + { + working_buffer++; + } + + /*--------------------------------------------------------*\ + ! Walk trough all the spatial slices, rows and columns. ! + \*--------------------------------------------------------*/ + #if defined(_OPENMP) + #pragma omp for collapse(3) + #endif + for(z = 0; z < (rZ1 - rZ0); ++z) + { + for(y = 0; y < (rY1 - rY0); ++y) + { + for(x = 0; x < (rX1 - rX0); ++x) + { + /*--------------------------------------------------------*\ + ! Advance the data pointer to the next temporal slice. ! + \*--------------------------------------------------------*/ + data = parameter->data + x * incr_X + y * incr_Y + z * incr_Z; + + /*--------------------------------------------------------*\ + ! In the event that the current slice and resolution only ! + ! encompasses 1 value, the sample will remain unaltered. ! + ! In case of an odd starting point the sample will be ! + ! doubled. ! + \*--------------------------------------------------------*/ + if((rTS1 - rTS0) == 1) + { + if(rTS0 & 2) + { + data[0].f *= 2; + } + continue; + } + + /*--------------------------------------------------------*\ + ! Fill the working buffer with the x-th temporal tile para-! + ! meter slice. ! + \*--------------------------------------------------------*/ + fill_inverse_buffer(data, &memory[id][filter_tapsTS], rTS0, rTS1, incr_TS); + + /*--------------------------------------------------------*\ + ! Apply the boundary extension on the working buffer ap- ! + ! propriate to the specified wavelet kernel. ! + \*--------------------------------------------------------*/ + boundary_extension[control->KernelTS](&memory[id][filter_tapsTS], rTS0, rTS1, filter_tapsTS); + + /*--------------------------------------------------------*\ + ! Perform the inverse wavelet transform on the current ! + ! temporal slice. ! + \*--------------------------------------------------------*/ + inverse_wavelet_transform[control->KernelTS](working_buffer, rTS0, rTS1); + + /*--------------------------------------------------------*\ + ! Copy the interleaved wavelet coefficients from the work- ! + ! ing buffer to the tile parameter memory. ! + \*--------------------------------------------------------*/ + buffer_flush_inverse(data, working_buffer, rTS0, rTS1, incr_TS); + } + } + } + } + + if(level < control->decompZ && (rZ1 - rZ0) > 1) + { + /*--------------------------------------------------------*\ + ! Associate the working buffer pointer to the allocated ! + ! memory block. The working buffer points to the appropri- ! + ! ate starting point in the memory block, accounting for ! + ! for the taps of the wavelet kernel selected for the ! + ! third spatial dimension. ! + \*--------------------------------------------------------*/ + working_buffer = &memory[id][filter_tapsZ]; + + /*--------------------------------------------------------*\ + ! Adjust the working buffer pointer in case of an odd ! + ! length starting point of the spatial slice. ! + \*--------------------------------------------------------*/ + if(rZ0 % 2) + { + working_buffer++; + } + + /*--------------------------------------------------------*\ + ! Walk trough all the temporal slices, rows and columns. ! + \*--------------------------------------------------------*/ + #if defined(_OPENMP) + #pragma omp for collapse(3) + #endif + for(t = 0; t < (rTS1 - rTS0); ++t) + { + for(y = 0; y < (rY1 - rY0); ++y) + { + for(x = 0; x < (rX1 - rX0); ++x) + { + /*--------------------------------------------------------*\ + ! Advance the data pointer to the next spatial slice. ! + \*--------------------------------------------------------*/ + data = parameter->data + x * incr_X + y * incr_Y + t * incr_TS; + + /*--------------------------------------------------------*\ + ! In the event that the current slice and resolution only ! + ! encompasses 1 value, the sample will remain unaltered. ! + ! In case of an odd starting point the sample will be ! + ! doubled. ! + \*--------------------------------------------------------*/ + if((rZ1 - rZ0) == 1) + { + if(rZ0 & 2) + { + data[0].f /= 2; + } + continue; + } + + /*--------------------------------------------------------*\ + ! Fill the working buffer with the x-th spatial tile para- ! + ! meter slice. ! + \*--------------------------------------------------------*/ + fill_inverse_buffer(data, &memory[id][filter_tapsZ], rZ0, rZ1, incr_Z); + + /*--------------------------------------------------------*\ + ! Apply the boundary extension on the working buffer ap- ! + ! propriate to the specified wavelet kernel. ! + \*--------------------------------------------------------*/ + boundary_extension[control->KernelZ](&memory[id][filter_tapsZ], rZ0, rZ1, filter_tapsZ); + + /*--------------------------------------------------------*\ + ! Perform the inverse wavelet transform on the current ! + ! spatial slice. ! + \*--------------------------------------------------------*/ + inverse_wavelet_transform[control->KernelZ](working_buffer, rZ0, rZ1); + + /*--------------------------------------------------------*\ + ! Copy the decompressed flow field samples from the work- ! + ! ing buffer to the tile parameter memory. ! + \*--------------------------------------------------------*/ + buffer_flush_inverse(data, working_buffer, rZ0, rZ1, incr_Z); + } + } + } + } + + if(level < control->decompY && (rY1 - rY0) > 1) + { + /*--------------------------------------------------------*\ + ! Associate the working buffer pointer to the allocated ! + ! memory block. The working buffer points to the appropri- ! + ! ate starting point in the memory block, accounting for ! + ! for the taps of the wavelet kernel selected for the ! + ! second spatial dimension. ! + \*--------------------------------------------------------*/ + working_buffer = &memory[id][filter_tapsY]; + + /*--------------------------------------------------------*\ + ! Adjust the working buffer pointer in case of an odd ! + ! length row starting point. ! + \*--------------------------------------------------------*/ + if(rY0 % 2) + { + working_buffer++; + } + + /*--------------------------------------------------------*\ + ! Walk trough all the temporal and spatial slices as well ! + ! as columns. ! + \*--------------------------------------------------------*/ + #if defined(_OPENMP) + #pragma omp for collapse(3) + #endif + for(t = 0; t < (rTS1 - rTS0); ++t) + { + for(z = 0; z < (rZ1 - rZ0); ++z) + { + for(x = 0; x < (rX1 - rX0); ++x) + { + /*--------------------------------------------------------*\ + ! Advance the data pointer to the next row. ! + \*--------------------------------------------------------*/ + data = parameter->data + x * incr_X + z * incr_Z + t * incr_TS; + + /*--------------------------------------------------------*\ + ! In the event that the current row and resolution only ! + ! encompasses 1 value, the sample will remain unaltered. ! + ! In case of an odd starting point the sample will be ! + ! doubled. ! + \*--------------------------------------------------------*/ + if((rY1 - rY0) == 1) + { + if(rY0 & 2) + { + data[0].f /= 2; + } + continue; + } + + /*--------------------------------------------------------*\ + ! Fill the working buffer with the x-th tile parameter ! + ! row. ! + \*--------------------------------------------------------*/ + fill_inverse_buffer(data, &memory[id][filter_tapsY], rY0, rY1, incr_Y); + + /*--------------------------------------------------------*\ + ! Apply the boundary extension on the working buffer ap- ! + ! propriate to the specified wavelet kernel. ! + \*--------------------------------------------------------*/ + boundary_extension[control->KernelY](&memory[id][filter_tapsY], rY0, rY1, filter_tapsY); + + /*--------------------------------------------------------*\ + ! Perform the inverse wavelet transform on the current ! + ! column. ! + \*--------------------------------------------------------*/ + inverse_wavelet_transform[control->KernelY](working_buffer, rY0, rY1); + + /*--------------------------------------------------------*\ + ! Copy the decompressed flow field samples from the work- ! + ! ing buffer to the tile parameter memory. ! + \*--------------------------------------------------------*/ + buffer_flush_inverse(data, working_buffer, rY0, rY1, incr_Y); + } + } + } + } + + if(level < control->decompX && (rX1 - rX0) > 1) + { + /*--------------------------------------------------------*\ + ! Associate the working buffer pointer to the allocated ! + ! memory block. The working buffer points to the appropri- ! + ! ate starting point in the memory block, accounting for ! + ! for the taps of the wavelet kernel selected for the ! + ! first spatial dimension. ! + \*--------------------------------------------------------*/ + working_buffer = &memory[id][filter_tapsX]; + + /*--------------------------------------------------------*\ + ! Adjust the working buffer pointer in case of an odd ! + ! length column starting point. ! + \*--------------------------------------------------------*/ + if(rX0 % 2) + { + working_buffer++; + } + + /*--------------------------------------------------------*\ + ! Walk trough all the temporal and spatial slices as well ! + ! as rows. ! + \*--------------------------------------------------------*/ + #if defined(_OPENMP) + #pragma omp for collapse(3) + #endif + for(t = 0; t < (rTS1 - rTS0); ++t) + { + for(z = 0; z < (rZ1 - rZ0); ++z) + { + for(y = 0; y < (rY1 - rY0); ++y) + { + /*--------------------------------------------------------*\ + ! Advance the data pointer to the next column. ! + \*--------------------------------------------------------*/ + data = parameter->data + y * incr_Y + z * incr_Z + t * incr_TS; + + /*--------------------------------------------------------*\ + ! In the event that the current column and resolution only ! + ! encompasses 1 value, the sample will remain unaltered. ! + ! In case of an odd starting point the sample will be ! + ! doubled. ! + \*--------------------------------------------------------*/ + if((rX1 - rX0) == 1) + { + if(rX0 & 2) + { + data[0].f /= 2; + } + continue; + } + + /*--------------------------------------------------------*\ + ! Fill the working buffer with the y-th tile parameter ! + ! column. ! + \*--------------------------------------------------------*/ + fill_inverse_buffer(data, &memory[id][filter_tapsX], rX0, rX1, incr_X); + + /*--------------------------------------------------------*\ + ! Apply the boundary extension on the working buffer ap- ! + ! propriate to the specified wavelet kernel. ! + \*--------------------------------------------------------*/ + boundary_extension[control->KernelX](&memory[id][filter_tapsX], rX0, rX1, filter_tapsX); + + /*--------------------------------------------------------*\ + ! Perform the inverse wavelet transform on the current ! + ! column. ! + \*--------------------------------------------------------*/ + inverse_wavelet_transform[control->KernelX](working_buffer, rX0, rX1); + + /*--------------------------------------------------------*\ + ! Copy the decompressed flow field samples from the work- ! + ! ing buffer to the tile parameter memory. ! + \*--------------------------------------------------------*/ + buffer_flush_inverse(data, working_buffer, rX0, rX1, incr_X); + } + } + } + } + } + } + + /*--------------------------------------------------------*\ + ! Deallocate the memory array and memory blocks. ! + \*--------------------------------------------------------*/ + for(i = 0; i < nThreads; ++i) + { + free(memory[i]); + } + free(memory); + + return 0; +} \ No newline at end of file diff --git a/1-bwc/src/library/libbwc.c b/1-bwc/src/library/libbwc.c new file mode 100755 index 0000000..9970805 --- /dev/null +++ b/1-bwc/src/library/libbwc.c @@ -0,0 +1,4453 @@ +/*================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| DESCRIPTION: || +|| ------------ || +|| || +|| Big Whoop is a compression codec for the lossy compression of IEEE 754 floating || +|| point arrays defined on curvelinear compute grids. || +|| || +|| -------------------------------------------------------------------------------------------- || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are || +|| permitted provided that the following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of || +|| conditions and the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || +|| of conditions and the following disclaimer in the documentation and/or other || +|| materials provided with the distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS || +|| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF || +|| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE || +|| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, || +|| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF || +|| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) || +|| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || +|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, || +|| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*================================================================================================*/ +/************************************************************************************************************\ +|| _ _ _ ____ _ _ _ ___ ____ || +|| | |\ | | | | | | \ |___ || +|| | | \| |___ |___ |__| |__/ |___ || +|| || +\************************************************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bitstream.h" +#include "constants.h" +#include "macros.h" +#include "types.h" +#include "codestream.h" +#include "dwt.h" +#include "tier1.h" +#include "tier2.h" +#include "tagtree.h" + +/************************************************************************************************************\ +|| ___ ____ _ _ _ ____ ___ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || +|| |__] |__/ | | | |__| | |___ |___ | | |\ | | | | | | |\ | [__ || +|| | | \ | \/ | | | |___ | |__| | \| |___ | | |__| | \| ___] || +|| || +\************************************************************************************************************/ +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: uint8 initialize_precinct(bwc_field *const field, bwc_precinct *precinct, ! +! -------------- const uint32 dX, const uint32 dY, ! +! const uint32 dZ, const uint32 dTS) ! +! ! +! ! +! DESCRIPTION: ! +! ------------ ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! precinct bwc_precinct* - Structure defining a bwc precinct. ! +! ! +! dX, dY, dZ, dTS unsigned int(32 bit) - Defines the offset of the codeblock ! +! with regards to the current subband. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! unsigned int (8 bit) - Subband gain factor in log2 factor. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 24.05.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static uint8 +initialize_precinct(bwc_field *const field, bwc_precinct *precinct, const uint32 dX, const uint32 dY, + const uint32 dZ, const uint32 dTS) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 cb, cbSizeX, cbSizeY, cbSizeZ, cbSizeTS; + uint16 cb_X, cb_Y, cb_Z, cb_TS; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_prec_ctrl *prec_control; + bwc_prec_inf *prec_info; + bwc_codeblock *codeblock; + bwc_cblk_ctrl *cblk_control; + bwc_cblk_inf *cblk_info; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert(precinct); + + /*--------------------------------------------------------*\ + ! Save the global control as well as the precinct control ! + ! and info structure to temporary variables to make the ! + ! code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + + prec_control = &precinct->control; + prec_info = &precinct->info; + + /*--------------------------------------------------------*\ + ! Evaluate the global codeblock size for easy access. ! + \*--------------------------------------------------------*/ + cbSizeX = 1 << control->cbX ; + cbSizeY = 1 << control->cbY ; + cbSizeZ = 1 << control->cbZ ; + cbSizeTS = 1 << control->cbTS; + + /*--------------------------------------------------------*\ + ! Calculate the number of codeblock to cover precinct p in ! + ! subband s according to the corresponding equation from ! + ! JPEG2000 by D. S. Taubman and M. W. Marcellin (p.462). ! + \*--------------------------------------------------------*/ + prec_control->numCbX = (uint16)((prec_info->X0 == prec_info->X1) ? 0 : (ceil((float)prec_info->X1 /cbSizeX) - + floor((float)prec_info->X0 / cbSizeX))); + prec_control->numCbY = (uint16)((prec_info->Y0 == prec_info->Y1) ? 0 : (ceil((float)prec_info->Y1 /cbSizeY) - + floor((float)prec_info->Y0 / cbSizeY))); + prec_control->numCbZ = (uint16)((prec_info->Z0 == prec_info->Z1) ? 0 : (ceil((float)prec_info->Z1 /cbSizeZ) - + floor((float)prec_info->Z0 / cbSizeZ))); + prec_control->numCbTS = (uint16)((prec_info->TS0 == prec_info->TS1) ? 0 : (ceil((float)prec_info->TS1/cbSizeTS)- + floor((float)prec_info->TS0/ cbSizeTS))); + + prec_control->number_of_codeblocks = (uint64)prec_control->numCbX * prec_control->numCbY * prec_control->numCbZ * prec_control->numCbTS; + + /*--------------------------------------------------------*\ + ! Evaluate if the current precinct features any codeblocks.! + \*--------------------------------------------------------*/ + if(prec_control->number_of_codeblocks) + { + /*--------------------------------------------------------*\ + ! Initialize the msbs and inclusion tagtree for the cur- ! + ! rent precinct. ! + \*--------------------------------------------------------*/ + prec_control->tag_msbs = initialize_tagtree(prec_control->numCbX, prec_control->numCbY, + prec_control->numCbZ, prec_control->numCbTS); + prec_control->tag_inclusion = initialize_tagtree(prec_control->numCbX, prec_control->numCbY, + prec_control->numCbZ, prec_control->numCbTS); + + /*--------------------------------------------------------*\ + ! Allocate, walk through and setup the codeblock structure ! + ! according to the specified compression parameters. ! + \*--------------------------------------------------------*/ + precinct->codeblock = calloc(prec_control->number_of_codeblocks, sizeof(bwc_codeblock)); + if(!precinct->codeblock) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + for(cb_TS = 0, cb = 0; cb_TS < prec_control->numCbTS; ++cb_TS) + { + for(cb_Z = 0; cb_Z < prec_control->numCbZ; ++cb_Z) + { + for(cb_Y = 0; cb_Y < prec_control->numCbY; ++cb_Y) + { + for(cb_X = 0; cb_X < prec_control->numCbX; ++cb_X, ++cb) + { + /*--------------------------------------------------------*\ + ! Allocate the info and control structure for the current ! + ! codeblock. ! + \*--------------------------------------------------------*/ + codeblock = &precinct->codeblock[cb]; + codeblock->encoded_block = calloc(1, sizeof(bwc_encoded_cblk)); + if(!codeblock->encoded_block) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + cblk_info = &codeblock->info; + cblk_control = &codeblock->control; + + /*--------------------------------------------------------*\ + ! Allocate the memory block used to store the coding pass ! + ! contributions for the specified quality layers and setup ! + ! the pointer used to access the integer array. ! + \*--------------------------------------------------------*/ + cblk_control->memory = calloc(control->nLayers + 1, sizeof(int16)); + if(!cblk_control->memory) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + cblk_control->cp_contr = &cblk_control->memory[1]; + + cblk_control->beta = 3; + cblk_control->beta_est = 3; + + /*--------------------------------------------------------*\ + ! Calculate the boundaries for the current codeblock ac- ! + ! cording to the corresponding equation from JPEG2000 by ! + ! David S. Taubman and Michael W. Marcellin (p.460). ! + \*--------------------------------------------------------*/ + cblk_info->X0 = dX + (uint32)MAX(prec_info->X0 , cbSizeX * (cb_X + (uint32)floor((float)prec_info->X0 / cbSizeX ))); + cblk_info->Y0 = dY + (uint32)MAX(prec_info->Y0 , cbSizeY * (cb_Y + (uint32)floor((float)prec_info->Y0 / cbSizeY ))); + cblk_info->Z0 = dZ + (uint32)MAX(prec_info->Z0 , cbSizeZ * (cb_Z + (uint32)floor((float)prec_info->Z0 / cbSizeZ ))); + cblk_info->TS0 = dTS + (uint16)MAX(prec_info->TS0, cbSizeTS * (cb_TS + (uint32)floor((float)prec_info->TS0/ cbSizeTS))); + cblk_info->X1 = dX + (uint32)MIN(prec_info->X1 , cbSizeX * (cb_X + (uint32)floor((float)prec_info->X0 / cbSizeX ) + 1)); + cblk_info->Y1 = dY + (uint32)MIN(prec_info->Y1 , cbSizeY * (cb_Y + (uint32)floor((float)prec_info->Y0 / cbSizeY ) + 1)); + cblk_info->Z1 = dZ + (uint32)MIN(prec_info->Z1 , cbSizeZ * (cb_Z + (uint32)floor((float)prec_info->Z0 / cbSizeZ ) + 1)); + cblk_info->TS1 = dTS + (uint16)MIN(prec_info->TS1, cbSizeTS * (cb_TS + (uint32)floor((float)prec_info->TS0/ cbSizeTS) + 1)); + } + } + } + } + } + return 0; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: uint8 subband_gain(const uint8 highband_flag) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function calculates the gain for a specific subband in log2 format according to the ! +! number of applied 1-D wavelet transforms. The subband gain is calculated by evaluating the ! +! hamming weight of the highband flag. (see https://en.wikipedia.org/wiki/Hamming_weight) ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! highband_flag unsigned in (8 bit) - Flag defining the number and types of ! +! 1-D wavelet of transforms applied to ! +! the subband. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! unsigned int (8 bit) - Subband gain factor in log2 factor. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 15.05.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static uint8 subband_gain(const uint8 highband_flag) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint8 temp; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(highband_flag <= DIM_ALL); + + /*--------------------------------------------------------*\ + ! Save the highband flag in a temporary variable. ! + \*--------------------------------------------------------*/ + temp = highband_flag; + + /*--------------------------------------------------------*\ + ! Calculate the subband gain according to the number of ! + ! applied 1-D wavelet transforms. ! + \*--------------------------------------------------------*/ + temp -= (temp >> 1) & 0x55; + temp = (temp & 0x33) + ((temp >> 2) & 0x33); + return (temp + (temp >> 4)) & 0x0F; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: uchar initialize_subband(bwc_field *const field, bwc_parameter *const parameter, ! +! -------------- bwc_resolution *const resolution, ! +! bwc_subband *const subband, ! +! int32 resolution_level, ! +! int16 highband_flag) ! +! ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function initializes the bwc_subband structure with all necessary standard parameters ! +! to (de)compress a floating point array with nX * nY * nZ grid points, nTS timesteps and ! +! nPar parameters. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! parameter bwc_parameter* - Structure defining a bwc tile parameter.! +! ! +! resolution bwc_resolution* - Structure defining a bwc resolution ! +! level. ! +! ! +! subband bwc_subband* - Structure defining a bwc subband. ! +! ! +! resolution_level signed int(32 bit) - Defines the current resolution level. ! +! ! +! highband_flag signed int(16 bit) - Defines the type of highband the cur- ! +! rent subband represents. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! uchar - Returns an unsigned char for error handling. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 12.12.2017 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static uchar +initialize_subband(bwc_field *const field, bwc_parameter *const parameter, bwc_resolution *const resolution, + bwc_subband *const subband, + int32 resolution_level, + int16 highband_flag) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 p, pSizeX, pSizeY, pSizeZ, pSizeTS; + uint64 sb_sX, sb_sY, sb_sZ, sb_sTS; + uint32 Rb; + uint16 p_X, p_Y, p_Z, p_TS; + int8 decomp_level; + int8 level_X, level_Y, level_Z, level_TS; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_param_ctrl *param_control; + bwc_param_inf *param_info; + bwc_res_ctrl *res_control; + bwc_res_inf *res_info; + bwc_subb_ctrl *subb_control; + bwc_subb_inf *subb_info; + bwc_prec_ctrl *prec_control; + bwc_prec_inf *prec_info; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert(resolution); + assert(subband); + assert(resolution_level <= field->control.nDecomp + 1); + assert(highband_flag <= DIM_ALL); + + /*--------------------------------------------------------*\ + ! Save the global, parameter, resolution and subband con- ! + ! trol and info structures to temporary variables to make ! + ! the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + + param_control = ¶meter->control; + param_info = ¶meter->info; + + res_control = &resolution->control; + res_info = &resolution->info; + + subb_control = &subband->control; + subb_info = &subband->info; + + /*--------------------------------------------------------*\ + ! Evaluate the number of decompositions in each temporal & ! + ! spatial directions according to the the global decompo - ! + ! sition level for which the subband is initialized. ! + \*--------------------------------------------------------*/ + decomp_level = control->nDecomp - resolution_level + 1; + + level_X = (decomp_level > control->decompX ) ? control->decompX : decomp_level; + level_Y = (decomp_level > control->decompY ) ? control->decompY : decomp_level; + level_Z = (decomp_level > control->decompZ ) ? control->decompZ : decomp_level; + level_TS = (decomp_level > control->decompTS) ? control->decompTS : decomp_level; + + /*--------------------------------------------------------*\ + ! Calculate the boundaries for the current subband accord- ! + ! ing to the corresponding equation from JPEG2000 by David ! + ! S. Taubman and Michael W. Marcellin (p.460). ! + \*--------------------------------------------------------*/ + subb_info->X0 = (uint64)ceil( ((float)param_info->X0 / (1 << level_X)) - 0.5 * ((highband_flag & DIM_X) >> 0)); + subb_info->Y0 = (uint64)ceil( ((float)param_info->Y0 / (1 << level_Y)) - 0.5 * ((highband_flag & DIM_Y) >> 1)); + subb_info->Z0 = (uint64)ceil( ((float)param_info->Z0 / (1 << level_Z)) - 0.5 * ((highband_flag & DIM_Z) >> 2)); + subb_info->TS0 = (uint16)ceil( ((float)param_info->TS0 / (1 << level_TS)) - 0.5 * ((highband_flag & DIM_TS) >> 3)); + subb_info->X1 = (uint64)ceil( ((float)param_info->X1 / (1 << level_X)) - 0.5 * ((highband_flag & DIM_X) >> 0)); + subb_info->Y1 = (uint64)ceil( ((float)param_info->Y1 / (1 << level_Y)) - 0.5 * ((highband_flag & DIM_Y) >> 1)); + subb_info->Z1 = (uint64)ceil( ((float)param_info->Z1 / (1 << level_Z)) - 0.5 * ((highband_flag & DIM_Z) >> 2)); + subb_info->TS1 = (uint16)ceil( ((float)param_info->TS1 / (1 << level_TS)) - 0.5 * ((highband_flag & DIM_TS) >> 3)); + + /*--------------------------------------------------------*\ + ! Evaluate the dynamic range (Rb) of the current subband. ! + \*--------------------------------------------------------*/ + Rb = PREC_BIT + subband_gain(highband_flag); + + /*--------------------------------------------------------*\ + ! Save the highband flag in the subband control structure ! + ! and evaluate the energy gain factor for the current sub- ! + ! band. ! + \*--------------------------------------------------------*/ + subb_control->highband_flag = highband_flag; + subb_info->dwt_gain = get_dwt_energy_gain(field, highband_flag, decomp_level); + + /*--------------------------------------------------------*\ + ! Evaluate the quantization exponent, mantissa, step size ! + ! and effective step size according to the specified quan- ! + ! tization style. ! + \*--------------------------------------------------------*/ + if(control->quantization_style == bwc_qt_none) + { + /*--------------------------------------------------------*\ + ! If no quantization is wanted the mantissa is set to 0 ! + ! while the exponent is set to the dynamic range of the ! + ! subband in order to obtain a step size of 1. ! + \*--------------------------------------------------------*/ + subb_control->qt_exponent = (uint8) Rb; + subb_control->qt_mantissa = (uint16) 0; + subb_control->qt_step_size = 1; + subb_control->qt_effective_step_size = 1; + } + else + { + /*--------------------------------------------------------*\ + ! For a derrived quantization style the exponent is a- ! + ! dapted to the current resolution level and the (effec- ! + ! tive) step size is evaluated according to equation ! + ! (10.26) from JPEG2000 by David S. Taubman and Michael ! + ! W. Marcellin (p.439). ! + \*--------------------------------------------------------*/ + subb_control->qt_exponent = (uint8) control->qt_exponent + ((resolution_level == 0) ? 0 : 1 - resolution_level); + subb_control->qt_mantissa = (uint16) control->qt_mantissa; + subb_control->qt_step_size = (1.0f + ((double)subb_control->qt_mantissa / (1 << 11))) / pow(2,subb_control->qt_exponent); + subb_control->qt_effective_step_size = (1.0f + ((double)subb_control->qt_mantissa / (1 << 11))); + if(subb_control->qt_exponent > Rb) + { + subb_control->qt_effective_step_size /= pow(2,subb_control->qt_exponent - Rb); + } + else + { + subb_control->qt_effective_step_size *= pow(2,Rb - subb_control->qt_exponent); + } + } + + /*--------------------------------------------------------*\ + ! Evaluate the dynamic range of the subband after the ! + ! transformation stage. ! + \*--------------------------------------------------------*/ + subb_control->Kmax = MAX(0, control->guard_bits + subb_control->qt_exponent - 1); + + /*--------------------------------------------------------*\ + ! Evaluate the global precinct size for easy access. ! + \*--------------------------------------------------------*/ + pSizeX = 1 << control->precSizeX; + pSizeY = 1 << control->precSizeY; + pSizeZ = 1 << control->precSizeZ; + pSizeTS = 1 << control->precSizeTS; + + /*--------------------------------------------------------*\ + ! Evaluate the start coordinates for the current subband. ! + \*--------------------------------------------------------*/ + sb_sX = (highband_flag & DIM_X) ? (parameter->resolution[resolution_level - 1].info.X1 - + parameter->resolution[resolution_level - 1].info.X0 ) : 0; + sb_sY = (highband_flag & DIM_Y) ? (parameter->resolution[resolution_level - 1].info.Y1 - + parameter->resolution[resolution_level - 1].info.Y0 ) : 0; + sb_sZ = (highband_flag & DIM_Z) ? (parameter->resolution[resolution_level - 1].info.Z1 - + parameter->resolution[resolution_level - 1].info.Z0 ) : 0; + sb_sTS = (highband_flag & DIM_TS) ? (parameter->resolution[resolution_level - 1].info.TS1 - + parameter->resolution[resolution_level - 1].info.TS0) : 0; + + /*--------------------------------------------------------*\ + ! Evaluate if the current resolution level features any ! + ! precincts. ! + \*--------------------------------------------------------*/ + if(res_control->number_of_precincts) + { + /*--------------------------------------------------------*\ + ! Allocate, walk through and setup the precinct structure ! + ! according to the specified compression parameters. ! + \*--------------------------------------------------------*/ + subband->precinct = calloc(res_control->number_of_precincts, sizeof(bwc_precinct)); + if(!subband->precinct) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + for(p_TS = 0, p = 0; p_TS < res_control->numPTS; ++p_TS) + { + for(p_Z = 0; p_Z < res_control->numPZ; ++p_Z) + { + for(p_Y = 0; p_Y < res_control->numPY; ++p_Y) + { + for(p_X = 0; p_X < res_control->numPX; ++p_X, ++p) + { + /*--------------------------------------------------------*\ + ! Save the precinct info and control structure to tempo- ! + ! rary variables to make the code more readable. ! + \*--------------------------------------------------------*/ + prec_control = &subband->precinct[p].control; + prec_info = &subband->precinct[p].info; + + /*--------------------------------------------------------*\ + ! Calculate the boundaries for the current precinct accord-! + ! ing to the corresponding equation from JPEG2000 by David ! + ! S. Taubman and Michael W. Marcellin (p.460). ! + \*--------------------------------------------------------*/ + prec_info->X0 = (uint32)MAX(res_info->X0 , pSizeX * (p_X + (uint32)floor(res_info->X0 / pSizeX))); + prec_info->Y0 = (uint32)MAX(res_info->Y0 , pSizeY * (p_Y + (uint32)floor(res_info->Y0 / pSizeY))); + prec_info->Z0 = (uint32)MAX(res_info->Z0 , pSizeZ * (p_Z + (uint32)floor(res_info->Z0 / pSizeZ))); + prec_info->TS0 = (uint16)MAX(res_info->TS0, pSizeTS * (p_TS + (uint32)floor(res_info->TS0/ pSizeTS))); + prec_info->X1 = (uint32)MIN(res_info->X1 , pSizeX * (p_X + (uint32)floor(res_info->X0 / pSizeX) + 1)); + prec_info->Y1 = (uint32)MIN(res_info->Y1 , pSizeY * (p_Y + (uint32)floor(res_info->Y0 / pSizeY) + 1)); + prec_info->Z1 = (uint32)MIN(res_info->Z1 , pSizeZ * (p_Z + (uint32)floor(res_info->Z0 / pSizeZ) + 1)); + prec_info->TS1 = (uint16)MIN(res_info->TS1, pSizeTS * (p_TS + (uint32)floor(res_info->TS0/ pSizeTS)+ 1)); + + if((control->nDecomp - control->decompX) < resolution_level) + { + prec_info->X0 = (uint32) ceil(((float)prec_info->X0 / 2) - 0.5 * ((highband_flag & DIM_X) >> 0)); + prec_info->X1 = (uint32) ceil(((float)prec_info->X1 / 2) - 0.5 * ((highband_flag & DIM_X) >> 0)); + } + + if((control->nDecomp - control->decompY) < resolution_level) + { + prec_info->Y0 = (uint32) ceil(((float)prec_info->Y0 / 2) - 0.5 * ((highband_flag & DIM_Y) >> 1)); + prec_info->Y1 = (uint32) ceil(((float)prec_info->Y1 / 2) - 0.5 * ((highband_flag & DIM_Y) >> 1)); + } + + if((control->nDecomp - control->decompZ) < resolution_level) + { + prec_info->Z0 = (uint32) ceil(((float)prec_info->Z0 / 2) - 0.5 * ((highband_flag & DIM_Z) >> 2)); + prec_info->Z1 = (uint32) ceil(((float)prec_info->Z1 / 2) - 0.5 * ((highband_flag & DIM_Z) >> 2)); + } + + if((control->nDecomp - control->decompTS) < resolution_level) + { + prec_info->TS0 = (uint16) ceil(((float)prec_info->TS0 / 2) - 0.5 * ((highband_flag & DIM_TS) >> 3)); + prec_info->TS1 = (uint16) ceil(((float)prec_info->TS1 / 2) - 0.5 * ((highband_flag & DIM_TS) >> 3)); + } + + /*--------------------------------------------------------*\ + ! Initialize the precinct structure according to the speci-! + ! fied compression parameters. ! + \*--------------------------------------------------------*/ + initialize_precinct(field, &subband->precinct[p], (uint32)sb_sX - subb_info->X0, (uint32)sb_sY - subb_info->Y0, + (uint32)sb_sZ - subb_info->Z0, (uint32)sb_sTS - subb_info->TS0); + + /*--------------------------------------------------------*\ + ! Update the number of codeblocks for the current parame- ! + ! ter. ! + \*--------------------------------------------------------*/ + param_control->number_of_codeblocks += prec_control->number_of_codeblocks; + } + } + } + } + } + return 0; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void bwc_header_append_aux(bwc_field *const field, bwc_stream *const aux) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function amends the main header for the compressed codestream with an auxiliary ! +! information block. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! aux unsigned char* - Memory handle for the auxiliary infor- ! +! mation block. ! +! ! +! size unsigned int(32 bit) - Size of the auxiliary information block.! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! uchar - Returns an unsigned char for error handling. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 12.04.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static uchar +header_append_aux(bwc_field *const field, bwc_stream *const aux) +{ + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert(aux); + + /*--------------------------------------------------------*\ + ! Save the global control and info structure to temporary ! + ! variables to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + + /*--------------------------------------------------------*\ + ! Check if the main header is already defined in the field ! + ! structure. ! + \*--------------------------------------------------------*/ + if(!control->header.memory) + { + fprintf(stderr,"o==========================================================o\n"\ + "| ERROR: Main header not defined |\n"\ + "| |\n"\ + "| Unable to append auxiliary information since the |\n"\ + "| main header has not yet been created. Appending |\n"\ + "| information to the end of the main header can |\n"\ + "| only be done after the bwc_create_compression |\n"\ + "| function has been called. |\n"\ + "| |\n"\ + "o==========================================================o\n"); + + return 1; + } + + /*--------------------------------------------------------*\ + ! Check if the main header would exceed the maximum number ! + ! of allowable bits after appending the auxiliary ! + ! information. ! + \*--------------------------------------------------------*/ + if(((uint64)control->header.size + aux->size) >= 0xFFFFFFFF) + { + fprintf(stderr,"o==========================================================o\n"\ + "| ERROR: Main header exceeds maximum size limit |\n"\ + "| |\n"\ + "| Appending the auxiliary information to the main |\n"\ + "| header would exceed its maximum size limit of |\n"\ + "| 4294967295 bytes. |\n"\ + "| |\n"\ + "o==========================================================o\n"); + + return 1; + } + + if(codestream_write_aux(&control->header, aux)) + { + return 1; + } + + return 0; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void bwc_header_append_com(bwc_field *const field, bwc_stream *const com) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function amends the main header for the compressed codestream with a comment ! +! block. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! com unsigned char* - Memory handle for the auxiliary infor- ! +! mation block. ! +! ! +! size unsigned int(32 bit) - Size of the auxiliary information block.! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! uchar - Returns an unsigned char for error handling. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 12.04.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static uchar +header_append_com(bwc_field *const field, bwc_stream *const com) +{ + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + + /*--------------------------------------------------------*\ + ! Save the global control and info structure to temporary ! + ! variables to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + + /*--------------------------------------------------------*\ + ! Check if the main header is already defined in the field ! + ! structure. ! + \*--------------------------------------------------------*/ + if(!control->header.memory) + { + fprintf(stderr,"o==========================================================o\n"\ + "| ERROR: Main header not defined |\n"\ + "| |\n"\ + "| Unable to append auxiliary information since the |\n"\ + "| main header has not yet been created. Appending |\n"\ + "| information to the end of the main header can |\n"\ + "| only be done after the bwc_create_compression |\n"\ + "| function has been called. |\n"\ + "| |\n"\ + "o==========================================================o\n"); + + return 1; + } + + /*--------------------------------------------------------*\ + ! Check if the main header would exceed the maximum number ! + ! of allowable bits after appending the auxiliary ! + ! information. ! + \*--------------------------------------------------------*/ + if(((uint64)control->header.size + com->size) >= 0xFFFFFFFF) + { + fprintf(stderr,"o==========================================================o\n"\ + "| ERROR: Main header exceeds maximum size limit |\n"\ + "| |\n"\ + "| Appending the auxiliary information to the main |\n"\ + "| header would exceed its maximum size limit of |\n"\ + "| 4294967295 bytes. |\n"\ + "| |\n"\ + "o==========================================================o\n"); + + return 1; + } + + if(codestream_write_com(&control->header, com)) + { + return 1; + } + + return 0; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void fill_buffer(bwc_field *const field, bwc_tile *const tile, ! +! ------------ bwc_parameter *const parameter, ! +! bwc_sample *const working_buffer, ! +! double *const data, ! +! uint64 param_size, ! +! uint16 param_id) ! +! ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is used to fill the working buffer with the appropriate flow field data for ! +! the specified tile parameter. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! tile bwc_tile* - Structure defining a bwc tile. ! +! ! +! parameter bwc_parameter* - Structure defining a bwc parameter. ! +! ! +! working_buffer bwc_sample* - Working buffer used to store flow field ! +! data for a specific tile parameter. ! +! ! +! param_size uint64 - Specifies the byte size of one tile ! +! parameter. ! +! ! +! parameter uint16 - Specifies the parameter index for the ! +! current tile parameter. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 22.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +fill_buffer(bwc_field *const field, bwc_tile *const tile, bwc_parameter *const parameter, + bwc_sample *const working_buffer, + bwc_data *const data, + uint16 param_id) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 width, height, depth, dt; + uint64 param_offset; + uint64 x, y, z; + uint16 t; + + /*-----------------------*\ + ! DEFINE FLOAT VARIABLES: ! + \*-----------------------*/ + bwc_float max, min; + double *src_d, *tmp_d; + float *src_f, *tmp_f; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_sample *dest; + bwc_gl_inf *info; + bwc_tile_inf *tile_info; + bwc_param_ctrl *param_control; + bwc_param_inf *param_info; + bwc_cmd_opts_ll *param; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert(tile); + assert(parameter); + assert(working_buffer); + assert(data); + + /*--------------------------------------------------------*\ + ! Save the global, tile and parameter control and info ! + ! structures to temporary variables to make the code more ! + ! readable. ! + \*--------------------------------------------------------*/ + info = field->info; + + tile_info = &tile->info; + + param_control = ¶meter->control; + param_info = ¶meter->info; + + /*--------------------------------------------------------*\ + ! Calculate the offset of the current parameter in the da- ! + ! ta array. ! + \*--------------------------------------------------------*/ + param_offset = 0; + param = data->info.parameter->root; + + while(param != NULL && param->id < param_id) + { + if(param->precision == param_info->precision) + { + param_offset += param->size; + } + param = param -> next; + } + + /*--------------------------------------------------------*\ + ! Associate the working buffer with the data pointer in ! + ! the bwc_parameter structure. ! + \*--------------------------------------------------------*/ + parameter->data = working_buffer; + + /*--------------------------------------------------------*\ + ! Initialize the maximum and minimum parameter value. ! + \*--------------------------------------------------------*/ + max = param_info->parameter_max; + min = param_info->parameter_min; + + /*--------------------------------------------------------*\ + ! Calculate the width, height, depth and dt of the current ! + ! tile parameter. ! + \*--------------------------------------------------------*/ + width = param_info->X1 - param_info->X0; + height = param_info->Y1 - param_info->Y0; + depth = param_info->Z1 - param_info->Z0; + dt = param_info->TS1 - param_info->TS0; + + /*--------------------------------------------------------*\ + ! Check if the parameter is single or double precision and ! + ! handle the field accordingly. ! + \*--------------------------------------------------------*/ + if(param_info->precision == 8) + { + /*--------------------------------------------------------*\ + ! Safe the field pointer to a temporary variable to make ! + ! the code more readable. ! + \*--------------------------------------------------------*/ + tmp_d = data->field.d; + + /*--------------------------------------------------------*\ + ! Walk through the tile parameter working buffer. ! + \*--------------------------------------------------------*/ + #if defined(_OPENMP) + #pragma omp parallel for collapse(3) private(dest, src_d, x) reduction(max:max) reduction(min:min) + #endif + for(t = 0; t < dt; ++t) + { + for(z = 0; z < depth; ++z) + { + for(y = 0; y < height; ++y) + { + /*--------------------------------------------------------*\ + ! Advance the temporary data and buffer pointers to their ! + ! appropriate positions in the working buffer and data ! + ! arrays. ! + \*--------------------------------------------------------*/ + src_d = &tmp_d[param_offset + tile_info->X0 + info->nX * + (tile_info->Y0 + y + info->nY * + (tile_info->Z0 + z + info->nZ * t))]; + + dest = &working_buffer[(uint64) width * (y + height * (z + depth * t))]; + + for(x = 0; x < width; ++x) + { + /*--------------------------------------------------------*\ + ! Copy the data sample to the working buffer. ! + \*--------------------------------------------------------*/ + dest[x].f = (bwc_float)src_d[x]; + + /*--------------------------------------------------------*\ + ! Update the maximum and minimum parameter value. ! + \*--------------------------------------------------------*/ + max = MAX(max, dest[x].f); + min = MIN(min, dest[x].f); + } + } + } + } + } + else + { + /*--------------------------------------------------------*\ + ! Safe the field pointer to a temporary variable to make ! + ! the code more readable. ! + \*--------------------------------------------------------*/ + tmp_f = data->field.f; + + /*--------------------------------------------------------*\ + ! Walk through the tile parameter working buffer. ! + \*--------------------------------------------------------*/ + #if defined(_OPENMP) + #pragma omp parallel for collapse(3) private(dest, src_f, x) reduction(max:max) reduction(min:min) + #endif + for(t = 0; t < dt; ++t) + { + for(z = 0; z < depth; ++z) + { + for(y = 0; y < height; ++y) + { + /*--------------------------------------------------------*\ + ! Advance the temporary data and buffer pointers to their ! + ! appropriate positions in the working buffer and data ! + ! arrays. ! + \*--------------------------------------------------------*/ + src_f = &tmp_f[param_offset + tile_info->X0 + info->nX * + (tile_info->Y0 + y + info->nY * + (tile_info->Z0 + z + info->nZ * t))]; + + dest = &working_buffer[(uint64) width * (y + height * (z + depth * t))]; + + for(x = 0; x < width; ++x) + { + /*--------------------------------------------------------*\ + ! Copy the data sample to the working buffer. ! + \*--------------------------------------------------------*/ + dest[x].f = (bwc_float)src_f[x]; + + /*--------------------------------------------------------*\ + ! Update the maximum and minimum parameter value. ! + \*--------------------------------------------------------*/ + max = MAX(max, dest[x].f); + min = MIN(min, dest[x].f); + } + } + } + } + } + + /*--------------------------------------------------------*\ + ! Update the maximum and minimum parameter value in the ! + ! parameter structure. ! + \*--------------------------------------------------------*/ + param_info->parameter_max = max; + param_info->parameter_min = min; + + /*--------------------------------------------------------*\ + ! Calculate the constants used to normalize the tile pa- ! + ! rameter to the range of [-1,1). ! + \*--------------------------------------------------------*/ + param_control->alpha = (param_info->parameter_max + param_info->parameter_min)/2.0f; + param_control->beta = 2.0f/(param_info->parameter_max - param_info->parameter_min); +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void fill_buffer(bwc_field *const field, bwc_tile *const tile, ! +! ------------ bwc_parameter *const parameter, ! +! bwc_sample *const working_buffer, ! +! double *const data, ! +! uint64 param_size, ! +! uint16 param_id) ! +! ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is used to flush the working buffer to the flow field data memory block. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! tile bwc_tile* - Structure defining a bwc tile. ! +! ! +! parameter bwc_parameter* - Structure defining a bwc parameter. ! +! ! +! working_buffer bwc_sample* - Working buffer used to store flow field ! +! data for a specific tile parameter. ! +! ! +! param_size uint64 - Specifies the byte size of one tile ! +! parameter. ! +! ! +! parameter uint16 - Specifies the parameter index for the ! +! current tile parameter. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 22.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +flush_buffer(bwc_field *const field, bwc_tile *const tile, bwc_parameter *const parameter, + bwc_sample *const working_buffer, + bwc_data *const data, + uint16 param_id) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 width, height, depth, dt; + uint64 nX, nY, nZ; + uint64 param_offset; + uint64 x, y, z; + uint16 t; + + /*-----------------------*\ + ! DEFINE FLOAT VARIABLES: ! + \*-----------------------*/ + double *dst_d, *tmp_d; + float *dst_f, *tmp_f; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_sample *src; + bwc_gl_inf *info; + bwc_param_ctrl *param_control; + bwc_param_inf *param_info; + bwc_cmd_opts_ll *param; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert(tile); + assert(parameter); + assert(working_buffer); + assert(data); + + /*--------------------------------------------------------*\ + ! Save the global, tile and parameter control and info ! + ! structures to temporary variables to make the code more ! + ! readable. ! + \*--------------------------------------------------------*/ + info = field->info; + + param_control = ¶meter->control; + param_info = ¶meter->info; + + nX = info->nX; + nY = info->nY; + nZ = info->nZ; + + /*--------------------------------------------------------*\ + ! Calculate the offset of the current parameter in the da- ! + ! ta array. ! + \*--------------------------------------------------------*/ + param_offset = 0; + param = data->info.parameter->root; + + while(param != NULL && param->id < param_id) + { + if(param->precision == param_info->precision) + { + param_offset += param->size; + } + param = param -> next; + } + + /*--------------------------------------------------------*\ + ! Calculate the width, height, depth and dt of the current ! + ! tile parameter. ! + \*--------------------------------------------------------*/ + width = param_info->X1 - param_info->X0; + height = param_info->Y1 - param_info->Y0; + depth = param_info->Z1 - param_info->Z0; + dt = param_info->TS1 - param_info->TS0; + + /*--------------------------------------------------------*\ + ! Check if the parameter is single or double precision and ! + ! handle the field accordingly. ! + \*--------------------------------------------------------*/ + if(param_info->precision == 8) + { + /*--------------------------------------------------------*\ + ! Safe the field pointer to a temporary variable to make ! + ! the code more readable. ! + \*--------------------------------------------------------*/ + tmp_d = data->field.d; + + /*--------------------------------------------------------*\ + ! Walk through the tile parameter working buffer. ! + \*--------------------------------------------------------*/ + #if defined(_OPENMP) + #pragma omp parallel for collapse(3) private(dst_d, src, x) + #endif + for(t = 0; t < dt; ++t) + { + for(z = 0; z < depth; ++z) + { + for(y = 0; y < height; ++y) + { + /*--------------------------------------------------------*\ + ! Advance the temporary data and buffer pointers to their ! + ! appropriate positions in the working buffer and data ! + ! arrays. ! + \*--------------------------------------------------------*/ + dst_d = &tmp_d[param_offset + param_info->X0 + nX * + (param_info->Y0 + y + nY * + (param_info->Z0 + z + nZ * t ))]; + + src = &working_buffer[(uint64) width * (y + height * (z + depth * t))]; + + for(x = 0; x < width; ++x) + { + /*--------------------------------------------------------*\ + ! Copy the sample to the data memory block. ! + \*--------------------------------------------------------*/ + dst_d[x] = (double)src[x].f; + } + } + } + } + } + else + { + /*--------------------------------------------------------*\ + ! Safe the field pointer to a temporary variable to make ! + ! the code more readable. ! + \*--------------------------------------------------------*/ + tmp_f = data->field.f; + + /*--------------------------------------------------------*\ + ! Walk through the tile parameter working buffer. ! + \*--------------------------------------------------------*/ + #if defined(_OPENMP) + #pragma omp parallel for collapse(3) private(dst_f, src, x) + #endif + for(t = 0; t < dt; ++t) + { + for(z = 0; z < depth; ++z) + { + for(y = 0; y < height; ++y) + { + /*--------------------------------------------------------*\ + ! Advance the temporary data and buffer pointers to their ! + ! appropriate positions in the working buffer and data ! + ! arrays. ! + \*--------------------------------------------------------*/ + dst_f = &tmp_f[param_offset + param_info->X0 + nX * + (param_info->Y0 + y + nY * + (param_info->Z0 + z + nZ * t ))]; + + src = &working_buffer[(uint64) width * (y + height * (z + depth * t))]; + + for(x = 0; x < width; ++x) + { + /*--------------------------------------------------------*\ + ! Copy the sample to the data memory block. ! + \*--------------------------------------------------------*/ + dst_f[x] = (float)src[x].f; + } + } + } + } + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void buff_normalize(bwc_field *const field, bwc_parameter *const parameter) ! +! ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is used to normalize the values v[i] of the current tile parameter to the ! +! range of [-1, 1) and scale them to a desired dynamic range: ! +! ! +! q[i] = [(v[i] - α)/β] * 2^Qm. ! +! ! +! Here, α and β define the normalization constants and Qm represents the dynamic range of ! +! the Q number format. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! parameter bwc_parameter* - Structure defining a bwc parameter. ! +! ! +! working_buffer bwc_sample* - Working buffer used to store flow field ! +! data for a specific tile parameter. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 24.10.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +normalize_param(bwc_field *const field, bwc_parameter *const parameter) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + bwc_raw shift; + uint64 param_size; + uint64 x; + + /*-----------------------*\ + ! DEFINE FLOAT VARIABLES: ! + \*-----------------------*/ + bwc_float alpha, beta; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_param_ctrl *param_control; + bwc_param_inf *param_info; + bwc_sample *tmp; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(parameter); + assert(parameter->data); + + /*--------------------------------------------------------*\ + ! Save the global control and the parameter control and ! + ! info structures to temporary variables to make the code ! + ! more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + + param_control = ¶meter->control; + param_info = ¶meter->info; + + /*--------------------------------------------------------*\ + ! Save the normalization constants to temporary variables ! + ! to make the code more readable. ! + \*--------------------------------------------------------*/ + alpha = param_control->alpha; + beta = param_control->beta; + + /*--------------------------------------------------------*\ + ! Calculate the size of the current tile parameter. ! + \*--------------------------------------------------------*/ + param_size = (param_info->X1 - param_info->X0) * + (param_info->Y1 - param_info->Y0) * + (param_info->Z1 - param_info->Z0) * + (param_info->TS1 - param_info->TS0); + + /*--------------------------------------------------------*\ + ! Associate the temporary pointer with the data pointer in ! + ! the bwc_parameter structure. ! + \*--------------------------------------------------------*/ + tmp = parameter->data; + + /*--------------------------------------------------------*\ + ! Shift the Q number range to the appropriate position for ! + ! the IEEE 754 floating point number. ! + \*--------------------------------------------------------*/ + shift = (uint64)control->Qm << PREC_MANTISSA; + + /*--------------------------------------------------------*\ + ! Walk through the tile parameter working buffer. ! + \*--------------------------------------------------------*/ + #if defined(_OPENMP) + #pragma omp parallel for + #endif + for(x = 0; x < param_size; ++x) + { + /*--------------------------------------------------------*\ + ! Normalize the flow field values to the range of [-1,1). ! + \*--------------------------------------------------------*/ + tmp[x].f = (bwc_float)(tmp[x].f - alpha) * beta; + + /*--------------------------------------------------------*\ + ! Scale the flow field values to the dynamic range speci- ! + ! fied by the Qm parameter. ! + \*--------------------------------------------------------*/ + tmp[x].raw += (((tmp[x].raw & EXPONENT) == 0)&& + ((tmp[x].raw & MANTISSA) == 0)) ? 0 : shift; + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void denormalize_param(bwc_field *const field, bwc_parameter *const parameter) ! +! ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is used to scale the decompressed values to their original dynamic range and ! +! denormalize the flow field values. ! +! ! +! q[i] = [(v[i]/2^Qm) * β] + α. ! +! ! +! Here, α and β define the normalization constants and Qm represents the dynamic range of ! +! the Q number format. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! parameter bwc_parameter* - Structure defining a bwc parameter. ! +! ! +! working_buffer bwc_sample* - Working buffer used to store flow field ! +! data for a specific tile parameter. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 24.10.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +denormalize_param(bwc_field *const field, bwc_parameter *const parameter) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + bwc_raw shift; + uint64 param_size; + uint64 x; + + /*-----------------------*\ + ! DEFINE FLOAT VARIABLES: ! + \*-----------------------*/ + bwc_float alpha, beta; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_param_inf *param_info; + bwc_sample *tmp; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(parameter); + assert(parameter->data); + + /*--------------------------------------------------------*\ + ! Save the global control and the parameter info struc- ! + ! tures to temporary variables to make the code more ! + ! readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + + param_info = ¶meter->info; + + /*--------------------------------------------------------*\ + ! Save the normalization constants to temporary variables ! + ! to make the code more readable. ! + \*--------------------------------------------------------*/ + alpha = (param_info->parameter_max + param_info->parameter_min)/2.0f; + beta = (param_info->parameter_max - param_info->parameter_min)/2.0f; + + /*--------------------------------------------------------*\ + ! Calculate the size of the current tile parameter. ! + \*--------------------------------------------------------*/ + param_size = (param_info->X1 - param_info->X0) * + (param_info->Y1 - param_info->Y0) * + (param_info->Z1 - param_info->Z0) * + (param_info->TS1 - param_info->TS0); + + /*--------------------------------------------------------*\ + ! Associate the temporary pointer with the data pointer in ! + ! the bwc_parameter structure. ! + \*--------------------------------------------------------*/ + tmp = parameter->data; + + /*--------------------------------------------------------*\ + ! Shift the Q number range to the appropriate position for ! + ! the IEEE 754 floating point number. ! + \*--------------------------------------------------------*/ + shift = (uint64)control->Qm << PREC_MANTISSA; + + /*--------------------------------------------------------*\ + ! Walk through the tile parameter working buffer. ! + \*--------------------------------------------------------*/ + #if defined(_OPENMP) + #pragma omp parallel for + #endif + for(x = 0; x < param_size; ++x) + { + /*--------------------------------------------------------*\ + ! Scale the flow field values to their original dynamic ! + ! range. ! + \*--------------------------------------------------------*/ + tmp[x].raw -= (((tmp[x].raw & EXPONENT) == 0)&& + ((tmp[x].raw & MANTISSA) == 0)) ? 0 : shift; + + /*--------------------------------------------------------*\ + ! Denormalize the flow field values. ! + \*--------------------------------------------------------*/ + tmp[x].f = (bwc_float)(tmp[x].f * beta) + alpha; + } +} + +/************************************************************************************************************\ +|| ___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || +|| |__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ || +|| | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] || +|| || +\************************************************************************************************************/ +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: bwc_field *bwc_initialize_data(...) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function initializes the bwc_data structure with all necessary parameters. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! nX ,nY, nZ unsigned int(64 bit) - Number of spatial Datapoints ! +! ! +! nTS unsigned int(16 bit) - Number of Timesteps. ! +! ! +! nPar unsigned int(8 bit) - Number of Parameters ! +! ! +! file_extension char* - File extension associated ! +! with the numerical dataset. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! bwc_data* - Structure used to store a numerical ! +! dataset/compressed bitstream. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 09.06.2021 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +bwc_data* +bwc_initialize_data(double* field, uint64 const nX, uint64 const nY, uint64 const nZ, uint16 const nTS, uint8 const nPar, char *file_extension) +{ + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_inf *info; + bwc_data *file; + + file = calloc(1, sizeof(bwc_data)); + if(!file) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return NULL; + } + + info = &file->info; + + info->nX = nX; + info->nY = nY; + info->nZ = nZ; + info->nTS = nTS; + info->nPar = nPar; + memcpy(&info->f_ext, file_extension, sizeof(char) * 19); + + file->field.d = field; + + return file; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void bwc_add_param(bwc_data* data, char *name, uint16 sample, uchar dim, uint8 precision) ! +! -------------- ! +! ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function initializes and adds new parameters to the parameter linked list. The linked ! +! list stores the parameter name, its precision, sampling factor and the dimension for which ! +! the sampling is active. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! name char* - Name of parameter(id). ! +! ! +! sample unsigned int(16 bit) - Sampling factor for parameter(id). ! +! ! +! dim unsigned char - Dimension(s) for which the sampling ! +! factor is active. ! +! ! +! precision unsigned int(8 bit) - Bit precision of the parameter. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 19.10.2017 Patrick Vogler B87D120 V 0.1.0 function created ! +! 03.12.2019 Patrick Vogler B87E7E4 V 0.1.0 redefined the function for the ! +! bwc_data structure. ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +bwc_add_param(bwc_data* data, char *name, uint8 precision) +{ + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_inf *info; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(data); + assert(dim <= DIM_ALL); + + /*--------------------------------------------------------*\ + ! Save the global info structure to a temporary variable ! + ! to make the code more readable. ! + \*--------------------------------------------------------*/ + info = &data->info; + + /*--------------------------------------------------------*\ + ! Check if the specified parameter name has the proper ! + ! length. ! + \*--------------------------------------------------------*/ + if((strlen(name) > 24) && name) + { + fprintf(stderr, "o==========================================================o\n"\ + "| WARNING: Invalid parameter name: %-24s|\n"\ + "| |\n"\ + "| Parameter names cannot exceed 24 characters. |\n"\ + "| |\n"\ + "o==========================================================o\n",name); + } + + /*--------------------------------------------------------*\ + ! Check if the parameter structure has already been allo- ! + ! cated. ! + \*--------------------------------------------------------*/ + if(info->parameter == NULL) + { + /*--------------------------------------------------------*\ + ! If the bwc_add_param function is called for the first ! + ! time, allocate the parameter structure and save the root ! + ! node address. ! + \*--------------------------------------------------------*/ + info->parameter = calloc(1, sizeof(bwc_cmd_opts_ll)); + info->parameter->root = info->parameter; + } + else + { + /*--------------------------------------------------------*\ + ! If a new parameter is added, allocate the nex linked ! + ! list node, save the root node address in its structure ! + ! and set the linked list access pointer to the new node. ! + \*--------------------------------------------------------*/ + info->parameter->next = calloc(1, sizeof(bwc_cmd_opts_ll)); + info->parameter->next->root = info->parameter->root; + info->parameter->next->id = info->parameter->id + 1; + info->parameter = info->parameter->next; + } + + /*--------------------------------------------------------*\ + ! Save the name of the new parameter its precision in the ! + ! structure of the new node. ! + \*--------------------------------------------------------*/ + strcpy(info->parameter->name, name ? name : "undefined"); + info->parameter->precision = precision ? precision : PREC_BYTE; + + /*--------------------------------------------------------*\ + ! Evaluate the parameter size the information in the ! + ! linked list. ! + \*--------------------------------------------------------*/ + info->parameter->size = (info->nX * info->nY * info->nZ * info->nTS); +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: bwc_field *bwc_initialize_data(...) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is used to copy the numerical dataset stored in the bwc_data ! +! structure to a user supplied memory block. A size argument is necessary ! +! to verify that the memory block has the correct size. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! data bwc_data* - Structure used to store a numerical ! +! dataset/compressed bitstream. ! +! ! +! buffer unsigned char* - Memory block supplied by ! +! the function caller. ! +! ! +! data bwc_data* - Size of memory block. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 09.06.2021 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +bwc_get_data(bwc_data* data, uchar* buffer, uint64 size) +{ + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_inf *info; + + info = &data->info; + + if(size != (uint64)(data->info.nX * data->info.nY * data->info.nZ * data->info.nTS * data->info.nPar)) + { + fprintf(stderr, "Incorrect buffer size\n"); + } + else + { + memcpy(buffer, data->field.d, size * sizeof(double)); + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void bwc_free_data(bwc_data* file) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function deallocates the data structure used to store an numerical dataset/compressed ! +! and can be called if an error occurs or once the data is no longer needed is to be closed. ! +! The deallocation will be carried out down to the structure levels that have been allocated. ! +! ! +! PARAMETERS: ! +! ----------- ! +! ! +! Variable Type Description ! +! -------- ---- ----------- ! +! file bwc_data - Defines a structure used to store all ! +! the relevant parameters and the data ! +! field of a numerical dataset or com- ! +! pressed codestream. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 20.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! 04.12.2019 Patrick Vogler B87E7E4 V 0.1.0 +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +bwc_free_data(bwc_data* data) +{ + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_cmd_opts_ll *param, *temp; + + if(data) + { + if(data->info.parameter) + { + param = data->info.parameter->root; + + while(param != NULL) + { + temp = param; + param = param -> next; + free(temp); + } + } + + if(data) + { + if(data->codestream.data) + { + release_packed_stream(data->codestream.data); + } + if(data->codestream.aux) + { + release_packed_stream(data->codestream.aux); + } + if(data->codestream.com) + { + release_packed_stream(data->codestream.com); + } + if(data->fp) + { + fclose(data->fp); + } + free(data->codestream.data); + free(data->codestream.aux); + free(data->codestream.com); + free(data->field.d); + free(data->field.f); + free(data); + } + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: uchar create_field(bwc_field *const field) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function creates the field structure used to (de)compress a floating point array de- ! +! fined by the bwc_initialize function. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! unsigned char - Returns an unsigned char for error handling. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 15.03.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uchar +create_field(bwc_field *const field) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 cblk, nPackets; + uint32 num_tiles_X, num_tiles_Y, num_tiles_Z, num_tiles_TS; + uint32 c, i, p, t, x, y, z; + uint32 max_Prec; + int16 r; + uint8 j; + int8 l,m, n; + + /*-----------------------*\ + ! DEFINE CHAR VARIABLES: ! + \*-----------------------*/ + uchar highband_flag = 0; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_gl_inf *info; + bwc_cmd_opts_ll *param; + bwc_parameter *parameter; + bwc_param_ctrl *param_control; + bwc_param_inf *param_info; + bwc_packet *packet; + bwc_resolution *resolution; + bwc_res_ctrl *res_control; + bwc_res_inf *res_info; + bwc_tile *tile; + bwc_tile_ctrl *tile_control; + bwc_tile_inf *tile_info; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + + /*--------------------------------------------------------*\ + ! Save the global control and info structure to temporary ! + ! variables to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + info = field->info; + + /*--------------------------------------------------------*\ + ! Calculate the number of tiles in all spatial and tempo- ! + ! ral directions and allocate the tile structure accord- ! + ! ingly. ! + \*--------------------------------------------------------*/ + num_tiles_X = (int)ceil(((float)info->nX / control->tileSizeX)); + num_tiles_Y = (int)ceil(((float)info->nY / control->tileSizeY)); + num_tiles_Z = (int)ceil(((float)info->nZ / control->tileSizeZ)); + num_tiles_TS = (int)ceil(((float)info->nTS/ control->tileSizeTS)); + + field->tile = calloc(control->nTiles, sizeof(bwc_tile)); + if(!field->tile) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + /*--------------------------------------------------------*\ + ! Walk through and setup the tile structure according to ! + ! the specified compression parameters. ! + \*--------------------------------------------------------*/ + for(t = 0, i = 0; t < num_tiles_TS; ++t) + { + for(z = 0; z < num_tiles_Z; ++z) + { + for(y = 0; y < num_tiles_Y; ++y) + { + for(x = 0; x < num_tiles_X; ++x, ++i) + { + /*--------------------------------------------------------*\ + ! Initialize the number of packets and maximum number of ! + ! precincts variables. ! + \*--------------------------------------------------------*/ + nPackets = 0; + max_Prec = 0; + + /*--------------------------------------------------------*\ + ! Save the tile and its info and control structure to tem- ! + ! porary variables to make the code more readable. ! + \*--------------------------------------------------------*/ + tile = &field->tile[i]; + tile_control = &tile->control; + tile_info = &tile->info; + + /*--------------------------------------------------------*\ + ! Save the index for the current tile. ! + \*--------------------------------------------------------*/ + tile_info->tile_index = i; + + /*--------------------------------------------------------*\ + ! Calculate the boundaries for the current tile. ! + \*--------------------------------------------------------*/ + tile_info->X0 = (uint64)MAX(0, x * control->tileSizeX); + tile_info->Y0 = (uint64)MAX(0, y * control->tileSizeY); + tile_info->Z0 = (uint64)MAX(0, z * control->tileSizeZ); + tile_info->TS0 = (uint16)MAX(0, t * control->tileSizeTS); + tile_info->X1 = (uint64)MIN(info->nX , (x + 1) * control->tileSizeX); + tile_info->Y1 = (uint64)MIN(info->nY , (y + 1) * control->tileSizeY); + tile_info->Z1 = (uint64)MIN(info->nZ , (z + 1) * control->tileSizeZ); + tile_info->TS1 = (uint16)MIN(info->nTS, (t + 1) * control->tileSizeTS); + + /*--------------------------------------------------------*\ + ! Initialize the tile header size. ! + \*--------------------------------------------------------*/ + tile_control->header_size = 14; + + /*--------------------------------------------------------*\ + ! Initialize the convex hull slope threshold. ! + \*--------------------------------------------------------*/ + tile_control->slope_max = 0x0000; + tile_control->slope_min = 0xFFFF; + + /*--------------------------------------------------------*\ + ! Allocate, walk through and setup the parameter structure ! + ! according to the specified compression parameters. ! + \*--------------------------------------------------------*/ + tile->parameter = calloc(info->nPar, sizeof(bwc_parameter)); + if(!tile->parameter) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + /*--------------------------------------------------------*\ + ! Initialize the parameter information linked listed. ! + \*--------------------------------------------------------*/ + param = info->parameter->root; + + for(j = 0; j < info->nPar; ++j) + { + /*--------------------------------------------------------*\ + ! Check if there is a node in the parameter information ! + ! linked list corresponding to the current paramter. ! + \*--------------------------------------------------------*/ + if(!param && (param->id == j)) + { + fprintf(stderr, MEMERROR); + return 1; + } + + /*--------------------------------------------------------*\ + ! Save the parameter and its info and control structure to ! + ! temporary variables to make the code more readable. ! + \*--------------------------------------------------------*/ + parameter = &tile->parameter[j]; + param_control = ¶meter->control; + param_info = ¶meter->info; + + /*--------------------------------------------------------*\ + ! Save the corresponding parameter name and its sampling ! + ! factors and precision in the info and control structures.! + \*--------------------------------------------------------*/ + param_info->name = param->name; + param_info->precision = param->precision; + + /*--------------------------------------------------------*\ + ! Initialize the number of codeblocks for the current ! + ! parameter. ! + \*--------------------------------------------------------*/ + param_control->number_of_codeblocks = 0; + cblk = 0; + + /*--------------------------------------------------------*\ + ! Initialize the maximum and minimum parameter value in ! + ! the parameter structure. ! + \*--------------------------------------------------------*/ + param_info->parameter_max = -FLT_MAX; + param_info->parameter_min = FLT_MAX; + + /*--------------------------------------------------------*\ + ! Safe the boundaries of the current tile in the parameter ! + ! info structure. + \*--------------------------------------------------------*/ + param_info->X0 = tile->info.X0; + param_info->Y0 = tile->info.Y0; + param_info->Z0 = tile->info.Z0; + param_info->TS0 = tile->info.TS0; + param_info->X1 = tile->info.X1; + param_info->Y1 = tile->info.Y1; + param_info->Z1 = tile->info.Z1; + param_info->TS1 = tile->info.TS1; + + /*--------------------------------------------------------*\ + ! Allocate, walk through and setup the resolution struc- ! + ! ture according to the specified compression parameters. ! + \*--------------------------------------------------------*/ + parameter->resolution = calloc(control->nDecomp + 1, sizeof(bwc_resolution)); + if(!parameter->resolution) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + for(r = 0; r < control->nDecomp + 1; ++r) + { + /*--------------------------------------------------------*\ + ! Save the resolution and its info and control structure ! + ! to temporary variables to make the code more readable. ! + \*--------------------------------------------------------*/ + resolution = ¶meter->resolution[r]; + res_control = &resolution->control; + res_info = &resolution->info; + + /*--------------------------------------------------------*\ + ! Calculate the boundaries for the current resolution ac- ! + ! cording to the corresponding equation from JPEG2000 by ! + ! David S. Taubman and Michael W. Marcellin (p.456). ! + \*--------------------------------------------------------*/ + res_info->X0 = (uint64)ceil((float)param_info->X0 / (1 << MIN(control->nDecomp -r, control->decompX))); + res_info->Y0 = (uint64)ceil((float)param_info->Y0 / (1 << MIN(control->nDecomp -r, control->decompY))); + res_info->Z0 = (uint64)ceil((float)param_info->Z0 / (1 << MIN(control->nDecomp -r, control->decompZ))); + res_info->TS0 = (uint16)ceil((float)param_info->TS0/ (1 << MIN(control->nDecomp -r, control->decompTS))); + res_info->X1 = (uint64)ceil((float)param_info->X1 / (1 << MIN(control->nDecomp -r, control->decompX))); + res_info->Y1 = (uint64)ceil((float)param_info->Y1 / (1 << MIN(control->nDecomp -r, control->decompY))); + res_info->Z1 = (uint64)ceil((float)param_info->Z1 / (1 << MIN(control->nDecomp -r, control->decompZ))); + res_info->TS1 = (uint16)ceil((float)param_info->TS1/ (1 << MIN(control->nDecomp -r, control->decompTS))); + + /*--------------------------------------------------------*\ + ! Calculate the number of precincts to cover tile t in pa- ! + ! rameter p at resolution r according to equation (11.10) ! + ! from JPEG2000 by D. S. Taubman and M. W. Marcellin ! + ! (p.459). ! + \*--------------------------------------------------------*/ + res_control->numPX = (uint16)((res_info->X0 == res_info->X1) ? 0 : (ceil((float)res_info->X1 / (1 << control->precSizeX) + - floor((float)res_info->X0 / (1 << control->precSizeX))))); + res_control->numPY = (uint16)((res_info->Y0 == res_info->Y1) ? 0 : (ceil((float)res_info->Y1 / (1 << control->precSizeY) + - floor((float)res_info->Y0 / (1 << control->precSizeY))))); + res_control->numPZ = (uint16)((res_info->Z0 == res_info->Z1) ? 0 : (ceil((float)res_info->Z1 / (1 << control->precSizeZ) + - floor((float)res_info->Z0 / (1 << control->precSizeZ))))); + res_control->numPTS = (uint16)((res_info->TS0 == res_info->TS1) ? 0 : (ceil((float)res_info->TS1 / (1 << control->precSizeTS) + - floor((float)res_info->TS0 / (1 << control->precSizeTS))))); + + res_control->number_of_precincts = (uint64)res_control->numPX * res_control->numPY * res_control->numPZ * res_control->numPTS; + + /*--------------------------------------------------------*\ + ! Add up the global number of packets and evaluate the ! + ! maximum number of precincts between all resolution lev- ! + ! els for all tile parameters. ! + \*--------------------------------------------------------*/ + nPackets += (res_control->number_of_precincts * control->nLayers); + max_Prec = MAX(res_control->number_of_precincts * control->nLayers, max_Prec); + + /*--------------------------------------------------------*\ + ! Calculate and save the real codeblock size in the reso- ! + ! lution control structure. ! + \*--------------------------------------------------------*/ + if(r == 0) + { + res_control->rcbX = MIN(control->cbX, (uint8)(control->precSizeX)); + res_control->rcbY = MIN(control->cbY, (uint8)(control->precSizeY)); + res_control->rcbZ = MIN(control->cbZ, (uint8)(control->precSizeZ)); + res_control->rcbTS = MIN(control->cbTS, (uint8)(control->precSizeTS)); + } + else + { + res_control->rcbX = MIN(control->cbX, (uint8)(control->precSizeX - 1)); + res_control->rcbY = MIN(control->cbY, (uint8)(control->precSizeY - 1)); + res_control->rcbZ = MIN(control->cbZ, (uint8)(control->precSizeZ - 1)); + res_control->rcbTS = MIN(control->cbTS, (uint8)(control->precSizeTS - 1)); + } + + /*--------------------------------------------------------*\ + ! Evaluate in which spatial or temporal directions the ! + ! wavelet decomposition has been applied to according to ! + ! the current resolution level and amend the highband flag ! + ! accordingly. ! + \*--------------------------------------------------------*/ + highband_flag = (control->nDecomp - control->decompX < r && r > 0) ? DIM_X : 0; + highband_flag |= (control->nDecomp - control->decompY < r && r > 0) ? DIM_Y : 0; + highband_flag |= (control->nDecomp - control->decompZ < r && r > 0) ? DIM_Z : 0; + highband_flag |= (control->nDecomp - control->decompTS < r && r > 0) ? DIM_TS : 0; + + /*--------------------------------------------------------*\ + ! Evaluate the overall number of subbands, for the current ! + ! resolution level, according to the value of the highband ! + ! flag. ! + \*--------------------------------------------------------*/ + res_control->number_of_subbands = (1 << (((highband_flag & DIM_X)) + + ((highband_flag & DIM_Y) >> 1) + + ((highband_flag & DIM_Z) >> 2) + + ((highband_flag & DIM_TS) >> 3))); + + res_control->number_of_subbands -= (res_control->number_of_subbands & 1) ? 0 : 1; + + /*--------------------------------------------------------*\ + ! Allocate the point array used to hold the memory handles ! + ! of all packets created for the current resolution. ! + \*--------------------------------------------------------*/ + resolution->packet = calloc(res_control->number_of_precincts * control->nLayers, sizeof(bwc_packet)); + if(!resolution->packet) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + /*--------------------------------------------------------*\ + ! Allocate, walk through and setup the subband structure ! + ! according to the specified compression parameters. ! + \*--------------------------------------------------------*/ + resolution->subband = calloc(res_control->number_of_subbands, sizeof(bwc_subband)); + if(!resolution->subband) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + for(l = 0, m = 0; m < res_control->number_of_subbands; ++l) + { + if(r == 0 || ((l & highband_flag) == l && l != 0)) + { + if(initialize_subband(field, parameter, resolution, &resolution->subband[m], r, l)) + { + return 1; + } + + /*--------------------------------------------------------*\ + ! Adjust the size of the codeblock access array. ! + \*--------------------------------------------------------*/ + parameter->access = realloc(parameter->access, param_control->number_of_codeblocks * + sizeof(bwc_cblk_access)); + + /*--------------------------------------------------------*\ + ! Fill the codeblock access array with the appropriate ! + ! pointers for the newly initialized precinct, subband and ! + ! codeblock structures. Save the codeblock index with re- ! + ! gards to the current precinct in the codeblock info ! + ! structure. Initialize the packet structure with the indi-! + ! ces for the parameter, resolution, precinct and quality ! + ! layer the packet occupies. ! + \*--------------------------------------------------------*/ + for(p = 0; p < res_control->number_of_precincts; ++p) + { + for(c = 0; c < resolution->subband[m].precinct[p].control.number_of_codeblocks; ++c, ++cblk) + { + parameter->access[cblk].subband = &resolution->subband[m]; + parameter->access[cblk].precinct = &resolution->subband[m].precinct[p]; + parameter->access[cblk].codeblock = &resolution->subband[m].precinct[p].codeblock[c]; + + parameter->access[cblk].codeblock->info.idx = c; + + for(n = 0; n < control->nLayers; ++n) + { + packet = &resolution->packet[n * res_control->number_of_precincts + p]; + + packet->c = j; + packet->r = r; + packet->p = p; + packet->l = n; + } + } + } + m++; + } + } + } + + /*--------------------------------------------------------*\ + ! Advance the parameter information linked listed to the ! + ! next node. ! + \*--------------------------------------------------------*/ + param = param->next; + } + + /*--------------------------------------------------------*\ + ! Allocate the pointer array used to sequence the code- ! + ! stream packets. ! + \*--------------------------------------------------------*/ + tile->packet_sequence = calloc(nPackets, sizeof(bwc_packet*)); + if(!tile->packet_sequence) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + /*--------------------------------------------------------*\ + ! Adjust the tile header size if the error resilience op- ! + ! tion has been specified and save the nPackets variable. ! + ! Store the maximum number of Precincts between all reso- ! + ! lution levels in the tile control structure. ! + \*--------------------------------------------------------*/ + tile_control->header_size += control->error_resilience ? 8 * nPackets : 0; + tile_control->nPackets = nPackets; + tile_control->max_Prec = max_Prec; + } + } + } + } + return 0; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void kill_compression(bwc_field *const field) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function deallocates the compression field structure used to define and control the ! +! bwc codec and can be called if an error occurs during the (de-)compression stage or once ! +! the codec has finished. The deallocation will be carried out down to the structure levels ! +! that have been allocated. ! +! ! +! PARAMETERS: ! +! ----------- ! +! ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 19.10.2017 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +bwc_kill_compression(bwc_field *const field) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 c, k; + uint32 i; + uint16 j, r; + int8 l; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_gl_inf *info; + + if(field) + { + /*--------------------------------------------------------*\ + ! Save the global control and info structure to temporary ! + ! variables to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + info = field->info; + + if(field->tile) + { + for(i = 0; i < control->nTiles; ++i) + { + if(field->tile[i].parameter) + { + for(j = 0; j < info->nPar; ++j) + { + if(field->tile[i].parameter[j].resolution) + { + for(r = 0; r < control->nDecomp + 1; ++r) + { + if(field->tile[i].parameter[j].resolution[r].subband) + { + for(l = 0; l < field->tile[i].parameter[j].resolution[r].control.number_of_subbands; ++l) + { + if(field->tile[i].parameter[j].resolution[r].subband[l].precinct) + { + for(k = 0; k < field->tile[i].parameter[j].resolution[r].control.number_of_precincts; ++k) + { + if(field->tile[i].parameter[j].resolution[r].subband[l].precinct[k].codeblock) + { + for(c = 0; c < field->tile[i].parameter[j].resolution[r].subband[l].precinct[k].control.number_of_codeblocks; ++c) + { + if(field->tile[i].parameter[j].resolution[r].subband[l].precinct[k].codeblock[c].encoded_block) + { + free(field->tile[i].parameter[j].resolution[r].subband[l].precinct[k].codeblock[c].encoded_block->data); + } + free(field->tile[i].parameter[j].resolution[r].subband[l].precinct[k].codeblock[c].control.memory); + free(field->tile[i].parameter[j].resolution[r].subband[l].precinct[k].codeblock[c].encoded_block); + } + } + if(field->tile[i].parameter[j].resolution[r].subband[l].precinct[k].control.number_of_codeblocks) + { + kill_tagtree(field->tile[i].parameter[j].resolution[r].subband[l].precinct[k].control.tag_inclusion); + kill_tagtree(field->tile[i].parameter[j].resolution[r].subband[l].precinct[k].control.tag_msbs); + } + free(field->tile[i].parameter[j].resolution[r].subband[l].precinct[k].codeblock); + } + } + free(field->tile[i].parameter[j].resolution[r].subband[l].precinct); + } + } + free(field->tile[i].parameter[j].resolution[r].subband); + free(field->tile[i].parameter[j].resolution[r].packet); + } + } + free(field->tile[i].parameter[j].resolution); + free(field->tile[i].parameter[j].access); + } + } + free(field->tile[i].packet_sequence); + free(field->tile[i].parameter); + } + } + free(control->header.memory); + free(control->bitrate); + free(field->tile); + free(field); + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: bwc_field *bwc_initialize_field(bwc_data *const data) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function initializes the bwc_field structure with all necessary standard parameters ! +! to (de)compress a floating point array with nX * nY * nZ grid points, nTS timesteps and ! +! nPar parameters. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! nX ,nY, nZ unsigned int(64 bit) - Structure used to store a numerical ! +! dataset/compressed bitstream. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! bwc_field* Defines the (de)compression data structure. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 14.03.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +bwc_field* +bwc_initialize_field(bwc_data *const data) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint8 levelsX, levelsY, levelsZ; + uint8 levelsTS; + + /*-----------------------*\ + ! DEFINE FLOAT VARIABLES: ! + \*-----------------------*/ + bwc_float delta; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_gl_inf *info; + + /*--------------------------------------------------------*\ + ! Allocate the root compression data structure. ! + \*--------------------------------------------------------*/ + bwc_field *field = calloc(1, sizeof(bwc_field)); + if(!field) + { + // memory allocation error + fprintf(stderr, MEMERROR); + bwc_kill_compression(field); + return NULL; + } + + /*--------------------------------------------------------*\ + ! Save the global control and info structure to temporary ! + ! variables to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + info = field->info = &data->info; + + /*--------------------------------------------------------*\ + ! Set all tile sizes to their maximum allowable value. The ! + ! value for the number of tiles is set to 1. ! + \*--------------------------------------------------------*/ + control->tileSizeX = info->nX; + control->tileSizeY = info->nY; + control->tileSizeZ = info->nZ; + control->tileSizeTS = info->nTS; + control->nTiles = 1; + + /*--------------------------------------------------------*\ + ! Set the spatial and temporal precinct sizes to their ! + ! standard values. For all valid dimensions the values ! + ! are set to 15 while all invalid dimensions are set to ! + ! 0. ! + \*--------------------------------------------------------*/ + control->precSizeX = (info->nX >> 1) ? 15 : 0; + control->precSizeY = (info->nY >> 1) ? 15 : 0; + control->precSizeZ = (info->nZ >> 1) ? 15 : 0; + control->precSizeTS = (info->nTS >> 1) ? 15 : 0; + + /*--------------------------------------------------------*\ + ! Set the spatial and temporal codeblock sizes to their ! + ! standard values. For all valid dimensions the values ! + ! are set to 4 while all invalid dimensions are set to ! + ! 0. ! + \*--------------------------------------------------------*/ + control->cbX = (info->nX >> 1) ? 5 : 0; + control->cbY = (info->nY >> 1) ? 5 : 0; + control->cbZ = (info->nZ >> 1) ? 5 : 0; + control->cbTS = (info->nTS >> 1) ? 5 : 0; + + /*--------------------------------------------------------*\ + ! Set the spatial and temporal wavelet kernels to their ! + ! standard values. ! + \*--------------------------------------------------------*/ + control->KernelX = + control->KernelY = + control->KernelZ = + control->KernelTS = bwc_dwt_9_7; + + /*--------------------------------------------------------*\ + ! Set the progression order, quantization style, number of ! + ! layers, Q number format value and guard bits to their ! + ! standard values. Amend the quantization style default ! + ! parameter for the main header, accordingly. ! + \*--------------------------------------------------------*/ + control->progression = bwc_prog_LRCP; + control->quantization_style = bwc_qt_derived; + control->nLayers = 0x00; + control->Qm = PREC_BIT - 1; + control->bitrate = 0; + control->guard_bits = 2; + + /*--------------------------------------------------------*\ + ! Save the codec precision in the info structure. ! + \*--------------------------------------------------------*/ + info->precision = PREC_BYTE; + + /*--------------------------------------------------------*\ + ! Calculate the possible decomposition levels for all ! + ! spatial and temporal dimensions. ! + \*--------------------------------------------------------*/ + levelsX = log(info->nX) /log(2); + levelsY = log(info->nY) /log(2); + levelsZ = log(info->nZ) /log(2); + levelsTS = log(info->nTS)/log(2); + + /*--------------------------------------------------------*\ + ! Check if the decomposition levels are specified for a ! + ! valid spatial or temporal dimension. For all invalid and ! + ! unspecified (NULL) values the corresponding decomposi- ! + ! tion level is set to 0. For all valid dimensions the ! + ! number of decomposition levels is set accordingly. ! + \*--------------------------------------------------------*/ + control->decompX = (info->nX >> 1) ? ((4 < levelsX) ? 4 : levelsX) : 0; + control->decompY = (info->nY >> 1) ? ((4 < levelsY) ? 4 : levelsY) : 0; + control->decompZ = (info->nZ >> 1) ? ((4 < levelsZ) ? 4 : levelsZ) : 0; + control->decompTS = (info->nTS >> 1) ? ((4 < levelsTS) ? 4 : levelsTS) : 0; + + control->nDecomp = MAX(control->decompX, + MAX(control->decompY, + MAX(control->decompZ, control->decompTS))); + + /*--------------------------------------------------------*\ + ! Initialize the lookup tables used to calculate the ener- ! + ! gy gain for the multi dimensional wavelet transforms. ! + \*--------------------------------------------------------*/ + if(initialize_gain_lut()) + { + bwc_kill_compression(field); + return NULL; + } + + /*--------------------------------------------------------*\ + ! Calculate the appropriate quantization step size for the ! + ! given number of decomposition levels according to equa- ! + ! tion (10.19) (epsilon = 6, mu = 16) from JPEG2000 by ! + ! by David S. Taubman and Michael W. Marcellin (p.437). ! + \*--------------------------------------------------------*/ + delta = (bwc_float)(1/(pow(2, 2 + PREC_BIT) * sqrt(get_dwt_energy_gain(field, 0, control->nDecomp)))); + + for(control->qt_exponent = 0; delta < 1; ++control->qt_exponent, delta *= 2); + control->qt_mantissa = (uint16)floor(0.5f + ((delta - 1.0f) * (1 << 16))); + + if(control->qt_exponent > PREC_BIT) + { + control->qt_exponent = PREC_BIT; + control->qt_mantissa = 0; + } + if(control->qt_mantissa >= 1 << 16) + { + if(control->qt_exponent == 0) + { + control->qt_exponent = 0; + control->qt_mantissa = (1 << 16) - 1; + } + else + { + control->qt_exponent--; + control->qt_mantissa = 0; + } + } + + return field; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void bwc_set_error_resilience(bwc_field *const field) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function sets the error resilience marker in the bwc_field structure if an error ! +! resilient compression approach is to be employed. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 13.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +bwc_set_error_resilience(bwc_field *const field) +{ + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + + /*--------------------------------------------------------*\ + ! Save the global control structure to a temporary varia- ! + ! ble to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + + /*--------------------------------------------------------*\ + ! Amend the codeblock style in the bwc_field structure ! + ! according to the specified value. ! + \*--------------------------------------------------------*/ + control->error_resilience ^= 0x01; + + /*--------------------------------------------------------*\ + ! Record the setting of the error resilience marker in the ! + ! CSsgc variable. ! + \*--------------------------------------------------------*/ + control->CSsgc ^= (0x01 << 0); +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void bwc_set_quant_style(bwc_field *const field, bwc_quant_st quantization_style) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function amends the quantization style in the bwc_field structure according to the ! +! specified value. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! quantization_style bwc_quant_st - Quantization style used during compres- ! +! sion. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 15.03.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +bwc_set_quant_style(bwc_field *const field, bwc_quant_st quantization_style) +{ + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert((quantization_style == bwc_qt_derived) || (quantization_style == bwc_qt_none)); + + /*--------------------------------------------------------*\ + ! Save the global control structure to a temporary varia- ! + ! ble to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + + /*--------------------------------------------------------*\ + ! Amend the quantization style in the bwc_field structure ! + ! according to the specified value. ! + \*--------------------------------------------------------*/ + control->quantization_style = quantization_style; + + /*--------------------------------------------------------*\ + ! Record the setting of the quantization style marker in ! + ! the CSsgc variable. ! + \*--------------------------------------------------------*/ + control->CSsgc |= (0x01 << 1); +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void bwc_set_quant_step_size(bwc_field *const field, double delta) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function amends the quantization step size in the bwc_field structure according to ! +! the specified value. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! delta double - Quantization step size used during ! +! compression. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 16.04.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +bwc_set_quant_step_size(bwc_field *const field, double delta) +{ + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + + /*--------------------------------------------------------*\ + ! Save the global control structure to a temporary varia- ! + ! ble to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + + /*--------------------------------------------------------*\ + ! Check if the quantization step size lies within the ac- ! + ! ceptable range. ! + \*--------------------------------------------------------*/ + if((delta <= 0) || (delta >= 2)) + { + fprintf(stderr, "o==========================================================o\n"\ + "| WARNING: Invalid quantization step size |\n"\ + "| |\n"\ + "| The quantization step size does not lie within |\n"\ + "| the acceptable range of: |\n"\ + "| |\n"\ + "| 0 < step size < 2 |\n"\ + "| |\n"\ + "o==========================================================o\n"); + + return; + } + + /*--------------------------------------------------------*\ + ! Reevaluate the mantissa and exponent of the user defined ! + ! quantization step size. ! + \*--------------------------------------------------------*/ + for(control->qt_exponent = 0; delta < 1; ++control->qt_exponent, delta *= 2); + control->qt_mantissa = (uint16)floor(0.5f + ((delta - 1.0f) * (1 << 16))); + + if(control->qt_exponent > PREC_BIT) + { + control->qt_exponent = PREC_BIT; + control->qt_mantissa = 0; + } + if(control->qt_mantissa >= 1 << 16) + { + if(control->qt_exponent == 0) + { + control->qt_exponent = 0; + control->qt_mantissa = (1 << 16) - 1; + } + else + { + control->qt_exponent--; + control->qt_mantissa = 0; + } + } + + /*--------------------------------------------------------*\ + ! Record the setting of the quantization step size in the ! + ! CSsgc variable. ! + \*--------------------------------------------------------*/ + control->CSsgc |= (0x01 << 2); +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void bwc_set_progression(bwc_field *const field, bwc_prog_ord progression) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function amends the progression order in the bwc_field structure according to the ! +! specified value. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! progression bwc_prog_ord - Progression orders employed during com- ! +! pression (CPRL, LRCP, PCRL, RLCP, ! +! RPCL). ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 15.03.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +bwc_set_progression(bwc_field *const field, bwc_prog_ord progression) +{ + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert((progression == bwc_prog_CPRL) || (progression == bwc_prog_LRCP) || + (progression == bwc_prog_PCRL) || (progression == bwc_prog_RLCP) || + (progression == bwc_prog_RPCL)); + + /*--------------------------------------------------------*\ + ! Save the global control structure to a temporary varia- ! + ! ble to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + + /*--------------------------------------------------------*\ + ! Amend the progression order in the bwc_field structure ! + ! according to the specified value. ! + \*--------------------------------------------------------*/ + control->progression = progression; + + /*--------------------------------------------------------*\ + ! Record the setting of the progression order marker in ! + ! the CSsgc variable. ! + \*--------------------------------------------------------*/ + control->CSsgc |= (0x01 << 3); +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void bwc_set_kernels(bwc_field *const field, bwc_dwt_filter KernelX, ! +! -------------- bwc_dwt_filter KernelY, ! +! bwc_dwt_filter KernelZ, ! +! bwc_dwt_filter KernelTS) ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function amends the wavelet kernels in the bwc_field structure according to the ! +! specified values. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! KernelX, KernelY, KernelZ bwc_dwt_filter - Wavelet kernels used for spatial ! +! decomposition. ! +! ! +! KernelT bwc_dwt_filter - Wavelet kernel used for temporal ! +! decomposition. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 15.03.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +bwc_set_kernels(bwc_field *const field, bwc_dwt_filter KernelX, bwc_dwt_filter KernelY, + bwc_dwt_filter KernelZ, bwc_dwt_filter KernelTS) +{ + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + + /*--------------------------------------------------------*\ + ! Save the global control structure to a temporary varia- ! + ! ble to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + + /*--------------------------------------------------------*\ + ! Amend the wavelet kernels in the bwc_field structure ac- ! + ! cording to the specified values. For all unspecified ! + ! (NULL) values the corresponding wavelet kernel is set to ! + ! bwc_dwt_9_7/bwc_dwt_haar. ! + \*--------------------------------------------------------*/ + control->KernelX = KernelX ? KernelX : bwc_dwt_9_7; + control->KernelY = KernelY ? KernelY : bwc_dwt_9_7; + control->KernelZ = KernelZ ? KernelZ : bwc_dwt_9_7; + control->KernelTS = KernelTS ? KernelTS : bwc_dwt_haar; + + /*--------------------------------------------------------*\ + ! Record the setting of the wavelet kernel order markers ! + ! in the CSsgc variable. ! + \*--------------------------------------------------------*/ + control->CSsgc |= (0x01 << 4); +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void bwc_set_decomp(bwc_field *const field, uint8 decompX, uint8 decompY, ! +! -------------- uint8 decompZ, uint8 decompTS) ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function amends the decomposition levels in the bwc_field structure according to the ! +! specified values. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! decompX, decompY, decompZ unsigned int(8 bit) - Number of spatial wavelet decomposition ! +! levels used during compression. ! +! ! +! decompTS unsigned int(8 bit) - Number of temporal wavelet decomposi- ! +! tion level used during compression. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 14.03.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +bwc_set_decomp(bwc_field *const field, uint8 decompX, uint8 decompY, uint8 decompZ, uint8 decompTS) +{ + /*-----------------------*\ + ! DEFINE FLOAT VARIABLES: ! + \*-----------------------*/ + double delta; + + /*-----------------------*\ + ! DEFINE CHAR VARIABLES: ! + \*-----------------------*/ + uint8 levelsX, levelsY, levelsZ, levelsTS; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_gl_inf *info; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + + /*--------------------------------------------------------*\ + ! Save the global control and info structure to temporary ! + ! variables to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + info = field->info; + + /*--------------------------------------------------------*\ + ! Calculate the possible decomposition levels for all ! + ! spatial and temporal dimensions. ! + \*--------------------------------------------------------*/ + levelsX = log(info->nX) /log(2); + levelsY = log(info->nY) /log(2); + levelsZ = log(info->nZ) /log(2); + levelsTS = log(info->nTS)/log(2); + + /*--------------------------------------------------------*\ + ! Check if the decomposition levels are specified for a ! + ! valid spatial or temporal dimension. For all invalid and ! + ! unspecified (NULL) values the corresponding decomposi- ! + ! tion level is set to 0. For all valid dimensions the ! + ! number of decompositions is set accordingly. ! + \*--------------------------------------------------------*/ + control->decompX = (info->nX >> 1) ? ((decompX < levelsX) ? decompX : levelsX) : 0; + control->decompY = (info->nY >> 1) ? ((decompY < levelsY) ? decompY : levelsY) : 0; + control->decompZ = (info->nZ >> 1) ? ((decompZ < levelsZ) ? decompZ : levelsZ) : 0; + control->decompTS = (info->nTS >> 1) ? ((decompTS < levelsTS) ? decompTS : levelsTS) : 0; + + /*--------------------------------------------------------*\ + ! Calculate the overall number of decomposition levels. ! + \*--------------------------------------------------------*/ + control->nDecomp = MAX(control->decompX, + MAX(control->decompY, + MAX(control->decompZ, control->decompTS))); + + /*--------------------------------------------------------*\ + ! Check if the decomposition levels have valid values. ! + \*--------------------------------------------------------*/ + if((control->decompX > 63) || (control->decompY > 63) || + (control->decompZ > 63) || (control->decompTS > 31)) + { + fprintf(stderr, "o==========================================================o\n"\ + "| WARNING: Invalid decomposition level value |\n"\ + "| |\n"\ + "| The maximum acceptable decomposition level is |\n"\ + "| 63 for all spatial and 31 for the temporal |\n"\ + "| dimensions. |\n"\ + "| |\n"\ + "o==========================================================o\n"); + + /*--------------------------------------------------------*\ + ! Reset the decomposition levels to their standard values. ! + \*--------------------------------------------------------*/ + control->decompX = (info->nX >> 1) ? 4 : 0; + control->decompY = (info->nY >> 1) ? 4 : 0; + control->decompZ = (info->nZ >> 1) ? 4 : 0; + control->decompTS = (info->nTS >> 1) ? 4 : 0; + + return; + } + + /*--------------------------------------------------------*\ + ! Initialize the lookup tables used to calculate the ener- ! + ! gy gain for the multi dimensional wavelet transforms. ! + \*--------------------------------------------------------*/ + if(initialize_gain_lut()) + { + bwc_kill_compression(field); + return; + } + + /*--------------------------------------------------------*\ + ! Calculate the appropriate quantization step size for the ! + ! given number of decomposition levels according to equa- ! + ! tion (10.19) (epsilon = 6, mu = 16) from JPEG2000 by ! + ! by David S. Taubman and Michael W. Marcellin (p.437). ! + \*--------------------------------------------------------*/ + delta = 1/(pow(2, 2 + PREC_BIT) * sqrt(get_dwt_energy_gain(field, 0, control->nDecomp))); + + for(control->qt_exponent = 0; delta < 1; ++control->qt_exponent, delta *= 2); + control->qt_mantissa = (uint16)floor(0.5f + ((delta - 1.0f) * (1 << 16))); + + if(control->qt_exponent > PREC_BIT) + { + control->qt_exponent = PREC_BIT; + control->qt_mantissa = 0; + } + if(control->qt_mantissa >= 1 << 16) + { + if(control->qt_exponent == 0) + { + control->qt_exponent = 0; + control->qt_mantissa = (1 << 16) - 1; + } + else + { + control->qt_exponent--; + control->qt_mantissa = 0; + } + } + + /*--------------------------------------------------------*\ + ! Record the setting of the decomposition level variables ! + ! in the CSsgc variable. ! + \*--------------------------------------------------------*/ + control->CSsgc |= (0x01 << 5); +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void bwc_set_precincts(bwc_field *const field, uint8 pX, uint8 pY, uint8 pZ, uint8 pTS) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function amends the precinct size in the bwc_field structure according to the ! +! specified values. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! px, py, pz, pTS unsigned int(8 bit) - Spatial and temporal precinct dimensions! +! in log2 exponent format. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 15.05.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +bwc_set_precincts(bwc_field *const field, uint8 pX, uint8 pY, uint8 pZ, uint8 pTS) +{ + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_gl_inf *info; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + + /*--------------------------------------------------------*\ + ! Save the global control and info structure to temporary ! + ! variables to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + info = field->info; + + /*--------------------------------------------------------*\ + ! Check if the precinct sizes are specified for a valid ! + ! spatial or temporal dimension. For all invalid and un- ! + ! specified (NULL) values the corresponding precinct size ! + ! is set to 0. For all valid dimensions the precinct size ! + ! is set accordingly. ! + \*--------------------------------------------------------*/ + control->precSizeX = (info->nX >> 1) ? (pX ? pX : 15) : 0; + control->precSizeY = (info->nY >> 1) ? (pY ? pY : 15) : 0; + control->precSizeZ = (info->nZ >> 1) ? (pZ ? pZ : 15) : 0; + control->precSizeTS = (info->nTS >> 1) ? (pTS ? pTS : 15) : 0; + + /*--------------------------------------------------------*\ + ! Check if the codeblock sizes have valid values. ! + \*--------------------------------------------------------*/ + if(((control->precSizeX < 1) && (info->nX >> 1)) || + ((control->precSizeY < 1) && (info->nY >> 1)) || + ((control->precSizeZ < 1) && (info->nZ >> 1)) || + ((control->precSizeTS < 1) && (info->nTS >> 1)) || + (control->precSizeX > 15) || (control->precSizeY > 15) || (control->precSizeZ > 15) || (control->precSizeTS > 15)) + { + fprintf(stderr, "o==========================================================o\n"\ + "| WARNING: Invalid precinct size |\n"\ + "| |\n"\ + "| The maximum acceptable precinct size is 2^15, |\n"\ + "| the smallest valid precinct size is 2^1. |\n"\ + "| |\n"\ + "o==========================================================o\n"); + + /*--------------------------------------------------------*\ + ! Reset the codeblock sizes to their standard values. ! + \*--------------------------------------------------------*/ + control->precSizeX = (info->nX >> 1) ? 15 : 0; + control->precSizeY = (info->nY >> 1) ? 15 : 0; + control->precSizeZ = (info->nZ >> 1) ? 15 : 0; + control->precSizeTS = (info->nTS >> 1) ? 15 : 0; + + return; + } + + /*--------------------------------------------------------*\ + ! Record the setting of the precinct size variables in the ! + ! CSsgc variable. ! + \*--------------------------------------------------------*/ + control->CSsgc |= (0x01 << 6); +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void bwc_set_codeblocks(bwc_field *const field, uint8 cbX, uint8 cbY, ! +! -------------- uint8 cbZ, uint8 cbTS) ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function amends the codeblock size in the bwc_field structure according to the ! +! specified values. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! cbx, cby, cbz, cbTS unsigned int(8 bit) - Spatial and temporal codeblock dimen- ! +! sions in log2 exponent format. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 14.03.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +bwc_set_codeblocks(bwc_field *const field, uint8 cbX, uint8 cbY, uint8 cbZ, uint8 cbTS) +{ + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_gl_inf *info; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + + /*--------------------------------------------------------*\ + ! Save the global control and info structure to temporary ! + ! variables to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + info = field->info; + + /*--------------------------------------------------------*\ + ! Check if the codeblock sizes are specified for a valid ! + ! spatial or temporal dimension. For all invalid and un- ! + ! specified (NULL) values the corresponding codeblock size ! + ! is set to 0. For all valid dimensions the codeblock size ! + ! is set accordingly. ! + \*--------------------------------------------------------*/ + control->cbX = (info->nX >> 1) ? (cbX ? cbX : 5) : 0; + control->cbY = (info->nY >> 1) ? (cbY ? cbY : 5) : 0; + control->cbZ = (info->nZ >> 1) ? (cbZ ? cbZ : 5) : 0; + control->cbTS = (info->nTS >> 1) ? (cbTS ? cbTS : 5) : 0; + + /*--------------------------------------------------------*\ + ! Check if the codeblock sizes have valid values. ! + \*--------------------------------------------------------*/ + if((control->cbX > 10) || (control->cbY > 10) || (control->cbZ > 10) || (control->cbTS > 10)|| + ((control->cbX + control->cbY + control->cbZ + control->cbTS) < 4) || + ((control->cbX + control->cbY + control->cbZ + control->cbTS) > 20)) + { + fprintf(stderr, "o==========================================================o\n"\ + "| WARNING: Invalid codeblock size |\n"\ + "| |\n"\ + "| The maximum acceptable codeblock size is 2^20 |\n"\ + "| with a maximum allowable number of datapoints |\n"\ + "| in each dimension of 2^10. The smallest valid |\n"\ + "| codeblock size is 2^4. |\n"\ + "| |\n"\ + "o==========================================================o\n"); + + /*--------------------------------------------------------*\ + ! Reset the codeblock sizes to their standard values. ! + \*--------------------------------------------------------*/ + control->cbX = (info->nX >> 1) ? 5 : 0; + control->cbY = (info->nY >> 1) ? 5 : 0; + control->cbZ = (info->nZ >> 1) ? 5 : 0; + control->cbTS = (info->nTS >> 1) ? 5 : 0; + + return; + } + + /*--------------------------------------------------------*\ + ! Record the setting of the codeblock size variables in ! + ! the CSsgc variable. ! + \*--------------------------------------------------------*/ + control->CSsgc |= (0x01 << 7); +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void bwc_set_qm(bwc_field *const field, uint8 Qm) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function amends the Q number formate range in the bwc_field structure according to the ! +! specified value. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! Qm unsigned int(8 bit) - Q number formate range (m). ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 14.03.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +bwc_set_qm(bwc_field *const field, uint8 Qm) +{ + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + + /*--------------------------------------------------------*\ + ! Save the global control structure to a temporary varia- ! + ! ble to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + + /*--------------------------------------------------------*\ + ! Check if the Q number formate range is valid and amend ! + ! the bwc_field structure accordingly. ! + \*--------------------------------------------------------*/ + if((int8)(PREC_BIT - Qm) < 2) + { + fprintf(stderr, "o==========================================================o\n"\ + "| WARNING: Invalid Q number formate range |\n"\ + "| |\n"\ + "| The specified Q number formate range is larger |\n"); + #ifdef BWC_SINGLE_PRECISION + fprintf(stderr, "| than the permitted 30 bits. |\n"); + #else + fprintf(stderr, "| than the permitted 62 bits. |\n"); + #endif + fprintf(stderr, "| |\n"\ + "o==========================================================o\n"); + } + else + { + control->Qm = Qm; + + /*--------------------------------------------------------*\ + ! Record the setting of the Q number format range in the ! + ! CSsgc variable. ! + \*--------------------------------------------------------*/ + control->CSsgc |= (0x01 << 8); + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void bwc_set_tiles(bwc_field *const field, uint32 tilesX, uint32 tilesY, uint32 tilesZ, ! +! -------------- uint32 tilesTS, uchar instr) ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function amends the tileSize and num_Tiles values in the bwc_field structure according ! +! to the specified values. The NUMBEROF and SIZEOF constants can be used to either specify ! +! the tile sizes or the number of tiles in each spatial and temporal directions. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! tilesX, tilesY, tilesZ unsigned int(32 bit) - Variables defining the size of ! +! a spatial tile. ! +! ! +! tilesTS unsigned int(32 bit) - Variables defining the size of ! +! a temporal tile. ! +! ! +! instr bwc_tile_instr - Constants used to instruct the ! +! bwc_set_tiles function. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 14.03.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +bwc_set_tiles(bwc_field *const field, uint64 tilesX, uint64 tilesY, uint64 tilesZ, uint16 tilesTS, bwc_tile_instr instr) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 num_tiles_X, num_tiles_Y, num_tiles_Z; + uint16 num_tiles_TS; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_gl_inf *info; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert(instr == bwc_tile_sizeof || instr == bwc_tile_numbof); + + /*--------------------------------------------------------*\ + ! Save the global control and info structure to temporary ! + ! variables to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + info = field->info; + + /*--------------------------------------------------------*\ + ! Check if the size of one tile or the overall number of ! + ! tiles are defined. ! + \*--------------------------------------------------------*/ + if(instr == bwc_tile_sizeof) + { + /*--------------------------------------------------------*\ + ! Check if the tile sizes have valid values. ! + \*--------------------------------------------------------*/ + if((control->tileSizeX < 16 && control->tileSizeX > info->nX)|| + (control->tileSizeY < 16 && control->tileSizeY > info->nY)|| + (control->tileSizeZ < 16 && control->tileSizeZ > info->nZ)|| + (control->tileSizeTS < 16 && control->tileSizeTS > info->nTS)) + { + fprintf(stderr,"o==========================================================o\n"\ + "| WARNING: Invalid Tile Dimensions |\n"\ + "| |\n"\ + "| One or more of the specified tile dimensions |\n"\ + "| has a value that falls outside of its valid |\n"\ + "| range. Please verify that all tile dimension |\n"\ + "| are within the range of: |\n"\ + "| |\n"\ + "| 16 ≤ Tile_Size_Xi ≤ Grid_Points_Xi |\n"\ + "| |\n"\ + "o==========================================================o\n"); + + return; + } + + /*--------------------------------------------------------*\ + ! Check if the tile dimensions are specified for a valid ! + ! spatial or temporal dimension. All invalid and unspeci- ! + ! fied (NULL) values are set to the maximum allowable tile ! + ! size. ! + \*--------------------------------------------------------*/ + control->tileSizeX = (info->nX >> 1) ? (tilesX ? tilesX : info->nX) : info->nX; + control->tileSizeY = (info->nY >> 1) ? (tilesY ? tilesY : info->nY) : info->nY; + control->tileSizeZ = (info->nZ >> 1) ? (tilesZ ? tilesZ : info->nZ) : info->nZ; + control->tileSizeTS = (info->nTS >> 1) ? (tilesTS ? tilesTS : info->nTS) : info->nTS; + + /*--------------------------------------------------------*\ + ! Calculate the number of tiles in all spatial and tempo- ! + ! ral directions and the overall number of tiles. ! + \*--------------------------------------------------------*/ + num_tiles_X = (uint64)ceil(((float)info->nX / control->tileSizeX)); + num_tiles_Y = (uint64)ceil(((float)info->nY / control->tileSizeY)); + num_tiles_Z = (uint64)ceil(((float)info->nZ / control->tileSizeZ)); + num_tiles_TS = (uint16)ceil(((float)info->nTS/ control->tileSizeTS)); + control->nTiles = num_tiles_X * num_tiles_Y * num_tiles_Z * num_tiles_TS; + + /*--------------------------------------------------------*\ + ! Check if the number of tiles exceeds its maximum allowa- ! + ! ble value. ! + \*--------------------------------------------------------*/ + if(((double)num_tiles_X * num_tiles_Y * num_tiles_Z * num_tiles_TS) > 0xFFFFFFFFFFFFFFFF) + { + fprintf(stderr,"o==========================================================o\n"\ + "| WARNING: Invalid Tile Dimensions |\n"\ + "| |\n"\ + "| The number of tiles exceeds its maxmum allowa- |\n"\ + "| ble value. Please adjust all tile dimension so |\n"\ + "| that the number of tiles falls within the range |\n"\ + "| of: |\n"\ + "| Number_of_Tiles < 2^64 |\n"\ + "| |\n"\ + "o==========================================================o\n"); + + /*--------------------------------------------------------*\ + ! Reset the tile sizes to their standard values. ! + \*--------------------------------------------------------*/ + control->tileSizeX = info->nX; + control->tileSizeY = info->nY; + control->tileSizeZ = info->nZ; + control->tileSizeTS = info->nTS; + + return; + } + } + else if(bwc_tile_numbof) + { + /*--------------------------------------------------------*\ + ! Check if the number of tiles exceeds its maximum allowa- ! + ! ble value. ! + \*--------------------------------------------------------*/ + if(((double)tilesX * tilesY * tilesZ * tilesTS) > 0xFFFFFFFFFFFFFFFF) + { + fprintf(stderr,"o==========================================================o\n"\ + "| WARNING: Invalid Number Of Tiles |\n"\ + "| |\n"\ + "| The number of tiles exceeds its maxmum allowa- |\n"\ + "| ble value of: |\n"\ + "| |\n"\ + "| Number_of_Tiles < 2^64 |\n"\ + "| |\n"\ + "o==========================================================o\n"); + + return; + } + + /*--------------------------------------------------------*\ + ! Check if the number of tiles are specified for a valid ! + ! spatial or temporal dimension. For all invalid and un- ! + ! specified (NULL) values the corresponding tile size is ! + ! set to its maximum allowable value. For all valid values ! + ! the tile sizes are calculated accordingly. ! + \*--------------------------------------------------------*/ + control->tileSizeX = (info->nX >> 1) ? (tilesX ? (uint64)ceil(((float)info->nX / tilesX)) : info->nX) : info->nX; + control->tileSizeY = (info->nY >> 1) ? (tilesY ? (uint64)ceil(((float)info->nY / tilesY)) : info->nY) : info->nY; + control->tileSizeZ = (info->nZ >> 1) ? (tilesZ ? (uint64)ceil(((float)info->nZ / tilesZ)) : info->nZ) : info->nZ; + control->tileSizeTS = (info->nTS >> 1) ? (tilesTS ? (uint16)ceil(((float)info->nTS/ tilesTS)) : info->nTS) : info->nTS; + + /*--------------------------------------------------------*\ + ! Check if the tile sizes have valid values. ! + \*--------------------------------------------------------*/ + if((control->tileSizeX < 16 && control->tileSizeX > info->nX)|| + (control->tileSizeY < 16 && control->tileSizeY > info->nY)|| + (control->tileSizeZ < 16 && control->tileSizeZ > info->nZ)|| + (control->tileSizeTS < 16 && control->tileSizeTS > info->nTS)) + { + fprintf(stderr,"o==========================================================o\n"\ + "| WARNING: Invalid Number Of Tiles |\n"\ + "| |\n"\ + "| One or more of the tile dimensions has a value |\n"\ + "| that falls outside of its valid range. Please |\n"\ + "| verify that the number of tiles for all dimen- |\n"\ + "| sions are set so that the corresponding tile |\n"\ + "| sizes fall within the range of: |\n"\ + "| |\n"\ + "| 16 ≤ Tile_Size_Xi ≤ Grid_Points_Xi |\n"\ + "| |\n"\ + "o==========================================================o\n"); + + /*--------------------------------------------------------*\ + ! Reset the tile sizes to their standard values. ! + \*--------------------------------------------------------*/ + control->tileSizeX = info->nX; + control->tileSizeY = info->nY; + control->tileSizeZ = info->nZ; + control->tileSizeTS = info->nTS; + + return; + } + /*--------------------------------------------------------*\ + ! Reevaluate the number of tiles in all spatial and tempo- ! + ! ral directions and the overall number of tiles. ! + \*--------------------------------------------------------*/ + num_tiles_X = (uint64)ceil(((float)info->nX / control->tileSizeX)); + num_tiles_Y = (uint64)ceil(((float)info->nY / control->tileSizeY)); + num_tiles_Z = (uint64)ceil(((float)info->nZ / control->tileSizeZ)); + num_tiles_TS = (uint16)ceil(((float)info->nTS/ control->tileSizeTS)); + control->nTiles = num_tiles_X * num_tiles_Y * num_tiles_Z * num_tiles_TS; + } + + /*--------------------------------------------------------*\ + ! Record the setting of the tile size variables in the ! + ! CSsgc variable. ! + \*--------------------------------------------------------*/ + control->CSsgc |= (0x01 << 9); +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void bwc_create_compression(bwc_field *field, char *rate_control) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function creates the field structure used to compress a floating point array defined ! +! by the bwc_initialize function. For a compression run, the rate_control and instr arguments ! +! need to be passed to the function to properly set up the lossy compression stage. Here, the ! +! instr parameter defines whether rate control is defined by a BITRATE - a floating point val-! +! ue defining the average number of bits per datapoint - and ACCURACY - an integer value de- ! +! fining the exponent of the maximum allowable error (i.e. 15 for err = 1e-15). ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! rate_control char* - Variable defining the bitrate. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 15.03.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! 05.12.2019 Patrick vogler B87E7E4 V 0.1.0 streamlined function arguments ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uchar +bwc_create_compression(bwc_field *field, char *rate_control) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + int8 l; + size_t size; + + /*-----------------------*\ + ! DEFINE FLOAT VARIABLES: ! + \*-----------------------*/ + float buf_f; + + /*-----------------------*\ + ! DEFINE CHAR VARIABLES: ! + \*-----------------------*/ + char *token, *ptr; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + + /*--------------------------------------------------------*\ + ! Save the global control structure to a temporary varia- ! + ! ble to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + + /*--------------------------------------------------------*\ + ! Allocate the array used to hold the quality layer bit- ! + ! rates with an initial size of 10. ! + \*--------------------------------------------------------*/ + size = 10; + control->bitrate = calloc(size, sizeof(float)); + if(!control->bitrate) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + /*--------------------------------------------------------*\ + ! Read the two additional arguments defining the rate con- ! + ! trol and accuracy parameters. ! + \*--------------------------------------------------------*/ + if(rate_control == NULL) + { + control->bitrate[0] = PREC_BIT + 1; + control->nLayers = 1; + } + else + { + token = strtok_r(rate_control, "-, ", &ptr); + + if(token) + { + for(control->nLayers = 0; token; token = strtok_r(NULL, "-, ", &ptr)) + { + buf_f = strtof(token, NULL); + + if(buf_f <= 0 || buf_f > 64) + { + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: Invalid bitrate value: %-25f|\n"\ + "| |\n"\ + "| The specified bitrate is not within its valid |\n"\ + "| range of: |\n"\ + "| |\n"\ + "| 0 < Bitrate ≤ 64 |\n"\ + "| |\n"\ + "o##########################################################o\n", buf_f); + return 1; + } + + if(((int8)size - control->nLayers) == 0) + { + size += 10; + control->bitrate = realloc(control->bitrate, size * sizeof(float)); + } + + for(l = control->nLayers; l >= 0; --l) + { + if(l && buf_f < control->bitrate[l - 1]) + { + control->bitrate[l] = control->bitrate[l - 1]; + } + else if (l && fabs(buf_f - control->bitrate[l - 1]) < 0.01f) + { + for(; l < control->nLayers; ++l) + { + control->bitrate[l] = control->bitrate[l + 1]; + } + break; + } + else + { + control->bitrate[l] = buf_f; + control->nLayers++; + break; + } + } + } + } + else + { + control->bitrate[0] = PREC_BIT + 1; + control->nLayers = 1; + } + } + + control->bitrate = realloc(control->bitrate, control->nLayers * sizeof(float)); + + /*--------------------------------------------------------*\ + ! Create the field structure used to compress a floating ! + ! point array defined by the bwc_initialize function. ! + \*--------------------------------------------------------*/ + if(create_field(field)) + { + return 1; + } + + /*--------------------------------------------------------*\ + ! Create the main header for the compressed codestream and ! + ! save the memory handle in the field structure. ! + \*--------------------------------------------------------*/ + if(assemble_main_header(field)) + { + return 1; + } + + return 0; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: uchar bwc_compress(bwc_field *const field, bwc_float *const data) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! Description needed. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! uchar - Returns an unsigned char for error handling. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 15.03.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uchar +bwc_compress(bwc_field *const field, bwc_data *const data) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 buff_size = 0; + uint64 i; + uint16 p; + + /*-----------------------*\ + ! DEFINE FLOAT VARIABLES: ! + \*-----------------------*/ + double start, end; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_gl_inf *info; + bwc_tile *tile; + bwc_parameter *parameter; + bwc_sample *working_buffer; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert(data); + + /*--------------------------------------------------------*\ + ! Initialize the compression time measurement. ! + \*--------------------------------------------------------*/ + #if defined (_OPENMP) + field->meter.time.ttl = omp_get_wtime(); + #else + field->meter.time.ttl = (double)clock(); + #endif + + /*--------------------------------------------------------*\ + ! Save the global control and info structure to temporary ! + ! variables to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + info = field->info; + + /*--------------------------------------------------------*\ + ! Check if any auxiliary information has been supplied by ! + ! the function caller and append the header accordingly. ! + \*--------------------------------------------------------*/ + if(data->codestream.aux && header_append_aux(field, data->codestream.aux)) + { + return 1; + } + + /*--------------------------------------------------------*\ + ! Check if any commentary information has been supplied by ! + ! the function caller and append the header accordingly. ! + \*--------------------------------------------------------*/ + if(data->codestream.com && header_append_com(field, data->codestream.com)) + { + return 1; + } + + /*--------------------------------------------------------*\ + ! Evaluate the working buffer size and allocate it accord- ! + ! ingly. ! + \*--------------------------------------------------------*/ + buff_size = control->tileSizeX * control->tileSizeY * + control->tileSizeZ * control->tileSizeTS; + + working_buffer = calloc(buff_size, sizeof(bwc_sample)); + if(!working_buffer) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + /*--------------------------------------------------------*\ + ! Walk through the tile structure and compress the speci- ! + ! fied data set. ! + \*--------------------------------------------------------*/ + for(i = 0; i < control->nTiles; ++i) + { + /*--------------------------------------------------------*\ + ! Save the tile structure in a temporary variable to make ! + ! the code more readable. ! + \*--------------------------------------------------------*/ + tile = &field->tile[i]; + + for(p = 0; p < info->nPar; ++p) + { + /*--------------------------------------------------------*\ + ! Save the parameter structure in a temporary variable to ! + ! make the code more readable. ! + \*--------------------------------------------------------*/ + parameter = &tile->parameter[p]; + + /*--------------------------------------------------------*\ + ! Fill the working buffer with the flow field data for the ! + ! current tile parameter. ! + \*--------------------------------------------------------*/ + #if defined (_OPENMP) + start = omp_get_wtime(); + #else + start = (double)clock(); + #endif + fill_buffer(field, tile, parameter, working_buffer, data, p); + #if defined (_OPENMP) + end = omp_get_wtime(); + field->meter.time.cpy += end - start; + #else + end = (double)clock(); + field->meter.time.cpy += (end - start)/CLOCKS_PER_SEC; + #endif + + /*--------------------------------------------------------*\ + ! Normalize the working buffer to a range of [-1,1) and ! + ! scale it to the dynamic range specified by the Qm param- ! + ! eter. ! + \*--------------------------------------------------------*/ + #if defined (_OPENMP) + start = omp_get_wtime(); + #else + start = (double)clock(); + #endif + normalize_param(field, parameter); + #if defined (_OPENMP) + end = omp_get_wtime(); + field->meter.time.nrm += end - start; + #else + end = (double)clock(); + field->meter.time.nrm += (end - start)/CLOCKS_PER_SEC; + #endif + + /*--------------------------------------------------------*\ + ! Perform the forward discrete wavelet transform. ! + \*--------------------------------------------------------*/ + #if defined (_OPENMP) + start = omp_get_wtime(); + #else + start = (double)clock(); + #endif + if(forward_wavelet_transform(field, parameter)) + { + free(working_buffer); + return 1; + } + #if defined (_OPENMP) + end = omp_get_wtime(); + field->meter.time.wav += end - start; + #else + end = (double)clock(); + field->meter.time.wav += (end - start)/CLOCKS_PER_SEC; + #endif + + /*--------------------------------------------------------*\ + ! Tier1 encode the current tile parameter. ! + \*--------------------------------------------------------*/ + #if defined (_OPENMP) + start = omp_get_wtime(); + #else + start = (double)clock(); + #endif + if(t1_encode(field, tile, parameter)) + { + free(working_buffer); + return 1; + } + #if defined (_OPENMP) + end = omp_get_wtime(); + field->meter.time.ent += end - start; + #else + end = (double)clock(); + field->meter.time.ent += (end - start)/CLOCKS_PER_SEC; + #endif + + /*--------------------------------------------------------*\ + ! Reset the working buffer memory block. ! + \*--------------------------------------------------------*/ + memset(working_buffer, 0, buff_size * sizeof(bwc_sample)); + parameter->data = NULL; + } + /*--------------------------------------------------------*\ + ! Tier2 encode the current tile. ! + \*--------------------------------------------------------*/ + #if defined (_OPENMP) + start = omp_get_wtime(); + #else + start = (double)clock(); + #endif + if(t2_encode(field, tile)) + { + free(working_buffer); + return 1; + } + #if defined (_OPENMP) + end = omp_get_wtime(); + field->meter.time.ent += end - start; + #else + end = (double)clock(); + field->meter.time.ent += (end - start)/CLOCKS_PER_SEC; + #endif + } + /*--------------------------------------------------------*\ + ! Assemble compressed codestream. ! + \*--------------------------------------------------------*/ + #if defined (_OPENMP) + start = omp_get_wtime(); + #else + start = (double)clock(); + #endif + data->codestream.data = assemble_codestream(field); + if(!data->codestream.data) + { + free(working_buffer); + return 1; + } + #if defined (_OPENMP) + end = omp_get_wtime(); + field->meter.time.ass += end - start; + #else + end = (double)clock(); + field->meter.time.ass += (end - start)/CLOCKS_PER_SEC; + #endif + + /*--------------------------------------------------------*\ + ! Free the working buffer. ! + \*--------------------------------------------------------*/ + free(working_buffer); + + /*--------------------------------------------------------*\ + ! Calculate the compression time. ! + \*--------------------------------------------------------*/ + #if defined (_OPENMP) + field->meter.time.ttl = omp_get_wtime() - field->meter.time.ttl; + #else + field->meter.time.ttl = ((double)clock() - field->meter.time.ttl)/CLOCKS_PER_SEC; + #endif + + /*--------------------------------------------------------*\ + ! Return to the function caller. ! + \*--------------------------------------------------------*/ + return 0; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: uchar bwc_create_compression(bwc_field *field_ptr, char *rate_control, uchar instr) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function parses the supplied bwc codestream and sets up the field structure used to ! +! decompress the numerical dataset. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! rate_control (opt) char* - Variable defining the bitrate/accuracy. ! +! ! +! instr (opt) bwc_rate_instr - Constants used to instruct the rate ! +! control information. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 15.03.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +bwc_field * +bwc_create_decompression(bwc_data *const data, uint8 layer) +{ + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_field *field; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(data); + + /*--------------------------------------------------------*\ + ! Parse the codestream and setup the field codestream. ! + \*--------------------------------------------------------*/ + field = parse_codestream(data, layer); + if(!field) + { + return NULL; + } + + /*--------------------------------------------------------*\ + ! If successful, return the field structure to the func- ! + ! tion caller. ! + \*--------------------------------------------------------*/ + return field; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: uchar bwc_create_compression(bwc_field *field, float rate_control, uchar instr) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function creates the field structure used to compress a floating point array defined ! +! by the bwc_initialize function at a prescribed bitrate or accuracy. In this context, the ! +! bitrate is a floating point value defining the average number of bits per datapoint and ! +! the accuracy is an integer value defining the exponent of the maximum allowable error ! +! (i.e. 15 for err = 1e-15). ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! rate_control float - Variable defining the bitrate/accuracy. ! +! ! +! instr unsigned char - Constants used to instruct the rate ! +! control information. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 15.03.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uchar +bwc_decompress(bwc_field *const field, bwc_data *const data) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 buff_size; + uint64 single_size, double_size; + uint64 i; + uint16 p; + + /*-----------------------*\ + ! DEFINE FLOAT VARIABLES: ! + \*-----------------------*/ + double start, end; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_gl_inf *info; + bwc_tile *tile; + bwc_parameter *parameter; + bwc_sample *working_buffer; + bwc_cmd_opts_ll *param; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert(data); + + /*--------------------------------------------------------*\ + ! Initialize the decompression time measurement. ! + \*--------------------------------------------------------*/ + #if defined (_OPENMP) + field->meter.time.ttl = omp_get_wtime(); + #else + field->meter.time.ttl = (double)clock(); + #endif + + /*--------------------------------------------------------*\ + ! Save the global control and info structure to temporary ! + ! variables to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + info = field->info; + + /*--------------------------------------------------------*\ + ! Calculate the field size after subsampling and allocate ! + ! the field memory blocks. ! + \*--------------------------------------------------------*/ + if(data->info.parameter) + { + param = data->info.parameter->root; + double_size = + single_size = 0; + + while(param != NULL) + { + if(param->precision == 8) + { + double_size += param->size; + } + else if (param->precision == 4) + { + single_size += param->size; + } + + param = param -> next; + } + } + + data->field.d = calloc(double_size, sizeof(double)); + data->field.f = calloc(single_size, sizeof(float)); + if(!data->field.d || !data->field.f) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + /*--------------------------------------------------------*\ + ! Evaluate the working buffer size and allocate it accord- ! + ! ingly. ! + \*--------------------------------------------------------*/ + buff_size = control->tileSizeX * control->tileSizeY * + control->tileSizeZ * control->tileSizeTS; + + working_buffer = calloc(buff_size, sizeof(bwc_sample)); + if(!working_buffer) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + /*--------------------------------------------------------*\ + ! Walk through the tile structure and decompress the speci-! + ! fied data set. ! + \*--------------------------------------------------------*/ + for(i = 0; i < control->nTiles; ++i) + { + /*--------------------------------------------------------*\ + ! Save the tile structure in a temporary variable to make ! + ! the code more readable. ! + \*--------------------------------------------------------*/ + tile = &field->tile[i]; + + for(p = 0; p < info->nPar; ++p) + { + /*--------------------------------------------------------*\ + ! Save the parameter structure in a temporary variable to ! + ! make the code more readable. ! + \*--------------------------------------------------------*/ + parameter = &tile->parameter[p]; + + /*--------------------------------------------------------*\ + ! Associate the working buffer with the data pointer in ! + ! the bwc_parameter structure. ! + \*--------------------------------------------------------*/ + parameter->data = working_buffer; + + /*--------------------------------------------------------*\ + ! Tier1 decode the current tile parameter. ! + \*--------------------------------------------------------*/ + #if defined (_OPENMP) + start = omp_get_wtime(); + #else + start = (double)clock(); + #endif + if(t1_decode(field, tile, parameter)) + { + free(working_buffer); + return 1; + } + #if defined (_OPENMP) + end = omp_get_wtime(); + field->meter.time.ent += end - start; + #else + end = (double)clock(); + field->meter.time.ent += (end - start)/CLOCKS_PER_SEC; + #endif + + /*--------------------------------------------------------*\ + ! Perform the inverse discrete wavelet transform. ! + \*--------------------------------------------------------*/ + #if defined (_OPENMP) + start = omp_get_wtime(); + #else + start = (double)clock(); + #endif + if(inverse_wavelet_transform(field, parameter)) + { + free(working_buffer); + return 1; + } + #if defined (_OPENMP) + end = omp_get_wtime(); + field->meter.time.wav += end - start; + #else + end = (double)clock(); + field->meter.time.wav += (end - start)/CLOCKS_PER_SEC; + #endif + + /*--------------------------------------------------------*\ + ! Denormalize the working buffer scale it to the original ! + ! dynamic range specified by the Qm parameter. ! + \*--------------------------------------------------------*/ + #if defined (_OPENMP) + start = omp_get_wtime(); + #else + start = (double)clock(); + #endif + denormalize_param(field, parameter); + #if defined (_OPENMP) + end = omp_get_wtime(); + field->meter.time.nrm += end - start; + #else + end = (double)clock(); + field->meter.time.nrm += (end - start)/CLOCKS_PER_SEC; + #endif + + /*--------------------------------------------------------*\ + ! Flush the working buffer to the appropriate memory block ! + ! in the flow field data structure for the current tile pa-! + ! rameter. ! + \*--------------------------------------------------------*/ + #if defined (_OPENMP) + start = omp_get_wtime(); + #else + start = (double)clock(); + #endif + flush_buffer(field, tile, parameter, working_buffer, data, p); + #if defined (_OPENMP) + end = omp_get_wtime(); + field->meter.time.cpy += end - start; + #else + end = (double)clock(); + field->meter.time.cpy += (end - start)/CLOCKS_PER_SEC; + #endif + + /*--------------------------------------------------------*\ + ! Reset the working buffer memory block. ! + \*--------------------------------------------------------*/ + memset(working_buffer, 0, buff_size * sizeof(bwc_sample)); + parameter->data = NULL; + } + } + + /*--------------------------------------------------------*\ + ! Free the working buffer. ! + \*--------------------------------------------------------*/ + free(working_buffer); + + /*--------------------------------------------------------*\ + ! Calculate the decompression time. ! + \*--------------------------------------------------------*/ + #if defined (_OPENMP) + field->meter.time.ttl = omp_get_wtime() - field->meter.time.ttl; + #else + field->meter.time.ttl = ((double)clock() - field->meter.time.ttl)/CLOCKS_PER_SEC; + #endif + + return 0; +} \ No newline at end of file diff --git a/1-bwc/src/library/mq.c b/1-bwc/src/library/mq.c new file mode 100755 index 0000000..ff77754 --- /dev/null +++ b/1-bwc/src/library/mq.c @@ -0,0 +1,1175 @@ +/*================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| DESCRIPTION: || +|| ------------ || +|| || +|| DESCRIPTION NEEDED. || +|| | | || +|| || +|| -------------------------------------------------------------------------------------------- || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are || +|| permitted provided that the following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of || +|| conditions and the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || +|| of conditions and the following disclaimer in the documentation and/or other || +|| materials provided with the distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS || +|| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF || +|| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE || +|| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, || +|| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF || +|| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) || +|| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || +|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, || +|| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*================================================================================================*/ +/************************************************************************************************************\ +|| _ _ _ ____ _ _ _ ___ ____ || +|| | |\ | | | | | | \ |___ || +|| | | \| |___ |___ |__| |__/ |___ || +|| || +\************************************************************************************************************/ +#include +#include +#include +#include + +#include "macros.h" +#include "mq.h" +#include "tier1.h" +#include "types.h" + +/************************************************************************************************************\ +|| _ _ ____ ____ ____ ____ ____ || +|| |\/| |__| | |__/ | | [__ || +|| | | | | |___ | \ |__| ___] || +|| || +\************************************************************************************************************/ +/*----------------------------------------------------------------------------------------------------------*\ +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! Macros: ! +! ------- ! +! Macro Description ! +! ----- ----------- ! +! ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 22.02.2019 Patrick Vogler B87D120 V 0.1.0 Macros created ! +\*----------------------------------------------------------------------------------------------------------*/ +#define transfer_byte(state) \ +{ \ + if(state->T == 0xFF) \ + { \ + if(state->L >= 0) \ + { \ + state->b[state->L] = state->T; \ + } \ + \ + state->L++; \ + state->T = (uchar)(state->C >> 0x14); \ + state->C &= 0xFFFFF; \ + state->t = 0x07; \ + } \ + else \ + { \ + if(state->C & 0x8000000) \ + { \ + state->T++; \ + state->C &= 0x7FFFFFF; \ + } \ + \ + if(state->L >= 0) \ + { \ + state->b[state->L] = state->T; \ + } \ + \ + state->L++; \ + \ + if(state->T == 0xFF) \ + { \ + state->T = (uchar)(state->C >> 0x14); \ + state->C &= 0xFFFFF; \ + state->t = 0x07; \ + } \ + else \ + { \ + state->T = (uchar)(state->C >> 0x13); \ + state->C &= 0x7FFFF; \ + state->t = 0x08; \ + } \ + } \ +} + +/*----------------------------------------------------------------------------------------------------------*\ +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! Macros: ! +! ------- ! +! Macro Description ! +! ----- ----------- ! +! ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 22.02.2019 Patrick Vogler B87D120 V 0.1.0 Macros created ! +\*----------------------------------------------------------------------------------------------------------*/ +#define fill_lsb(state, bitcoder) \ +{ \ + if((state->L == bitcoder->Lmax) || \ + ((state->T == 0xFF) && \ + (state->b[state->L] > 0x8f) )) \ + { \ + state->t = 8; \ + state->C += 0xFF; \ + } \ + else \ + { \ + if((state->T == 0xFF)) \ + { \ + state->t = 7; \ + state->T = state->b[state->L]; \ + state->C += (uint32)state->T << 1; \ + state->L++; \ + } \ + else \ + { \ + state->t = 8; \ + state->T = state->b[state->L]; \ + state->C += (uint32)state->T; \ + state->L++; \ + } \ + } \ +} + +/************************************************************************************************************\ +|| ____ ____ _ _ ____ ___ ____ _ _ ___ ____ || +|| | | | |\ | [__ | |__| |\ | | [__ || +|| |___ |__| | \| ___] | | | | \| | ___] || +|| || +\************************************************************************************************************/ +/*----------------------------------------------------------------------------------------------------------*\ +! DESCRIPTION: ! +! ------------ ! +! These constants define the probability state transition table as described in JPEG2000 by ! +! David S. Taubman and Michael W. Marcellin (p. 75). In order to avoid the the Most Probable ! +! Symbol and Least Probable Symbol exchange during encoding, the table has been expanded to ! +! store the Most Probable Symbol sk instead of the function Xs. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 19.02.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static const bwc_context_state context_state[94] = +{{0x5601, 0, &context_state[ 1], &context_state[48]}, + {0x3401, 0, &context_state[ 2], &context_state[ 6]}, + {0x1801, 0, &context_state[ 3], &context_state[ 9]}, + {0x0AC1, 0, &context_state[ 4], &context_state[12]}, + {0x0521, 0, &context_state[ 5], &context_state[29]}, + {0x0221, 0, &context_state[38], &context_state[33]}, + {0x5601, 0, &context_state[ 7], &context_state[53]}, + {0x5401, 0, &context_state[ 8], &context_state[14]}, + {0x4801, 0, &context_state[ 9], &context_state[14]}, + {0x3801, 0, &context_state[10], &context_state[14]}, + {0x3001, 0, &context_state[11], &context_state[17]}, + {0x2401, 0, &context_state[12], &context_state[18]}, + {0x1C01, 0, &context_state[13], &context_state[20]}, + {0x1601, 0, &context_state[29], &context_state[21]}, + {0x5601, 0, &context_state[15], &context_state[61]}, + {0x5401, 0, &context_state[16], &context_state[14]}, + {0x5101, 0, &context_state[17], &context_state[15]}, + {0x4801, 0, &context_state[18], &context_state[16]}, + {0x3801, 0, &context_state[19], &context_state[17]}, + {0x3401, 0, &context_state[20], &context_state[18]}, + {0x3001, 0, &context_state[21], &context_state[19]}, + {0x2801, 0, &context_state[22], &context_state[19]}, + {0x2401, 0, &context_state[23], &context_state[20]}, + {0x2201, 0, &context_state[24], &context_state[21]}, + {0x1C01, 0, &context_state[25], &context_state[22]}, + {0x1801, 0, &context_state[26], &context_state[23]}, + {0x1601, 0, &context_state[27], &context_state[24]}, + {0x1401, 0, &context_state[28], &context_state[25]}, + {0x1201, 0, &context_state[29], &context_state[26]}, + {0x1101, 0, &context_state[30], &context_state[27]}, + {0x0AC1, 0, &context_state[31], &context_state[28]}, + {0x09C1, 0, &context_state[32], &context_state[29]}, + {0x08A1, 0, &context_state[33], &context_state[30]}, + {0x0521, 0, &context_state[34], &context_state[31]}, + {0x0441, 0, &context_state[35], &context_state[32]}, + {0x02A1, 0, &context_state[36], &context_state[33]}, + {0x0221, 0, &context_state[37], &context_state[34]}, + {0x0141, 0, &context_state[38], &context_state[35]}, + {0x0111, 0, &context_state[39], &context_state[36]}, + {0x0085, 0, &context_state[40], &context_state[37]}, + {0x0049, 0, &context_state[41], &context_state[38]}, + {0x0025, 0, &context_state[42], &context_state[39]}, + {0x0015, 0, &context_state[43], &context_state[40]}, + {0x0009, 0, &context_state[44], &context_state[41]}, + {0x0005, 0, &context_state[45], &context_state[42]}, + {0x0001, 0, &context_state[45], &context_state[43]}, + {0x5601, 0, &context_state[46], &context_state[46]}, + {0x5601, 1, &context_state[48], &context_state[ 1]}, + {0x3401, 1, &context_state[49], &context_state[53]}, + {0x1801, 1, &context_state[50], &context_state[56]}, + {0x0AC1, 1, &context_state[51], &context_state[59]}, + {0x0521, 1, &context_state[52], &context_state[76]}, + {0x0221, 1, &context_state[85], &context_state[80]}, + {0x5601, 1, &context_state[54], &context_state[ 6]}, + {0x5401, 1, &context_state[55], &context_state[61]}, + {0x4801, 1, &context_state[56], &context_state[61]}, + {0x3801, 1, &context_state[57], &context_state[61]}, + {0x3001, 1, &context_state[58], &context_state[64]}, + {0x2401, 1, &context_state[59], &context_state[65]}, + {0x1C01, 1, &context_state[60], &context_state[67]}, + {0x1601, 1, &context_state[76], &context_state[68]}, + {0x5601, 1, &context_state[62], &context_state[14]}, + {0x5401, 1, &context_state[63], &context_state[61]}, + {0x5101, 1, &context_state[64], &context_state[62]}, + {0x4801, 1, &context_state[65], &context_state[63]}, + {0x3801, 1, &context_state[66], &context_state[64]}, + {0x3401, 1, &context_state[67], &context_state[65]}, + {0x3001, 1, &context_state[68], &context_state[66]}, + {0x2801, 1, &context_state[69], &context_state[66]}, + {0x2401, 1, &context_state[70], &context_state[67]}, + {0x2201, 1, &context_state[71], &context_state[68]}, + {0x1C01, 1, &context_state[72], &context_state[69]}, + {0x1801, 1, &context_state[73], &context_state[70]}, + {0x1601, 1, &context_state[74], &context_state[71]}, + {0x1401, 1, &context_state[75], &context_state[72]}, + {0x1201, 1, &context_state[76], &context_state[73]}, + {0x1101, 1, &context_state[77], &context_state[74]}, + {0x0AC1, 1, &context_state[78], &context_state[75]}, + {0x09C1, 1, &context_state[79], &context_state[76]}, + {0x08A1, 1, &context_state[80], &context_state[77]}, + {0x0521, 1, &context_state[81], &context_state[78]}, + {0x0441, 1, &context_state[82], &context_state[79]}, + {0x02A1, 1, &context_state[83], &context_state[80]}, + {0x0221, 1, &context_state[84], &context_state[81]}, + {0x0141, 1, &context_state[85], &context_state[82]}, + {0x0111, 1, &context_state[86], &context_state[83]}, + {0x0085, 1, &context_state[87], &context_state[84]}, + {0x0049, 1, &context_state[88], &context_state[85]}, + {0x0025, 1, &context_state[89], &context_state[86]}, + {0x0015, 1, &context_state[90], &context_state[87]}, + {0x0009, 1, &context_state[91], &context_state[88]}, + {0x0005, 1, &context_state[92], &context_state[89]}, + {0x0001, 1, &context_state[92], &context_state[90]}, + {0x5601, 1, &context_state[93], &context_state[93]}}; + +/************************************************************************************************************\ +|| ___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || +|| |__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ || +|| | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] || +|| || +\************************************************************************************************************/ +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void initialize_bit_encoder(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 19.02.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uchar +initialize_mq_encoder(bwc_coder *const coder, const uint8 number_of_contexts) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint8 i; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_bit_coder *bitcoder; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(coder); + assert(coder->compressed); + + coder->bitcoder = calloc(1, sizeof(bwc_bit_coder)); + if(!coder->bitcoder) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + bitcoder = coder->bitcoder; + + bitcoder->nContext = number_of_contexts; + + bitcoder->b = coder->compressed; + + bitcoder->context = calloc(bitcoder->nContext, sizeof(bwc_context_state*)); + if(!bitcoder->context) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + for(i = 0; i < number_of_contexts; ++i) + { + bitcoder->context[i] = &context_state[0]; + } + + bitcoder->context[CONTEXT_SIG] = &context_state[ 4]; + bitcoder->context[CONTEXT_RUN] = &context_state[ 3]; + bitcoder->context[CONTEXT_UNI] = &context_state[46]; + + return 0; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void initialize_bit_encoder(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 19.02.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uchar +mq_next_run(bwc_bit_coder *const bitcoder) +{ + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_coder_state *state; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(bitcoder); + + state = calloc(1, sizeof(bwc_coder_state)); + if(!state) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + if(bitcoder->state) + { + memcpy(state, bitcoder->state, sizeof(bwc_coder_state)); + state->prev = bitcoder->state; + bitcoder->state->next = state; + bitcoder->state = state; + } + else + { + bitcoder->state = state; + bitcoder->state->b = bitcoder->b; + + state->A = 0x8000; + state->t = 0x000C; + state->L = -0x0001; + } + + return 0; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void initialize_bit_encoder(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 19.02.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +mq_bit_encode(bwc_bit_coder *const bitcoder, const uint8 s, const uint8 k) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint16 p; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(bitcoder); + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_context_state const **context; + bwc_coder_state *state; + + context = bitcoder->context; + state = bitcoder->state; + + p = context[k]->p; + + state->A -= p; + + if(s == context[k]->sk) + { + if(state->A >= 0x8000) + { + state->C += p; + } + else + { + if(state->A < p) + { + state->A = p; + } + else + { + state->C += p; + } + context[k] = context[k]->MPS; + + do + { + state->A <<= 1; + state->C <<= 1; + state->t --; + if(state->t == 0) + { + transfer_byte(state); + } + } while (state->A < 0x8000); + } + } + else + { + if(state->A < p) + { + state->C += p; + } + else + { + state->A = p; + } + context[k] = context[k]->LPS; + + do + { + state->A <<= 1; + state->C <<= 1; + state->t --; + if(state->t == 0) + { + transfer_byte(state); + } + } while (state->A < 0x8000); + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void initialize_bit_encoder(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 19.02.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +mq_truncation_length_min(bwc_coder_state *const state) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + #ifdef BWC_SINGLE_PRECISION + int32 buff, CrDec, CrFrac; + int32 CArDec, CArFrac; + uint8 s; + #else + int64 buff, Cr, CAr; + int8 s; + #endif + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(state); + + #ifdef BWC_SINGLE_PRECISION + CrFrac = (int32)state->C << state->t; + CArFrac = ((int32)state->A << state->t) + CrFrac; + + CrDec = state->T; + CArDec = state->T; + + CrDec += 0x01 & (CrFrac >> 27); + CArDec += 0x01 & (CArFrac >> 27); + + CrFrac &= 0x7FFFFFF; + CArFrac &= 0x7FFFFFF; + + s = 8; + + while((CrDec > 0xff) || + (CArDec <= 0xff)) + { + buff = (state->L >= 0) ? (int32)state->b[state->L] : 0; + state->L++; + + CrDec -= buff << (8 - s); + CArDec -= buff << (8 - s); + + CrDec <<= s; + CArDec <<= s; + + CrDec += CrFrac >> (27 - s); + CArDec += CArFrac >> (27 - s); + + CrFrac <<= s; + CArFrac <<= s; + + CrFrac &= 0x7FFFFFF; + CArFrac &= 0x7FFFFFF; + + s = (buff == 0xFF) ? 7 : 8; + } + #else + Cr = ((int64)state->T << 27) + + ((int64)state->C << state->t); + CAr = ((int64)state->A << state->t) + Cr; + s = 8; + + while(((Cr >> 27) > 0xff) || + ((CAr >> 27) <= 0xff)) + { + buff = (state->L >= 0) ? (int64)state->b[state->L] : 0; + state->L++; + + Cr -= buff << (35 - s); + CAr -= buff << (35 - s); + + Cr <<= s; + CAr <<= s; + + s = (buff == 0xFF) ? 7 : 8; + } + #endif + + if(state->L > 0 && (state->b[state->L - 1] == 0xFF)) + { + state->L--; + } + while(state->L > 1 && (state->b[state->L - 2] == 0xFF) && + (state->b[state->L - 1] == 0x7F)) + { + state->L -= 2; + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void initialize_bit_encoder(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 19.02.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +mq_termination(bwc_bit_coder *const bitcoder) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + int8 n; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_coder_state buff; + bwc_coder_state *state; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(bitcoder); + + state = bitcoder->state; + + buff.A = state->A; + buff.C = state->C; + buff.L = state->L; + buff.T = state->T; + buff.t = state->t; + + n = 12 - state->t; + state->C <<= state->t; + + while(n > 0) + { + transfer_byte(state); + n -= state->t; + state->C <<= state->t; + } + transfer_byte(state); + + state->A = buff.A; + state->C = buff.C; + state->L = buff.L; + state->T = buff.T; + state->t = buff.t; + + while(state->prev) + { + state = state->prev; + } + + while(state) + { + mq_truncation_length_min(state); + state = state->next; + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void initialize_bit_encoder(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 19.02.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +free_mq_encoder(bwc_coder *const coder) +{ + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(coder); + + if(coder->bitcoder) + { + while(coder->bitcoder->state->next) + { + coder->bitcoder->state = coder->bitcoder->state->next; + } + + while(coder->bitcoder->state->prev) + { + coder->bitcoder->state = coder->bitcoder->state->prev; + free(coder->bitcoder->state->next); + } + + free(coder->bitcoder->state); + free(coder->bitcoder->context); + } + + free(coder->bitcoder); +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void initialize_bit_encoder(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 19.02.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uchar +initialize_mq_decoder(bwc_coder *const coder, const uint8 number_of_contexts, const int64 Lmax) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint8 i; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_bit_coder *bitcoder; + bwc_coder_state *state; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(coder); + assert(coder->compressed); + + coder->bitcoder = calloc(1, sizeof(bwc_bit_coder)); + if(!coder->bitcoder) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + bitcoder = coder->bitcoder; + + bitcoder->Lmax = Lmax; + bitcoder->nContext = number_of_contexts; + + bitcoder->b = coder->compressed; + + bitcoder->context = calloc(bitcoder->nContext, sizeof(bwc_context_state*)); + if(!bitcoder->context) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + for(i = 0; i < number_of_contexts; ++i) + { + bitcoder->context[i] = &context_state[0]; + } + + bitcoder->context[CONTEXT_SIG] = &context_state[ 4]; + bitcoder->context[CONTEXT_RUN] = &context_state[ 3]; + bitcoder->context[CONTEXT_UNI] = &context_state[46]; + + bitcoder->state = calloc(1, sizeof(bwc_coder_state)); + if(!bitcoder->state) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + state = bitcoder->state; + state->b = coder->compressed; + + fill_lsb(state, bitcoder); + + state->C <<= 0x08; + + fill_lsb(state, bitcoder); + + state->C <<= 0x07; + state->t -= 0x07; + state->A = 0x8000; + + return 0; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void initialize_bit_encoder(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 19.02.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uint8 +mq_bit_decode(bwc_bit_coder *const bitcoder, const uint8 k) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint16 p; + uint8 x; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(bitcoder); + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_context_state const **context; + bwc_coder_state *state; + + context = bitcoder->context; + state = bitcoder->state; + + p = context[k]->p; + x = context[k]->sk; + + state->A -= p; + + if((state->C >> 8) >= p) + { + state->C -= p << 8; + state->C &= 0xFFFFFF; + if(~state->A & 0x8000) + { + if(state->A < p) + { + x = 1 - x; + context[k] = context[k]->LPS; + } + else + { + context[k] = context[k]->MPS; + } + do + { + if(state->t == 0) + { + fill_lsb(state, bitcoder); + } + state->A <<= 1; + state->C <<= 1; + state->t -= 1; + } while (~state->A & 0x8000); + } + } + else + { + if(state->A MPS; + } + else + { + x = 1 - x; + context[k] = context[k]->LPS; + } + state->A = p; + do + { + if(state->t == 0) + { + fill_lsb(state, bitcoder); + } + state->A <<= 1; + state->C <<= 1; + state->t -= 1; + } while (~state->A & 0x8000); + } + + return x; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void initialize_bit_encoder(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 19.02.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uint64 +mq_get_no_bytes(bwc_bit_coder *const bitcoder) +{ + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(bitcoder); + + return (uint64)(bitcoder->state->b - bitcoder->b) + bitcoder->state->L; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void initialize_bit_encoder(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 19.02.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +mq_reset_ptr(bwc_bit_coder *const bitcoder, uchar *const memory) +{ + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_coder_state *state; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(bitcoder); + + state = bitcoder->state; + + bitcoder->b = memory; + + while(state) + { + state->b = memory; + state = state->prev; + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void initialize_bit_encoder(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 19.02.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +mq_get_pass_lengths(bwc_bit_coder *const bitcoder, bwc_encoded_cblk *const encoded_cblk) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint8 j; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_coder_state *state; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(bitcoder); + assert(encoded_cblk); + + state = bitcoder->state; + + for(j = encoded_cblk->Z; (j --> 0) && state; state = state->prev) + { + encoded_cblk->L[j] = (uint64)(state->b - bitcoder->b) + state->L; + } +} \ No newline at end of file diff --git a/1-bwc/src/library/tagtree.c b/1-bwc/src/library/tagtree.c new file mode 100755 index 0000000..9ba1554 --- /dev/null +++ b/1-bwc/src/library/tagtree.c @@ -0,0 +1,573 @@ +/*================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| DESCRIPTION: || +|| ------------ || +|| || +|| This file defines a tagtree procedure used to encode/decode two types of || +|| information found defining in a codeblock in specific quality layer: || +|| || +|| - The inclusion tag records if a codeblock has any contribution || +|| to a quality layer. || +|| - The number of leading bitplanes that are not significant/only || +|| populated by zero bits. || +|| || +|| For more information on the encoding/decoding process please refere to JPEG2000 || +|| by D. S. Taubman and M. W. Marcellin (p. 384). || +|| || +|| -------------------------------------------------------------------------------------------- || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are || +|| permitted provided that the following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of || +|| conditions and the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || +|| of conditions and the following disclaimer in the documentation and/or other || +|| materials provided with the distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS || +|| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF || +|| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE || +|| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, || +|| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF || +|| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) || +|| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || +|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, || +|| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*================================================================================================*/ +/************************************************************************************************************\ +|| _ _ _ ____ _ _ _ ___ ____ || +|| | |\ | | | | | | \ |___ || +|| | | \| |___ |___ |__| |__/ |___ || +|| || +\************************************************************************************************************/ +#include +#include +#include + +#include "bitstream.h" +#include "macros.h" +#include "types.h" +#include "tagtree.h" + +/************************************************************************************************************\ +|| ___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || +|| |__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ || +|| | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] || +|| || +\************************************************************************************************************/ +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void kill_tagtree(bwc_tagtree* tagtree) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function deallocates a tagtree instance used to encode codeblock contributions to a ! +! specific quality layer as well as the number of magnitude bit planes used to represent the ! +! samples of a specific codeblock. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! tagtree bwc_tagtree* - Structure defining a tagtree instance. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 14.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +kill_tagtree(bwc_tagtree* tagtree) +{ + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(tagtree); + + free(tagtree->nodes); + free(tagtree); + return; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 14.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +reset_tagtree(bwc_tagtree* const tagtree) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 i = 0; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(tagtree); + + do + { + tagtree->nodes[i].value = 0xFFFF; + tagtree->nodes[i].threshold = 0; + }while(tagtree->nodes[i++].parent); +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 14.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uint16 +tagtree_get_value(const bwc_tagtree* const tagtree, const uint64 leaf_index) +{ + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(tagtree); + assert(leaf_index < tagtree->leavesX * tagtree->leavesY * tagtree->leavesZ * tagtree->leavesTS); + assert(tagtree->nodes[leaf_index].value != 0xFFFF); + + return tagtree->nodes[leaf_index].value; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 14.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +tagtree_set_value(bwc_tagtree* const tagtree, const uint64 leaf_index, const uint16 value) +{ + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_tagtree_node *node; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(tagtree); + assert(leaf_index < tagtree->leavesX * tagtree->leavesY * tagtree->leavesZ * tagtree->leavesTS); + assert(tagtree->nodes[leaf_index].value == 0xFFFF); + assert(value < 0xFFFF); + + node = &tagtree->nodes[leaf_index]; + + do + { + node->value = value; + node = node->parent; + }while(node && (node->value > value)); +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 14.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +bwc_tagtree* +initialize_tagtree(const uint64 leafsX, const uint64 leafsY, const uint64 leafsZ, const uint64 leafsTS) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 levels, number_of_nodes; + uint32 nlX[32] = {0}, nlY[32] = {0}, nlZ[32] = {0}, nlTS[32] = {0}; + uint32 i, j, k, l, n; + uint16 a,b,c,d; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_tagtree_node *node, *parent_x, *parent_y, *parent_z, *parent_ts; + bwc_tagtree *tagtree; + + for(nlX[0] = leafsX, nlY[0] = leafsY, + nlZ[0] = leafsZ, nlTS[0] = leafsTS, + levels = 0, number_of_nodes = 1; + nlX[levels] * nlY[levels] * + nlZ[levels] * nlTS[levels] > 1; + ++levels) + { + number_of_nodes += nlX[levels] * nlY[levels] * nlZ[levels] * nlTS[levels]; + nlX[levels + 1] = (nlX[levels] + 1) >> 1; + nlY[levels + 1] = (nlY[levels] + 1) >> 1; + nlZ[levels + 1] = (nlZ[levels] + 1) >> 1; + nlTS[levels + 1] = (nlTS[levels] + 1) >> 1; + } + + tagtree = calloc(1, sizeof(bwc_tagtree)); + if (!tagtree) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 0; + } + + tagtree->nodes = calloc(number_of_nodes, sizeof(bwc_tagtree_node)); + if (!tagtree->nodes) + { + // memory allocation error + fprintf(stderr, MEMERROR); + free(tagtree); + return 0; + } + + node = tagtree->nodes; + + for(i = 0; i < number_of_nodes; ++i) + { + node->index = i; + ++node; + } + + tagtree->leavesX = leafsX; + tagtree->leavesY = leafsY; + tagtree->leavesZ = leafsZ; + tagtree->leavesTS = leafsTS; + + parent_ts = tagtree->nodes; + node = tagtree->nodes; + for(n = 0; n < levels; ++n) + { + parent_ts += (uint32)(nlX[n] * nlY[n] * nlZ[n] * nlTS[n]); + for(l = 0, d = 0; l < nlTS[n]; ++l, ++d) + { + if(d >> 1) + { + parent_ts += nlX[n+1] * nlY[n+1] * nlZ[n+1]; + d = 0; + } + for(k = 0, c = 0, parent_z = parent_ts; k < nlZ[n]; ++k, ++c) + { + if(c >> 1) + { + parent_z += nlX[n+1] * nlY[n+1]; + c = 0; + } + for(j = 0, b = 0, parent_y = parent_z; j < nlY[n]; ++j, ++b) + { + if(b >> 1) + { + parent_y += nlX[n+1]; + b = 0; + } + for(i = 0, a = 0, parent_x = parent_y; i < nlX[n]; ++i, ++a) + { + if(a >> 1) + { + parent_x++; + a = 0; + } + node->parent = parent_x; + node++; + } + } + } + } + } + reset_tagtree(tagtree); + return tagtree; +} + + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 14.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +void +encode_tagtree(bwc_tagtree *const tagtree, bitstream *const stream, const uint32 threshold, const uint32 leaf_index, const uchar estimate) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint32 threshold_tmp, threshold_min; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_tagtree_node *node; + bwc_tagtree_node **branch_ptr, *branch[32]; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(tagtree); + assert(stream); + assert(leaf_index < (tagtree->leavesX * tagtree->leavesY * tagtree->leavesZ * tagtree->leavesTS)); + + node = &tagtree->nodes[leaf_index]; + branch_ptr = branch; + + while(node->parent) + { + *branch_ptr++ = node; + node = node->parent; + } + + for(threshold_min = 0; ; node = *--branch_ptr) + { + threshold_tmp = node->threshold; + + if(threshold_tmp < threshold_min) + { + threshold_tmp = threshold_min; + } + while((node->value >= threshold_tmp) && (threshold_tmp < threshold)) //this conditional jump needs to be checked + { + threshold_tmp++; + if(node->value >= threshold_tmp) + { + emit_bit(stream, 0); + } + else + { + emit_bit(stream, 1); + } + } + + threshold_min = MIN(node->value, threshold_tmp); + + if(!estimate) + { + node->threshold = threshold_tmp; + } + + if(node == &tagtree->nodes[leaf_index]) + { + break; + } + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 14.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uchar +decode_tagtree(bwc_tagtree *const tagtree, bitstream *const stream, const uint32 threshold, const uint32 leaf_index) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint32 threshold_min; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_tagtree_node *node; + bwc_tagtree_node **branch_ptr, *branch[32]; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(tagtree); + assert(stream); + assert(leaf_index < (tagtree->leavesX * tagtree->leavesY * tagtree->leavesZ * tagtree->leavesTS)); + + node = &tagtree->nodes[leaf_index]; + branch_ptr = branch; + + while(node) + { + if(node->value == 0xFFFF) + { + node->value = 0; + } + + *branch_ptr++ = node; + node = node->parent; + } + + for(*branch_ptr--, node = *branch_ptr--, threshold_min = 0; ; node = *branch_ptr--) + { + if(node->threshold < threshold_min) + { + node->value = threshold_min; + node->threshold = threshold_min; + } + while((node->value == node->threshold) && (node->threshold < threshold)) + { + node->threshold++; + if(!get_bit(stream)) + { + node->value++; + } + } + + threshold_min = MIN(node->value, node->threshold); + + if(node == &tagtree->nodes[leaf_index]) + { + break; + } + } + return (node->value < threshold) ? 0 : 1; +} \ No newline at end of file diff --git a/1-bwc/src/library/tier1.c b/1-bwc/src/library/tier1.c new file mode 100755 index 0000000..fce996e --- /dev/null +++ b/1-bwc/src/library/tier1.c @@ -0,0 +1,3361 @@ +/*================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| DESCRIPTION: || +|| ------------ || +|| || +|| This file describes a set of functions that can be used to de-/encode bwc || +|| codeblocks described by the bwc_field structure according to the embedded block || +|| coding paradigm described by the JPEG 2000 standard. For more information please || +|| refere to JPEG2000 by D. S. Taubman and M. W. Marcellin. || +|| || +|| -------------------------------------------------------------------------------------------- || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are || +|| permitted provided that the following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of || +|| conditions and the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || +|| of conditions and the following disclaimer in the documentation and/or other || +|| materials provided with the distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS || +|| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF || +|| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE || +|| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, || +|| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF || +|| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) || +|| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || +|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, || +|| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*================================================================================================*/ +/************************************************************************************************************\ +|| _ _ _ ____ _ _ _ ___ ____ || +|| | |\ | | | | | | \ |___ || +|| | | \| |___ |___ |__| |__/ |___ || +|| || +\************************************************************************************************************/ +#include +#include +#include +#include +#include +#include +#include + +#include "constants.h" +#include "macros.h" +#include "types.h" +#include "dwt.h" +#include "mq.h" +#include "tier1.h" + +/************************************************************************************************************\ +|| _ _ ____ ____ ____ ____ ____ || +|| |\/| |__| | |__/ | | [__ || +|| | | | | |___ | \ |__| ___] || +|| || +\************************************************************************************************************/ +/*----------------------------------------------------------------------------------------------------------*\ +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! Macros: ! +! ------- ! +! Macro Description ! +! ----- ----------- ! +! ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 01.02.2019 Patrick Vogler B87D120 V 0.1.0 Macros created ! +\*----------------------------------------------------------------------------------------------------------*/ +#define encode_segmark(bitcoder) \ +{ \ + mq_bit_encode(bitcoder, 1, CONTEXT_UNI); \ + mq_bit_encode(bitcoder, 0, CONTEXT_UNI); \ + mq_bit_encode(bitcoder, 1, CONTEXT_UNI); \ + mq_bit_encode(bitcoder, 0, CONTEXT_UNI); \ +} + +/************************************************************************************************************\ +|| ____ _ _ ___ ____ ____ _ _ ____ _ ____ ____ _ _ ____ ___ ____ _ _ ___ ____ || +|| |___ \/ | |___ |__/ |\ | |__| | | | | |\ | [__ | |__| |\ | | [__ || +|| |___ _/\_ | |___ | \ | \| | | |___ |___ |__| | \| ___] | | | | \| | ___] || +|| || +\************************************************************************************************************/ +/*----------------------------------------------------------------------------------------------------------*\ +! DESCRIPTION: ! +! ------------ ! +! These constants define the distortion estimation for the significance propagation (TS) ! +! and magnitude refinement (TM) pass as lookup tables. These lookup tables were evaluated ! +! using the appropriate equations from JPEG2000 by David S. Taubman and Michael W. Marcellin ! +! (p. 378): ! +! ! +! 𝛥D_i^(p,k) = G_bi × 𝛥_i^2 × 2^2p × ! +! ┌ ! +! | ∑_{j∈P_i^(p,k), ν_i^p = 1} TS(νtilde_i^(p+1)[j]) + ! +! └ ┐ ! +! ∑_{j∈P_i^(p,k), ν_i^p>1} TM(νtilde_i^(p+1)[j]) | ! +! ┘ ! +! TS(νtilde) = (2νtilde)^2 - (2νtilde - 1 - δ)^2 ! +! TM(νtilde) = (2νtilde - 1)^2 - (2νtilde - ⌊2νtilde^(p+1)⌋ - δ)^2 ! +! ! +! here 𝛥D_i^(p,k) describes the aggregate distortion contribution, G_bi the energy gain fac- ! +! tor for subband b_i, 𝛥_i the quantization step-size, ν_i the quantization magnitude, νtilde ! +! the fraction part of ν_i, ν_i^p the quantization magnitude obtained by dropping the last p ! +! bits of v_i and TS/TM the respective lookup tables. The index p is used to identify a spe- ! +! cific bitplane. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 23.01.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static const int32 DISTORTION_TM_LUT[64] = +{49152, 47104, 45056, 43008, + 40960, 38912, 36864, 34816, + 32768, 30720, 28672, 26624, + 24576, 22528, 20480, 18432, + 16384, 14336, 12288, 10240, + 8192, 6144, 4096, 2048, + 0, -2048, -4096, -6144, + -8192,-10240,-12288,-14336, +-16384,-14336,-12288,-10240, + -8192, -6144, -4096, -2048, + 0, 2048, 4096, 6144, + 8192, 10240, 12288, 14336, + 16384, 18432, 20480, 22528, + 24576, 26624, 28672, 30720, + 32768, 34816, 36864, 38912, + 40960, 43008, 45056, 47104}; + +static const int32 DISTORTION_TS_LUT[32] = +{49152, 55296, 61440, 67584, + 73728, 79872, 86016, 92160, + 98304, 104448, 110592, 116736, +122880, 129024, 135168, 141312, +147456, 153600, 159744, 165888, +172032, 178176, 184320, 190464, +196608, 202752, 208896, 215040, +221184, 227328, 233472, 239616}; + +/*----------------------------------------------------------------------------------------------------------*\ +! DESCRIPTION: ! +! ------------ ! +! These constants define a lookup table that is used to calculate the number of leading zeros ! +! in a pseudo 4-bit integer variable. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 15.02.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static const int32 DISTORTION_LZ_LUT[15] = +{0, 3, 0, 2, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0}; + + +/*----------------------------------------------------------------------------------------------------------*\ +! DESCRIPTION: ! +! ------------ ! +! - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 08.03.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static const uint16 frac2log[256] = +{ 0, 1, 2, 4, 5, 7, 8, 9, 11, 12, 14, 15, 16, 18, 19, 21, + 22, 23, 25, 26, 27, 29, 30, 31, 33, 34, 35, 37, 38, 39, 40, 42, + 43, 44, 46, 47, 48, 49, 51, 52, 53, 54, 56, 57, 58, 59, 61, 62, + 63, 64, 65, 67, 68, 69, 70, 71, 73, 74, 75, 76, 77, 78, 80, 81, + 82, 83, 84, 85, 87, 88, 89, 90, 91, 92, 93, 94, 96, 97, 98, 99, +100, 101, 102, 103, 104, 105, 106, 108, 109, 110, 111, 112, 113, 114, 115, 116, +117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 131, 132, 133, +134, 135, 136, 137, 138, 139, 140, 140, 141, 142, 143, 144, 145, 146, 147, 148, +149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 162, 163, +164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 173, 174, 175, 176, 177, 178, +179, 180, 181, 181, 182, 183, 184, 185, 186, 187, 188, 188, 189, 190, 191, 192, +193, 194, 194, 195, 196, 197, 198, 199, 200, 200, 201, 202, 203, 204, 205, 205, +206, 207, 208, 209, 209, 210, 211, 212, 213, 214, 214, 215, 216, 217, 218, 218, +219, 220, 221, 222, 222, 223, 224, 225, 225, 226, 227, 228, 229, 229, 230, 231, +232, 232, 233, 234, 235, 235, 236, 237, 238, 239, 239, 240, 241, 242, 242, 243, +244, 245, 245, 246, 247, 247, 248, 249, 250, 250, 251, 252, 253, 253, 254, 255}; + +/*----------------------------------------------------------------------------------------------------------*\ +! DESCRIPTION: ! +! ------------ ! +! - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 08.03.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static const uint8 SIG2CONTEXT_L[45] = +{CONTEXT_SIG + 0, CONTEXT_SIG + 1, CONTEXT_SIG + 2, CONTEXT_SIG + 2, CONTEXT_SIG + 2, + CONTEXT_SIG + 3, CONTEXT_SIG + 3, CONTEXT_SIG + 3, CONTEXT_SIG + 3, CONTEXT_SIG + 3, + CONTEXT_SIG + 4, CONTEXT_SIG + 4, CONTEXT_SIG + 4, CONTEXT_SIG + 4, CONTEXT_SIG + 4, + CONTEXT_SIG + 5, CONTEXT_SIG + 6, CONTEXT_SIG + 6, CONTEXT_SIG + 6, CONTEXT_SIG + 6, + CONTEXT_SIG + 7, CONTEXT_SIG + 7, CONTEXT_SIG + 7, CONTEXT_SIG + 7, CONTEXT_SIG + 7, + CONTEXT_SIG + 7, CONTEXT_SIG + 7, CONTEXT_SIG + 7, CONTEXT_SIG + 7, CONTEXT_SIG + 7, + CONTEXT_SIG + 8, CONTEXT_SIG + 8, CONTEXT_SIG + 8, CONTEXT_SIG + 8, CONTEXT_SIG + 8, + CONTEXT_SIG + 8, CONTEXT_SIG + 8, CONTEXT_SIG + 8, CONTEXT_SIG + 8, CONTEXT_SIG + 8, + CONTEXT_SIG + 8, CONTEXT_SIG + 8, CONTEXT_SIG + 8, CONTEXT_SIG + 8, CONTEXT_SIG + 8}; + +static const uint8 SIG2CONTEXT_H[45] = +{CONTEXT_SIG + 0, CONTEXT_SIG + 1, CONTEXT_SIG + 2, CONTEXT_SIG + 2, CONTEXT_SIG + 2, + CONTEXT_SIG + 5, CONTEXT_SIG + 6, CONTEXT_SIG + 6, CONTEXT_SIG + 6, CONTEXT_SIG + 6, + CONTEXT_SIG + 8, CONTEXT_SIG + 8, CONTEXT_SIG + 8, CONTEXT_SIG + 8, CONTEXT_SIG + 8, + CONTEXT_SIG + 3, CONTEXT_SIG + 3, CONTEXT_SIG + 3, CONTEXT_SIG + 3, CONTEXT_SIG + 3, + CONTEXT_SIG + 7, CONTEXT_SIG + 7, CONTEXT_SIG + 7, CONTEXT_SIG + 7, CONTEXT_SIG + 7, + CONTEXT_SIG + 8, CONTEXT_SIG + 8, CONTEXT_SIG + 8, CONTEXT_SIG + 8, CONTEXT_SIG + 8, + CONTEXT_SIG + 4, CONTEXT_SIG + 4, CONTEXT_SIG + 4, CONTEXT_SIG + 4, CONTEXT_SIG + 4, + CONTEXT_SIG + 7, CONTEXT_SIG + 7, CONTEXT_SIG + 7, CONTEXT_SIG + 7, CONTEXT_SIG + 7, + CONTEXT_SIG + 8, CONTEXT_SIG + 8, CONTEXT_SIG + 8, CONTEXT_SIG + 8, CONTEXT_SIG + 8}; + +static const uint8 SIG2CONTEXT_HH[45] = +{CONTEXT_SIG + 0, CONTEXT_SIG + 3, CONTEXT_SIG + 6, CONTEXT_SIG + 8, CONTEXT_SIG + 8, + CONTEXT_SIG + 1, CONTEXT_SIG + 4, CONTEXT_SIG + 7, CONTEXT_SIG + 8, CONTEXT_SIG + 8, + CONTEXT_SIG + 2, CONTEXT_SIG + 5, CONTEXT_SIG + 7, CONTEXT_SIG + 8, CONTEXT_SIG + 8, + CONTEXT_SIG + 1, CONTEXT_SIG + 4, CONTEXT_SIG + 7, CONTEXT_SIG + 8, CONTEXT_SIG + 8, + CONTEXT_SIG + 2, CONTEXT_SIG + 5, CONTEXT_SIG + 7, CONTEXT_SIG + 8, CONTEXT_SIG + 8, + CONTEXT_SIG + 2, CONTEXT_SIG + 5, CONTEXT_SIG + 7, CONTEXT_SIG + 8, CONTEXT_SIG + 8, + CONTEXT_SIG + 2, CONTEXT_SIG + 5, CONTEXT_SIG + 7, CONTEXT_SIG + 8, CONTEXT_SIG + 8, + CONTEXT_SIG + 2, CONTEXT_SIG + 5, CONTEXT_SIG + 7, CONTEXT_SIG + 8, CONTEXT_SIG + 8, + CONTEXT_SIG + 2, CONTEXT_SIG + 5, CONTEXT_SIG + 7, CONTEXT_SIG + 8, CONTEXT_SIG + 8}; + +static const uint8_t SIG2XI[16] = +{1, 2, 2, 2, + 1, 0, 2, 1, + 1, 2, 0, 1, + 1, 0, 0, 0}; + +static const uint8_t XI2CONT[11][2] = +{{CONTEXT_SIGN + 4, 1}, {CONTEXT_SIGN + 3, 1}, {CONTEXT_SIGN + 2, 1}, + {0, 0}, + {CONTEXT_SIGN + 1, 1}, {CONTEXT_SIGN , 0}, {CONTEXT_SIGN + 1, 0}, + {0, 0}, + {CONTEXT_SIGN + 2, 0}, {CONTEXT_SIGN + 3, 0}, {CONTEXT_SIGN + 4, 0}}; + +/************************************************************************************************************\ +|| ___ ____ _ _ _ ____ ___ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || +|| |__] |__/ | | | |__| | |___ |___ | | |\ | | | | | | |\ | [__ || +|| | | \ | \/ | | | |___ | |__| | \| |___ | | |__| | \| ___] || +|| || +\************************************************************************************************************/ +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void cblkreset_fwd(bwc_coder_stripe *const cblk, uint64 cblksize) ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is used to reset the codeblock memory block used to store the quantized ! +! wavelet samples alongside their sample states. This function should be called after ! +! encoding a codeblock. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! cblk bwc_coder_stripe* - Pointer to the codeblock memory block. ! +! cblksize unsigned int(64 bit) - Size of the codeblock. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 10.12.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +cblkreset_fwd(bwc_coder_stripe *const cblk, uint64 cblksize) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 i; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_coder_stripe buff; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(cblk); + + /*--------------------------------------------------------*\ + ! Walk through the cblk memory block. ! + \*--------------------------------------------------------*/ + for(i = 0; i < cblksize; ++i) + { + /*--------------------------------------------------------*\ + ! Save the sample bit and context memory address in a tem- ! + ! porary variables. ! + \*--------------------------------------------------------*/ + buff.sample = cblk[i].sample; + buff.bit = cblk[i].bit; + + /*--------------------------------------------------------*\ + ! Reset the bwc_coder_stripe structure and the memory block! + ! used to hold the sample bits of the wavelet coefficients.! + \*--------------------------------------------------------*/ + memset(&cblk[i], 0, sizeof(bwc_coder_stripe)); + memset(buff.bit, 0, PREC_BIT * sizeof(uint8)); + memset(buff.sample, 0, 4 * sizeof(uint64)); + + /*--------------------------------------------------------*\ + ! Store the memory address of the sample, bit and context ! + ! variables in the bwc_coder_stripe structure. ! + \*--------------------------------------------------------*/ + cblk[i].sample = buff.sample; + cblk[i].bit = buff.bit; + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void cblkreset_inv(bwc_coder_stripe *const cblk, const uint64 width, const uint64 height, ! +! const uint64 depth, const uint64 dt) ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is used to reset the codeblock memory block used to store the quantized ! +! wavelet samples alongside their sample states. This function should be called before ! +! decoding a codeblock. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! cblk bwc_coder_stripe* - Pointer to the codeblock memory block. ! +! width, height, depth, dt unsigned int(64 bit) - Size of the codeblock. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 10.12.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +cblkreset_inv(bwc_coder_stripe *const cblk, const uint64 width, const uint64 height, + const uint64 depth, const uint64 dt) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 i; + uint64 limit; + uint64 cblk_stripe; + uint64 x, y, z; + int64 idx_u, idx_r, idx_d, idx_l; + uint16 t; + uint8 s; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_coder_stripe buff; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(cblk); + + /*--------------------------------------------------------*\ + ! Calculate the number of stripes that are to be copied. ! + ! In case the number of rows is not divisible by 8, the ! + ! number of stripes is rounded up to the nearest integer. ! + \*--------------------------------------------------------*/ + cblk_stripe = ceil((double)height/4); + + /*--------------------------------------------------------*\ + ! Walk through all wavelet coefficients in the current ! + ! codeblock in a stripe pattern and save the sign and ! + ! significant magnitude bits in the bwc_coder_stripe ! + ! structure. Here, two adjacent stripes are stored ! + ! in one 8 bit integer. ! + \*--------------------------------------------------------*/ + for(t = 0, i = 0; t < dt; ++t) + { + for(z = 0; z < depth; ++z) + { + for(y = 0; y < cblk_stripe; i += width, ++y) + { + for(s = 0, limit = height - y * 4; s < 4 && s < limit; ++s) + { + for(x = 0; x < width; ++x) + { + /*--------------------------------------------------------*\ + ! Save the sample bit and context memory address in a tem- ! + ! porary variables. ! + \*--------------------------------------------------------*/ + buff.sample = cblk[x + i].sample; + buff.bit = cblk[x + i].bit; + + /*--------------------------------------------------------*\ + ! Reset the bwc_coder_stripe structure and the memory block ! + ! used to hold the sample bits of the wavelet coefficients.! + \*--------------------------------------------------------*/ + memset(&cblk[x + i], 0, sizeof(bwc_coder_stripe)); + memset(buff.bit, 0, PREC_BIT * sizeof(uint8)); + memset(buff.sample, 0, 4 * sizeof(uint64)); + + /*--------------------------------------------------------*\ + ! Store the memory address of the sample, bit and context ! + ! variables in the bwc_coder_stripe structure. ! + \*--------------------------------------------------------*/ + cblk[x + i].sample = buff.sample; + cblk[x + i].bit = buff.bit; + + /*--------------------------------------------------------*\ + ! Evaluate the appropriate index for the stripe neighbours.! + ! Neighbours that fall outside of the codeblock boundaries ! + ! are set to dummy variables to uncouple the current block ! + ! from its neighbors. ! + \*--------------------------------------------------------*/ + idx_u = (y == 0) ? -1 : (int64)(i + x - width); + idx_r = (x == width - 1) ? -2 : (int64)(i + x + 1); + idx_d = (s == limit - 1) ? -1 : (int64)(i + x + width); + idx_l = (x == 0) ? -2 : (int64)(i + x - 1); + + /*--------------------------------------------------------*\ + ! Set the state pointers. ! + \*--------------------------------------------------------*/ + cblk[x + i].stripe_u = &cblk[idx_u]; + cblk[x + i].stripe_r = &cblk[idx_r]; + cblk[x + i].stripe_d = &cblk[idx_d]; + cblk[x + i].stripe_l = &cblk[idx_l]; + } + } + } + } + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void cblkcopy_forward(bwc_coder_stripe *const destination, bwc_sample *const source, ! +! bwc_cblk_access *const cblkaccess, const uint64 width,! +! const uint64 height, const uint64 depth)! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function walks through the wavelet coefficients in the current codeblock in a stripe ! +! pattern and saves the sign and magnitude bits in the sign and magnitude bitfields in the ! +! bwc_coder_stripe structure. Here, the 8-bit sign and magnitude bitfields are used to store ! +! two adjacent stripes to reduce the memory footprint. Furthermore, the pointer to the neigh- ! +! boring state variables are initialized. States that fall outside of the codeblock bounda- ! +! ries are set to dummy variables to uncouple the current block from its neighbors. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! destination bwc_coder_stripe* - Pointer to the destination memory block.! +! source bwc_sample* - Pointer to the source memory block. ! +! cblkaccess bwc_cblk_access* - Structure used to directly access the ! +! parameter codeblock and subband struc- ! +! ture. ! +! width, height, depth unsigned int(64 bit) - Size of the destination memory block. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 02.07.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +cblkcopy_forward(bwc_coder_stripe *const destination, bwc_sample *const source, + bwc_cblk_access *const cblkaccess, const uint64 width, + const uint64 height, const uint64 depth) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + bwc_raw buff, sign_mask; + uint64 bit_mask, limit; + uint64 cblk_width, cblk_height, cblk_depth, cblk_stripe; + uint64 incrX, incrY, incrZ; + uint64 i, x, y, z; + uint64 X0, Y0, Z0; + uint64 X1, Y1, Z1; + int64 idx_u, idx_r, idx_d, idx_l; + uint16 TS0, TS1; + uint16 cblk_dt; + uint16 t; + uint8 b, Kmax, s; + + /*-----------------------*\ + ! DEFINE FLOAT VARIABLES: ! + \*-----------------------*/ + bwc_float qt_step_size; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_cblk_inf *cblk_info; + bwc_sample *tmp; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(destination); + assert(cblkaccess); + assert(source); + + /*--------------------------------------------------------*\ + ! Save the codeblock info structure to a temporary varia- ! + ! ble to make the code more readable. ! + \*--------------------------------------------------------*/ + cblk_info = &cblkaccess->codeblock->info; + + /*--------------------------------------------------------*\ + ! Setup a bitmask to access the sign bit position. ! + \*--------------------------------------------------------*/ + sign_mask = ~((bwc_raw)0x01 << PREC_BIT); + + /*--------------------------------------------------------*\ + ! Initialize the quantization step size and the index of ! + ! the most significant bitfield. ! + \*--------------------------------------------------------*/ + qt_step_size = cblkaccess->subband->control.qt_effective_step_size; + Kmax = 0; + + /*--------------------------------------------------------*\ + ! Save the codeblock dimensions to temporary variables to ! + ! make the code more readable. ! + \*--------------------------------------------------------*/ + X0 = cblk_info->X0; + Y0 = cblk_info->Y0; + Z0 = cblk_info->Z0; + TS0 = cblk_info->TS0; + + X1 = cblk_info->X1; + Y1 = cblk_info->Y1; + Z1 = cblk_info->Z1; + TS1 = cblk_info->TS1; + + /*--------------------------------------------------------*\ + ! Calculate the width, height, depth and dt of the code- ! + ! block to be copied. ! + \*--------------------------------------------------------*/ + cblk_width = X1 - X0; + cblk_height = Y1 - Y0; + cblk_depth = Z1 - Z0; + cblk_dt = TS1 - TS0; + + /*--------------------------------------------------------*\ + ! Calculate the number of stripes that are to be copied. ! + ! In case the number of rows is not divisible by 8, the ! + ! number of stripes is rounded up to the nearest integer. ! + \*--------------------------------------------------------*/ + cblk_stripe = ceil((double)cblk_height/4); + + /*--------------------------------------------------------*\ + ! Calculate the pointer increments used to loop through ! + ! the source memory. ! + \*--------------------------------------------------------*/ + incrX = width; + incrY = width * (height - (Y1 - Y0)); + incrZ = width * height * (depth - (Z1 - Z0)); + + /*--------------------------------------------------------*\ + ! Associate the temporary pointer to the starting points ! + ! of the source memory. ! + \*--------------------------------------------------------*/ + tmp = &source[X0 + width * (Y0 + height * (Z0 + depth * TS0))]; + + /*--------------------------------------------------------*\ + ! Walk through all wavelet coefficients in the current ! + ! codeblock in a stripe pattern and save the sign and ! + ! significant magnitude bits in the bwc_coder_stripe ! + ! structure. Here, two adjacent stripes are stored ! + ! in one 8 bit integer. ! + \*--------------------------------------------------------*/ + for(t = 0, i = 0; t < cblk_dt; ++t) + { + for(z = 0; z < cblk_depth; ++z) + { + for(y = 0; y < cblk_stripe; i += cblk_width, ++y) + { + /*--------------------------------------------------------*\ + ! Initialize the stripe bit masks to the first stripe posi-! + ! tion in the sign, state and sample variables. ! + \*--------------------------------------------------------*/ + bit_mask = 0x08; + + for(s = 0, limit = cblk_height - y * 4; s < 4 && s < limit; ++s) + { + for(x = 0; x < cblk_width; ++x) + { + /*--------------------------------------------------------*\ + ! Save the sign bit of the current wavelet coefficient in ! + ! the appropriate position of the sign field. ! + \*--------------------------------------------------------*/ + destination[x + i].xi |= bit_mask * (tmp[x].raw / ~sign_mask); + + /*--------------------------------------------------------*\ + ! Calculate the absolute value of the wavelet coefficient ! + ! and store the quantized value in the temporary buffer. ! + \*--------------------------------------------------------*/ + tmp[x].raw &= sign_mask; + buff = (bwc_raw)(tmp[x].f / qt_step_size); + + /*--------------------------------------------------------*\ + ! Save the unsigned wavelet coefficient for distortion ! + ! calculation. ! + \*--------------------------------------------------------*/ + destination[x + i].sample[3 - s] = buff; + + /*--------------------------------------------------------*\ + ! set the bitfield index b to zero. ! + \*--------------------------------------------------------*/ + b = 0; + + /*--------------------------------------------------------*\ + ! Save the significant bits of the current wavelet coeffi- ! + ! cient in the appropriate bitfield and stripe. ! + \*--------------------------------------------------------*/ + while(buff) + { + destination[x + i].bit[b] |= bit_mask * (buff & 0x01); + buff >>= 1; + b++; + } + + /*--------------------------------------------------------*\ + ! Update the index of the most significant bitfield. ! + \*--------------------------------------------------------*/ + Kmax = MAX(Kmax, b); + + /*--------------------------------------------------------*\ + ! Evaluate the appropriate index for the stripe neighbours ! + ! Neighbours that fall outside of the codeblock boundaries ! + ! are set to dummy variables to uncouple the current block ! + ! from its neighbors. ! + \*--------------------------------------------------------*/ + idx_u = (y == 0) ? -1 : (int64)(i + x - cblk_width); + idx_r = (x == cblk_width - 1) ? -2 : (int64)(i + x + 1); + idx_d = (s == limit - 1) ? -1 : (int64)(i + x + cblk_width); + idx_l = (x == 0) ? -2 : (int64)(i + x - 1); + + /*--------------------------------------------------------*\ + ! Set the state pointers. ! + \*--------------------------------------------------------*/ + destination[x + i].stripe_u = &destination[idx_u]; + destination[x + i].stripe_r = &destination[idx_r]; + destination[x + i].stripe_d = &destination[idx_d]; + destination[x + i].stripe_l = &destination[idx_l]; + } + /*--------------------------------------------------------*\ + ! Increment the stripe bit mask to the next stripe posi- ! + ! tion slice and increment the temporary data pointer to ! + ! the next row. ! + \*--------------------------------------------------------*/ + bit_mask >>= 1; + tmp += incrX; + } + } + /*--------------------------------------------------------*\ + ! Increment to the next column. ! + \*--------------------------------------------------------*/ + tmp += incrY; + } + /*--------------------------------------------------------*\ + ! Increment to the next spatial slice. ! + \*--------------------------------------------------------*/ + tmp += incrZ; + } + /*--------------------------------------------------------*\ + ! Save the most significant bitfield of the current sub- ! + ! band in the appropriate subband structure. ! + \*--------------------------------------------------------*/ + cblkaccess->codeblock->control.K = Kmax; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void cblkcopy_inverse(bwc_coder_stripe *const destination, bwc_sample *const source, ! +! bwc_cblk_access *const cblkaccess, const uint64 width,! +! const uint64 height, const uint64 depth)! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is used to copy the decompressed wavelet coefficients from the codeblock ! +! structure to the parameter data memory block. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! destination bwc_coder_stripe* - Pointer to the destination memory block.! +! source bwc_sample* - Pointer to the source memory block. ! +! cblkaccess bwc_cblk_access* - Structure used to directly access the ! +! parameter codeblock and subband struc- ! +! ture. ! +! width, height, depth unsigned int(64 bit) - Size of the destination memory block. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 02.07.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +cblkcopy_inverse(bwc_coder_stripe *const source, bwc_sample *const destination, + bwc_cblk_access *const cblkaccess, const uint64 width, + const uint64 height, const uint64 depth) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 cblk_width, cblk_height, cblk_depth, cblk_stripe; + uint64 bit_shift, buff, limit; + uint64 incrX, incrY, incrZ; + uint64 i, x, y, z; + uint64 X0, Y0, Z0; + uint64 X1, Y1, Z1; + uint16 TS0, TS1; + uint16 cblk_dt; + uint16 t; + uint8 bitplane; + uint8 codingpass; + uint8 s; + int8 b; + + /*-----------------------*\ + ! DEFINE FLOAT VARIABLES: ! + \*-----------------------*/ + bwc_float qt_step_size; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_cblk_inf *cblk_info; + bwc_sample *tmp; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(destination); + assert(cblkaccess); + assert(source); + + /*--------------------------------------------------------*\ + ! Save the codeblock info structure to a temporary varia- ! + ! ble to make the code more readable. ! + \*--------------------------------------------------------*/ + cblk_info = &cblkaccess->codeblock->info; + + /*--------------------------------------------------------*\ + ! Initialize the quantization step size and the index of ! + ! the most significant bitfield. ! + \*--------------------------------------------------------*/ + qt_step_size = cblkaccess->subband->control.qt_effective_step_size; + + /*--------------------------------------------------------*\ + ! Safe the last bitplane and codingpass to temporary vari- ! + ! able to make the code more readable. ! + \*--------------------------------------------------------*/ + bitplane = source->bitplane; + codingpass = source->codingpass; + + /*--------------------------------------------------------*\ + ! Save the codeblock dimensions to temporary variables to ! + ! make the code more readable. ! + \*--------------------------------------------------------*/ + X0 = cblk_info->X0; + Y0 = cblk_info->Y0; + Z0 = cblk_info->Z0; + TS0 = cblk_info->TS0; + + X1 = cblk_info->X1; + Y1 = cblk_info->Y1; + Z1 = cblk_info->Z1; + TS1 = cblk_info->TS1; + + /*--------------------------------------------------------*\ + ! Calculate the width, height, depth and dt of the code- ! + ! block to be copied. ! + \*--------------------------------------------------------*/ + cblk_width = X1 - X0; + cblk_height = Y1 - Y0; + cblk_depth = Z1 - Z0; + cblk_dt = TS1 - TS0; + + /*--------------------------------------------------------*\ + ! Calculate the number of stripes that are to be copied. ! + ! In case the number of rows is not divisible by 8, the ! + ! number of stripes is rounded up to the nearest integer. ! + \*--------------------------------------------------------*/ + cblk_stripe = ceil((double)cblk_height/4); + + /*--------------------------------------------------------*\ + ! Calculate the pointer increments used to loop through ! + ! the destination memory. ! + \*--------------------------------------------------------*/ + incrX = width; + incrY = width * (height - (Y1 - Y0)); + incrZ = width * height * (depth - (Z1 - Z0)); + + /*--------------------------------------------------------*\ + ! Associate the temporary pointer to the starting points ! + ! of the destination memory. ! + \*--------------------------------------------------------*/ + tmp = &destination[X0 + width * (Y0 + height * (Z0 + depth * TS0))]; + + /*--------------------------------------------------------*\ + ! Walk through all wavelet coefficients in the current ! + ! codeblock in a stripe pattern and save the sign and ! + ! significant magnitude bits in the bwc_coder_stripe ! + ! structure. Here, two adjacent stripes are stored ! + ! in one 8 bit integer. ! + \*--------------------------------------------------------*/ + for(t = 0, i = 0; t < cblk_dt; ++t) + { + for(z = 0; z < cblk_depth; ++z) + { + for(y = 0; y < cblk_stripe; i += cblk_width, ++y) + { + /*--------------------------------------------------------*\ + ! Initialize the stripe bit masks to the first stripe posi-! + ! tion in the sign, state and sample variables. ! + \*--------------------------------------------------------*/ + bit_shift = 0x03; + + for(s = 0, limit = cblk_height - y * 4; s < 4 && s < limit; ++s) + { + for(x = 0; x < cblk_width; ++x) + { + /*--------------------------------------------------------*\ + ! Save the significant bits of the current wavelet coeffi- ! + ! cient in the appropriate bitfield and stripe. ! + \*--------------------------------------------------------*/ + for(b = PREC_BIT, buff = 0; b --> 0;) + { + buff <<= 1; + buff |= (source[x + i].bit[b] >> bit_shift) & 0x01; + } + + /*--------------------------------------------------------*\ + ! Calculate the absolute value of the wavelet coefficient ! + ! and store the quantized value in the temporary buffer. ! + \*--------------------------------------------------------*/ + if(buff) + { + tmp[x].f = (bwc_float)buff; + tmp[x].f += (1UL << (bitplane + ((!codingpass || ((source[x + i].pi >> bit_shift) & 0x01)) ? 0 : 1))) * 0.475f; + tmp[x].f *= qt_step_size; + tmp[x].raw |= SIGN * ((source[x + i].xi >> bit_shift) & 0x01); + } + } + + /*--------------------------------------------------------*\ + ! Increment the stripe bit mask to the next stripe posi- ! + ! tion slice and increment the temporary data pointer to ! + ! the next row. ! + \*--------------------------------------------------------*/ + bit_shift--; + tmp += incrX; + } + } + /*--------------------------------------------------------*\ + ! Increment to the next column. ! + \*--------------------------------------------------------*/ + tmp += incrY; + } + /*--------------------------------------------------------*\ + ! Increment to the next spatial slice. ! + \*--------------------------------------------------------*/ + tmp += incrZ; + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! - Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static uint64 +significance_propagation_enc_pass(bwc_coder *const coder, const int8 b) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 i, j; + uint64 k, x; + int64 mse; + uint16 k_h, k_v, k_d; + uint16 k_sig; + uint16 xi_h, xi_v; + uint8 bit_mask, stripe_mask; + uint8 dist_shift, dist_corr, l; + uint8 bit; + uint8 rest; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_coder_stripe *stripe; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(coder); + + mse = 0; + stripe = coder->data; + rest = 4 - (coder->height & 0x03); + stripe_mask = ~((0x0F >> ((coder->height & 0x03))) | 0xF0); + dist_shift = (b < DISTORTION_SIG) ? 0 : (b - DISTORTION_SIG); + dist_corr = (b < DISTORTION_SIG) ? (DISTORTION_SIG - b) : 0; + + for(i = 0, k = 0; i < coder->no_slice; ++i) + { + for(j = 0; j < coder->no_full_stripe; ++j) + { + for(x = 0; x < coder->width; ++x, ++k) + { + if(stripe[k].sigma^0xF) + { + for(bit = stripe[k].bit[b], bit_mask = 0x08, l = 4; l --> 0; bit_mask >>= 1) + { + if(!(stripe[k].sigma & bit_mask)) + { + k_h = (stripe[k].stripe_l->sigma & bit_mask) + (stripe[k].stripe_r->sigma & bit_mask); + + k_v = ((bit_mask & (stripe[k].sigma >> 1)) + (bit_mask & (stripe[k].sigma << 1))); + + k_d = ((bit_mask & (stripe[k].stripe_l->sigma >> 1)) + (bit_mask & (stripe[k].stripe_l->sigma << 1)) + + (bit_mask & (stripe[k].stripe_r->sigma >> 1)) + (bit_mask & (stripe[k].stripe_r->sigma << 1))); + + if(l == 3) + { + k_v += ((0x01 & stripe[k].stripe_u->sigma) << 3); + k_d += ((0x01 & stripe[k].stripe_u->stripe_l->sigma) + + (0x01 & stripe[k].stripe_u->stripe_r->sigma)) << 3; + } + else if(l == 0) + { + k_v += ((0x08 & stripe[k].stripe_d->sigma) >> 3); + k_d += ((0x08 & stripe[k].stripe_d->stripe_l->sigma) + + (0x08 & stripe[k].stripe_d->stripe_r->sigma)) >> 3; + } + + k_sig = ((15 * k_h + 5 * k_v + k_d) >> l); + + if(k_sig) + { + mq_bit_encode(coder->bitcoder, (uchar)((bit >> l) & 0x01), coder->sig2context[k_sig]); + + if(bit & bit_mask) + { + xi_h = ((bit_mask & stripe[k].stripe_l->sigma) | ((bit_mask & stripe[k].stripe_l->xi) << 2) | + ((bit_mask & stripe[k].stripe_r->sigma) << 1) | ((bit_mask & stripe[k].stripe_r->xi) << 3)) >> l; + + xi_v = ((bit_mask & (stripe[k].sigma >> 1)) | ((bit_mask & (stripe[k].xi >> 1)) << 2) | + ((bit_mask & (stripe[k].sigma << 1)) << 1) | ((bit_mask & (stripe[k].xi << 1)) << 3)) >> l; + + if(l == 3) + { + xi_v |= ((0x01 & stripe[k].stripe_u->sigma) | ((0x01 & stripe[k].stripe_u->xi) << 2)); + } + else if(l == 0) + { + xi_v |= (((0x08 & stripe[k].stripe_d->sigma) >> 2) | (0x08 & stripe[k].stripe_d->xi)); + } + + xi_h = SIG2XI[xi_h]; + xi_v = SIG2XI[xi_v]; + + mq_bit_encode(coder->bitcoder, (uchar)(((bit_mask & stripe[k].xi) >> l)^XI2CONT[(xi_h << 2) | xi_v][1]), + XI2CONT[(xi_h << 2) | xi_v][0]); + + mse += DISTORTION_TS_LUT[((stripe[k].sample[l] >> dist_shift) << dist_corr) & 0x1F]; + stripe[k].sigma |= bit_mask; + } + + stripe[k].pi |= bit_mask; + } + } + else + { + stripe[k].pi ^= (stripe[k].pi & bit_mask); + } + } + } + else + { + stripe[k].pi = 0; + } + } + } + + if(rest < 4) + { + for(x = 0; x < coder->width; ++x, ++k) + { + if((stripe[k].sigma^0xF) & stripe_mask) + { + for(bit = stripe[k].bit[b], bit_mask = 0x08, l = 4; l --> rest; bit_mask >>= 1) + { + if(!(stripe[k].sigma & bit_mask)) + { + k_h = (stripe[k].stripe_l->sigma & bit_mask) + (stripe[k].stripe_r->sigma & bit_mask); + + k_v = ((bit_mask & (stripe[k].sigma >> 1)) + (bit_mask & (stripe[k].sigma << 1))); + + k_d = ((bit_mask & (stripe[k].stripe_l->sigma >> 1)) + (bit_mask & (stripe[k].stripe_l->sigma << 1)) + + (bit_mask & (stripe[k].stripe_r->sigma >> 1)) + (bit_mask & (stripe[k].stripe_r->sigma << 1))); + + if(l == 3) + { + k_v += ((0x01 & stripe[k].stripe_u->sigma) << 3); + k_d += ((0x01 & stripe[k].stripe_u->stripe_l->sigma) + + (0x01 & stripe[k].stripe_u->stripe_r->sigma)) << 3; + } + + k_sig = ((15 * k_h + 5 * k_v + k_d) >> l); + + if(k_sig && (stripe[k].sigma^bit_mask)) + { + mq_bit_encode(coder->bitcoder, (uchar)((bit >> l) & 0x01), coder->sig2context[k_sig]); + + if(bit & bit_mask) + { + xi_h = ((bit_mask & stripe[k].stripe_l->sigma) | ((bit_mask & stripe[k].stripe_l->xi) << 2) | + ((bit_mask & stripe[k].stripe_r->sigma) << 1) | ((bit_mask & stripe[k].stripe_r->xi) << 3)) >> l; + + xi_v = ((bit_mask & (stripe[k].sigma >> 1)) | ((bit_mask & (stripe[k].xi >> 1)) << 2) | + ((bit_mask & (stripe[k].sigma << 1)) << 1) | ((bit_mask & (stripe[k].xi << 1)) << 3)) >> l; + + if(l == 3) + { + xi_v |= ((0x01 & stripe[k].stripe_u->sigma) | ((0x01 & stripe[k].stripe_u->xi) << 2)); + } + + xi_h = SIG2XI[xi_h]; + xi_v = SIG2XI[xi_v]; + + mq_bit_encode(coder->bitcoder, (uchar)(((bit_mask & stripe[k].xi) >> l)^XI2CONT[(xi_h << 2) | xi_v][1]), + XI2CONT[(xi_h << 2) | xi_v][0]); + + mse += DISTORTION_TS_LUT[((stripe[k].sample[l] >> dist_shift) << dist_corr) & 0x1F]; + stripe[k].sigma |= bit_mask; + } + + stripe[k].pi |= bit_mask; + } + } + else + { + stripe[k].pi ^= (stripe[k].pi & bit_mask); + } + } + } + else + { + stripe[k].pi = 0; + } + } + } + } + return mse; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! - Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static uint64 +magnitude_refinement_enc_pass(bwc_coder *const coder, const int8 b) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 i, j; + uint64 k, x; + int64 mse; + uint16 k_mag; + uint8 bit_mask, stripe_mask; + uint8 dist_shift, dist_corr, l; + uint8 bit, sig; + uint8 rest; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_coder_stripe *stripe; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(coder); + + mse = 0; + stripe = coder->data; + rest = 4 - (coder->height & 0x03); + stripe_mask = ~((0x0F >> ((coder->height & 0x03))) | 0xF0); + dist_shift = (b < DISTORTION_MAG) ? 0 : (b - DISTORTION_MAG); + dist_corr = (b < DISTORTION_MAG) ? (DISTORTION_MAG - b) : 0; + + for(i = 0, k = 0; i < coder->no_slice; ++i) + { + for(j = 0; j < coder->no_full_stripe; ++j) + { + for(x = 0; x < coder->width; ++x, ++k) + { + sig = stripe[k].sigma & (~stripe[k].pi); + + for(bit = stripe[k].bit[b], bit_mask = 0x08, l = 4; l --> 0; bit_mask >>= 1) + { + if(sig & bit_mask) + { + k_mag = CONTEXT_MAG; + + if(stripe[k].delta & bit_mask) + { + k_mag += 2; + } + else + { + if((bit_mask & (stripe[k].sigma >> 1)) || (bit_mask & (stripe[k].sigma << 1)) || + (stripe[k].stripe_l->sigma & bit_mask) || (stripe[k].stripe_r->sigma & bit_mask) || + (bit_mask & (stripe[k].stripe_l->sigma >> 1)) || (bit_mask & (stripe[k].stripe_l->sigma << 1)) || + (bit_mask & (stripe[k].stripe_r->sigma >> 1)) || (bit_mask & (stripe[k].stripe_r->sigma << 1))) + { + k_mag += 1; + } + else if((l == 3) && ((0x08 & (stripe[k].stripe_u->sigma << 3)) + || (0x08 & (stripe[k].stripe_u->stripe_l->sigma << 3)) + || (0x08 & (stripe[k].stripe_u->stripe_r->sigma << 3)))) + { + k_mag += 1; + } + else if((l == 0) && ((0x01 & (stripe[k].stripe_d->sigma >> 3)) + || (0x01 & (stripe[k].stripe_d->stripe_l->sigma >> 3)) + || (0x01 & (stripe[k].stripe_d->stripe_r->sigma >> 3)))) + { + k_mag += 1; + } + } + + mq_bit_encode(coder->bitcoder, (uchar)((bit >> l) & 0x01), k_mag); + + mse += DISTORTION_TM_LUT[((stripe[k].sample[l] >> dist_shift) << dist_corr) & 0x3F]; + stripe[k].delta |= bit_mask; + } + } + } + } + + if(rest < 4) + { + for(x = 0; x < coder->width; ++x, ++k) + { + sig = (stripe[k].sigma & (~stripe[k].pi)) & stripe_mask; + + for(bit = stripe[k].bit[b], bit_mask = 0x08, l = 4; l --> rest; bit_mask >>= 1) + { + if(sig & bit_mask) + { + k_mag = CONTEXT_MAG; + + if(stripe[k].delta & bit_mask) + { + k_mag += 2; + } + else + { + if((bit_mask & (stripe[k].sigma >> 1)) || (bit_mask & (stripe[k].sigma << 1)) || + (stripe[k].stripe_l->sigma & bit_mask) || (stripe[k].stripe_r->sigma & bit_mask) || + (bit_mask & (stripe[k].stripe_l->sigma >> 1)) || (bit_mask & (stripe[k].stripe_l->sigma << 1)) || + (bit_mask & (stripe[k].stripe_r->sigma >> 1)) || (bit_mask & (stripe[k].stripe_r->sigma << 1))) + { + k_mag += 1; + } + else if((l == 3) && ((0x08 & (stripe[k].stripe_u->sigma << 3)) + || (0x08 & (stripe[k].stripe_u->stripe_l->sigma << 3)) + || (0x08 & (stripe[k].stripe_u->stripe_r->sigma << 3)))) + { + k_mag += 1; + } + } + + mq_bit_encode(coder->bitcoder, (uchar)((bit >> l) & 0x01), k_mag); + + mse += DISTORTION_TM_LUT[((stripe[k].sample[l] >> dist_shift) << dist_corr) & 0x3F]; + stripe[k].delta |= bit_mask; + } + } + } + } + } + return mse; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! - Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static uint64 +cleanup_enc_pass(bwc_coder *const coder, const int8 b) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 i, j; + uint64 k, x; + int64 mse; + uint16 k_h, k_v, k_d; + uint16 xi_h, xi_v; + uint8 bit_mask, l; + uint8 dist_shift, dist_corr; + uint8 bit; + uint8 rest; + int8 r; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_coder_stripe *stripe; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(coder); + + mse = 0; + stripe = coder->data; + rest = 4 - (coder->height & 0x03); + dist_shift = (b < DISTORTION_SIG) ? 0 : (b - DISTORTION_SIG); + dist_corr = (b < DISTORTION_SIG) ? (DISTORTION_SIG - b) : 0; + + for(i = 0, k = 0; i < coder->no_slice; ++i) + { + for(j = 0; j < coder->no_full_stripe; ++j) + { + for(x = 0; x < coder->width; ++x, ++k) + { + r = -1; + + if(!(0x08 & stripe[k].stripe_d->stripe_l->sigma) && !(0x08 & stripe[k].stripe_d->sigma) && + !(0x08 & stripe[k].stripe_d->stripe_r->sigma) && !(0x01 & stripe[k].stripe_u->sigma) && + !(0x01 & stripe[k].stripe_u->stripe_l->sigma) && !stripe[k].stripe_l->sigma && + !(0x01 & stripe[k].stripe_u->stripe_r->sigma) && !stripe[k].stripe_r->sigma && + !stripe[k].sigma) + { + bit = stripe[k].bit[b]; + if(bit) + { + r = bit | (bit >> 1); + r |= r >> 2; + r = DISTORTION_LZ_LUT[r]; + + mq_bit_encode(coder->bitcoder, (uchar)1, CONTEXT_RUN); + mq_bit_encode(coder->bitcoder, (uchar)r >> 1, CONTEXT_UNI); + mq_bit_encode(coder->bitcoder, (uchar)r&0x01, CONTEXT_UNI); + } + else + { + r = 4; + mq_bit_encode(coder->bitcoder, (uchar)0, CONTEXT_RUN); + } + } + + for(bit = stripe[k].bit[b], bit_mask = 0x08, l = 4; l --> 0; bit_mask >>= 1) + { + if(!(stripe[k].sigma & bit_mask) && !(stripe[k].pi & bit_mask)) + { + if(r >= 0) + { + r--; + } + else + { + k_h = (stripe[k].stripe_l->sigma & bit_mask) + (stripe[k].stripe_r->sigma & bit_mask); + + k_v = ((bit_mask & (stripe[k].sigma >> 1)) + (bit_mask & (stripe[k].sigma << 1))); + + k_d = ((bit_mask & (stripe[k].stripe_l->sigma >> 1)) + (bit_mask & (stripe[k].stripe_l->sigma << 1)) + + (bit_mask & (stripe[k].stripe_r->sigma >> 1)) + (bit_mask & (stripe[k].stripe_r->sigma << 1))); + + if(l == 3) + { + k_v += ((0x01 & stripe[k].stripe_u->sigma) << 3); + k_d += ((0x01 & stripe[k].stripe_u->stripe_l->sigma) + + (0x01 & stripe[k].stripe_u->stripe_r->sigma)) << 3; + } + else if(l == 0) + { + k_v += ((0x08 & stripe[k].stripe_d->sigma) >> 3); + k_d += ((0x08 & stripe[k].stripe_d->stripe_l->sigma) + + (0x08 & stripe[k].stripe_d->stripe_r->sigma)) >> 3; + } + + mq_bit_encode(coder->bitcoder, (uchar)((bit >> l) & 0x01), coder->sig2context[(15 * k_h + 5 * k_v + k_d) >> l]); + } + if(bit & bit_mask) + { + xi_h = ((bit_mask & stripe[k].stripe_l->sigma) | ((bit_mask & stripe[k].stripe_l->xi) << 2) | + ((bit_mask & stripe[k].stripe_r->sigma) << 1) | ((bit_mask & stripe[k].stripe_r->xi) << 3)) >> l; + + xi_v = ((bit_mask & (stripe[k].sigma >> 1)) | ((bit_mask & (stripe[k].xi >> 1)) << 2) | + ((bit_mask & (stripe[k].sigma << 1)) << 1) | ((bit_mask & (stripe[k].xi << 1)) << 3)) >> l; + + if(l == 3) + { + xi_v |= ((0x01 & stripe[k].stripe_u->sigma) | ((0x01 & stripe[k].stripe_u->xi) << 2)); + } + else if(l == 0) + { + xi_v |= (((0x08 & stripe[k].stripe_d->sigma) >> 2) | (0x08 & stripe[k].stripe_d->xi)); + } + + xi_h = SIG2XI[xi_h]; + xi_v = SIG2XI[xi_v]; + + mq_bit_encode(coder->bitcoder, (uchar)(((bit_mask & stripe[k].xi) >> l)^XI2CONT[(xi_h << 2) | xi_v][1]), + XI2CONT[(xi_h << 2) | xi_v][0]); + + mse += DISTORTION_TS_LUT[((stripe[k].sample[l] >> dist_shift) << dist_corr) & 0x1F]; + stripe[k].sigma |= bit_mask; + } + } + } + } + } + + if(rest < 4) + { + for(x = 0; x < coder->width; ++x, ++k) + { + for(bit = stripe[k].bit[b], bit_mask = 0x08, l = 4; l --> rest; bit_mask >>= 1) + { + if(!(stripe[k].sigma & bit_mask) && !(stripe[k].pi & bit_mask)) + { + k_h = (stripe[k].stripe_l->sigma & bit_mask) + (stripe[k].stripe_r->sigma & bit_mask); + + k_v = ((bit_mask & (stripe[k].sigma >> 1)) + (bit_mask & (stripe[k].sigma << 1))); + + k_d = ((bit_mask & (stripe[k].stripe_l->sigma >> 1)) + (bit_mask & (stripe[k].stripe_l->sigma << 1)) + + (bit_mask & (stripe[k].stripe_r->sigma >> 1)) + (bit_mask & (stripe[k].stripe_r->sigma << 1))); + + if(l == 3) + { + k_v += ((0x01 & stripe[k].stripe_u->sigma) << 3); + k_d += ((0x01 & stripe[k].stripe_u->stripe_l->sigma) + + (0x01 & stripe[k].stripe_u->stripe_r->sigma)) << 3; + } + + mq_bit_encode(coder->bitcoder, (uchar)((bit >> l) & 0x01), coder->sig2context[(15 * k_h + 5 * k_v + k_d) >> l]); + + if(bit & bit_mask) + { + xi_h = ((bit_mask & stripe[k].stripe_l->sigma) | ((bit_mask & stripe[k].stripe_l->xi) << 2) | + ((bit_mask & stripe[k].stripe_r->sigma) << 1) | ((bit_mask & stripe[k].stripe_r->xi) << 3)) >> l; + + xi_v = ((bit_mask & (stripe[k].sigma >> 1)) | ((bit_mask & (stripe[k].xi >> 1)) << 2) | + ((bit_mask & (stripe[k].sigma << 1)) << 1) | ((bit_mask & (stripe[k].xi << 1)) << 3)) >> l; + + if(l == 3) + { + xi_v |= ((0x01 & stripe[k].stripe_u->sigma) | ((0x01 & stripe[k].stripe_u->xi) << 2)); + } + + xi_h = SIG2XI[xi_h]; + xi_v = SIG2XI[xi_v]; + + mq_bit_encode(coder->bitcoder, (uchar)(((bit_mask & stripe[k].xi) >> l)^XI2CONT[(xi_h << 2) | xi_v][1]), + XI2CONT[(xi_h << 2) | xi_v][0]); + + mse += DISTORTION_TS_LUT[((stripe[k].sample[l] >> dist_shift) << dist_corr) & 0x1F]; + stripe[k].sigma |= bit_mask; + } + } + } + } + } + } + return mse; +} + + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! - Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +significance_propagation_dec_pass(bwc_coder *const coder, const int8 b) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 i, j; + uint64 k, x; + uint16 k_h, k_v, k_d; + uint16 k_sig; + uint16 xi_h, xi_v; + uint8 bit_mask, stripe_mask; + uint8 l; + uint8 bit; + uint8 rest; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_coder_stripe *stripe; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(coder); + + stripe = coder->data; + stripe_mask = ~((0x0F >> ((coder->height & 0x03))) | 0xF0); + rest = 4 - (coder->height & 0x03); + + for(i = 0, k = 0; i < coder->no_slice; ++i) + { + for(j = 0; j < coder->no_full_stripe; ++j) + { + for(x = 0; x < coder->width; ++x, ++k) + { + if(stripe[k].sigma^0xF) + { + for(bit_mask = 0x08, l = 4; l --> 0; bit_mask >>= 1) + { + if(!(stripe[k].sigma & bit_mask)) + { + k_h = (stripe[k].stripe_l->sigma & bit_mask) + (stripe[k].stripe_r->sigma & bit_mask); + + k_v = ((bit_mask & (stripe[k].sigma >> 1)) + (bit_mask & (stripe[k].sigma << 1))); + + k_d = ((bit_mask & (stripe[k].stripe_l->sigma >> 1)) + (bit_mask & (stripe[k].stripe_l->sigma << 1)) + + (bit_mask & (stripe[k].stripe_r->sigma >> 1)) + (bit_mask & (stripe[k].stripe_r->sigma << 1))); + + if(l == 3) + { + k_v += ((0x01 & stripe[k].stripe_u->sigma) << 3); + k_d += ((0x01 & stripe[k].stripe_u->stripe_l->sigma) + + (0x01 & stripe[k].stripe_u->stripe_r->sigma)) << 3; + } + else if(l == 0) + { + k_v += ((0x08 & stripe[k].stripe_d->sigma) >> 3); + k_d += ((0x08 & stripe[k].stripe_d->stripe_l->sigma) + + (0x08 & stripe[k].stripe_d->stripe_r->sigma)) >> 3; + } + + k_sig = ((15 * k_h + 5 * k_v + k_d) >> l); + + if(k_sig) + { + bit = mq_bit_decode(coder->bitcoder, coder->sig2context[k_sig]); + + if(bit) + { + stripe[k].bit[b] |= (bit << l); + + xi_h = ((bit_mask & stripe[k].stripe_l->sigma) | ((bit_mask & stripe[k].stripe_l->xi) << 2) | + ((bit_mask & stripe[k].stripe_r->sigma) << 1) | ((bit_mask & stripe[k].stripe_r->xi) << 3)) >> l; + + xi_v = ((bit_mask & (stripe[k].sigma >> 1)) | ((bit_mask & (stripe[k].xi >> 1)) << 2) | + ((bit_mask & (stripe[k].sigma << 1)) << 1) | ((bit_mask & (stripe[k].xi << 1)) << 3)) >> l; + + if(l == 3) + { + xi_v |= ((0x01 & stripe[k].stripe_u->sigma) | ((0x01 & stripe[k].stripe_u->xi) << 2)); + } + else if(l == 0) + { + xi_v |= (((0x08 & stripe[k].stripe_d->sigma) >> 2) | (0x08 & stripe[k].stripe_d->xi)); + } + + xi_h = SIG2XI[xi_h]; + xi_v = SIG2XI[xi_v]; + + stripe[k].xi |= ((XI2CONT[(xi_h << 2) | xi_v][1] ^ mq_bit_decode(coder->bitcoder, XI2CONT[(xi_h << 2) | xi_v][0])) << l); + + stripe[k].sigma |= bit_mask; + } + + stripe[k].pi |= bit_mask; + } + } + else + { + stripe[k].pi ^= (stripe[k].pi & bit_mask); + } + } + } + else + { + stripe[k].pi = 0; + } + } + } + + if(rest < 4) + { + for(x = 0; x < coder->width; ++x, ++k) + { + if((stripe[k].sigma^0xF) & stripe_mask) + { + for(bit = stripe[k].bit[b], bit_mask = 0x08, l = 4; l --> rest; bit_mask >>= 1) + { + if(!(stripe[k].sigma & bit_mask)) + { + k_h = (stripe[k].stripe_l->sigma & bit_mask) + (stripe[k].stripe_r->sigma & bit_mask); + + k_v = ((bit_mask & (stripe[k].sigma >> 1)) + (bit_mask & (stripe[k].sigma << 1))); + + k_d = ((bit_mask & (stripe[k].stripe_l->sigma >> 1)) + (bit_mask & (stripe[k].stripe_l->sigma << 1)) + + (bit_mask & (stripe[k].stripe_r->sigma >> 1)) + (bit_mask & (stripe[k].stripe_r->sigma << 1))); + + if(l == 3) + { + k_v += ((0x01 & stripe[k].stripe_u->sigma) << 3); + k_d += ((0x01 & stripe[k].stripe_u->stripe_l->sigma) + + (0x01 & stripe[k].stripe_u->stripe_r->sigma)) << 3; + } + + k_sig = ((15 * k_h + 5 * k_v + k_d) >> l); + + if(k_sig && (stripe[k].sigma^bit_mask)) + { + bit = mq_bit_decode(coder->bitcoder, coder->sig2context[k_sig]); + + if(bit) + { + stripe[k].bit[b] |= (bit << l); + + xi_h = ((bit_mask & stripe[k].stripe_l->sigma) | ((bit_mask & stripe[k].stripe_l->xi) << 2) | + ((bit_mask & stripe[k].stripe_r->sigma) << 1) | ((bit_mask & stripe[k].stripe_r->xi) << 3)) >> l; + + xi_v = ((bit_mask & (stripe[k].sigma >> 1)) | ((bit_mask & (stripe[k].xi >> 1)) << 2) | + ((bit_mask & (stripe[k].sigma << 1)) << 1) | ((bit_mask & (stripe[k].xi << 1)) << 3)) >> l; + + if(l == 3) + { + xi_v |= ((0x01 & stripe[k].stripe_u->sigma) | ((0x01 & stripe[k].stripe_u->xi) << 2)); + } + + xi_h = SIG2XI[xi_h]; + xi_v = SIG2XI[xi_v]; + + stripe[k].xi |= ((XI2CONT[(xi_h << 2) | xi_v][1] ^ mq_bit_decode(coder->bitcoder, XI2CONT[(xi_h << 2) | xi_v][0])) << l); + + stripe[k].sigma |= bit_mask; + } + + stripe[k].pi |= bit_mask; + } + } + else + { + stripe[k].pi ^= (stripe[k].pi & bit_mask); + } + } + } + else + { + stripe[k].pi = 0; + } + } + } + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! - Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +magnitude_refinement_dec_pass(bwc_coder *const coder, const int8 b) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 i, j; + uint64 k, x; + uint16 k_mag; + uint8 bit_mask, stripe_mask; + uint8 l; + uint8 sig; + uint8 rest; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_coder_stripe *stripe; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(coder); + + stripe = coder->data; + stripe_mask= ~((0x0F >> ((coder->height & 0x03))) | 0xF0); + rest = 4 - (coder->height & 0x03); + + for(i = 0, k = 0; i < coder->no_slice; ++i) + { + for(j = 0; j < coder->no_full_stripe; ++j) + { + for(x = 0; x < coder->width; ++x, ++k) + { + sig = stripe[k].sigma & (~stripe[k].pi); + + for(bit_mask = 0x08, l = 4; l --> 0; bit_mask >>= 1) + { + if(sig & bit_mask) + { + k_mag = CONTEXT_MAG; + + if(stripe[k].delta & bit_mask) + { + k_mag += 2; + } + else + { + if((bit_mask & (stripe[k].sigma >> 1)) || (bit_mask & (stripe[k].sigma << 1)) || + (stripe[k].stripe_l->sigma & bit_mask) || (stripe[k].stripe_r->sigma & bit_mask) || + (bit_mask & (stripe[k].stripe_l->sigma >> 1)) || (bit_mask & (stripe[k].stripe_l->sigma << 1)) || + (bit_mask & (stripe[k].stripe_r->sigma >> 1)) || (bit_mask & (stripe[k].stripe_r->sigma << 1))) + { + k_mag += 1; + } + else if((l == 3) && ((0x08 & (stripe[k].stripe_u->sigma << 3)) + || (0x08 & (stripe[k].stripe_u->stripe_l->sigma << 3)) + || (0x08 & (stripe[k].stripe_u->stripe_r->sigma << 3)))) + { + k_mag += 1; + } + else if((l == 0) && ((0x01 & (stripe[k].stripe_d->sigma >> 3)) + || (0x01 & (stripe[k].stripe_d->stripe_l->sigma >> 3)) + || (0x01 & (stripe[k].stripe_d->stripe_r->sigma >> 3)))) + { + k_mag += 1; + } + } + + stripe[k].bit[b] |= (mq_bit_decode(coder->bitcoder, k_mag) << l); + + stripe[k].delta |= bit_mask; + } + } + } + } + + if(rest < 4) + { + for(x = 0; x < coder->width; ++x, ++k) + { + sig = (stripe[k].sigma & (~stripe[k].pi)) & stripe_mask; + + for(bit_mask = 0x08, l = 4; l --> rest; bit_mask >>= 1) + { + if(sig & bit_mask) + { + k_mag = CONTEXT_MAG; + + if(stripe[k].delta & bit_mask) + { + k_mag += 2; + } + else + { + if((bit_mask & (stripe[k].sigma >> 1)) || (bit_mask & (stripe[k].sigma << 1)) || + (stripe[k].stripe_l->sigma & bit_mask) || (stripe[k].stripe_r->sigma & bit_mask) || + (bit_mask & (stripe[k].stripe_l->sigma >> 1)) || (bit_mask & (stripe[k].stripe_l->sigma << 1)) || + (bit_mask & (stripe[k].stripe_r->sigma >> 1)) || (bit_mask & (stripe[k].stripe_r->sigma << 1))) + { + k_mag += 1; + } + else if((l == 3) && ((0x08 & (stripe[k].stripe_u->sigma << 3)) + || (0x08 & (stripe[k].stripe_u->stripe_l->sigma << 3)) + || (0x08 & (stripe[k].stripe_u->stripe_r->sigma << 3)))) + { + k_mag += 1; + } + } + + stripe[k].bit[b] |= (mq_bit_decode(coder->bitcoder, k_mag) << l); + + stripe[k].delta |= bit_mask; + } + } + } + } + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! - Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +cleanup_dec_pass(bwc_coder *const coder, const int8 b) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 i, j; + uint64 k, x; + uint16 k_h, k_v, k_d; + uint16 xi_h, xi_v; + uint8 bit_mask, l; + uint8 bit; + uint8 rest; + int8 r; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_coder_stripe *stripe; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(coder); + + rest = 4 - (coder->height & 0x03); + stripe = coder->data; + + for(i = 0, k = 0; i < coder->no_slice; ++i) + { + for(j = 0; j < coder->no_full_stripe; ++j) + { + for(x = 0; x < coder->width; ++x, ++k) + { + bit = 0; + r = -1; + + if(!(0x08 & stripe[k].stripe_d->stripe_l->sigma) && !(0x08 & stripe[k].stripe_d->sigma) && + !(0x08 & stripe[k].stripe_d->stripe_r->sigma) && !(0x01 & stripe[k].stripe_u->sigma) && + !(0x01 & stripe[k].stripe_u->stripe_l->sigma) && !stripe[k].stripe_l->sigma && + !(0x01 & stripe[k].stripe_u->stripe_r->sigma) && !stripe[k].stripe_r->sigma && + !stripe[k].sigma) + { + if(mq_bit_decode(coder->bitcoder, CONTEXT_RUN)) + { + r = mq_bit_decode(coder->bitcoder, CONTEXT_UNI); + r = (r << 1) + mq_bit_decode(coder->bitcoder, CONTEXT_UNI); + bit |= (0x08 >> r); + } + else + { + r = 4; + } + } + + for(bit_mask = 0x08, l = 4; l --> 0; bit_mask >>= 1) + { + if(!(stripe[k].sigma & bit_mask) && !(stripe[k].pi & bit_mask)) + { + if(r >= 0) + { + r--; + } + else + { + k_h = (stripe[k].stripe_l->sigma & bit_mask) + (stripe[k].stripe_r->sigma & bit_mask); + + k_v = ((bit_mask & (stripe[k].sigma >> 1)) + (bit_mask & (stripe[k].sigma << 1))); + + k_d = ((bit_mask & (stripe[k].stripe_l->sigma >> 1)) + (bit_mask & (stripe[k].stripe_l->sigma << 1)) + + (bit_mask & (stripe[k].stripe_r->sigma >> 1)) + (bit_mask & (stripe[k].stripe_r->sigma << 1))); + + if(l == 3) + { + k_v += ((0x01 & stripe[k].stripe_u->sigma) << 3); + k_d += ((0x01 & stripe[k].stripe_u->stripe_l->sigma) + + (0x01 & stripe[k].stripe_u->stripe_r->sigma)) << 3; + } + else if(l == 0) + { + k_v += ((0x08 & stripe[k].stripe_d->sigma) >> 3); + k_d += ((0x08 & stripe[k].stripe_d->stripe_l->sigma) + + (0x08 & stripe[k].stripe_d->stripe_r->sigma)) >> 3; + } + + bit |= (mq_bit_decode(coder->bitcoder, coder->sig2context[(15 * k_h + 5 * k_v + k_d) >> l]) << l); + } + if(bit & bit_mask) + { + xi_h = ((bit_mask & stripe[k].stripe_l->sigma) | ((bit_mask & stripe[k].stripe_l->xi) << 2) | + ((bit_mask & stripe[k].stripe_r->sigma) << 1) | ((bit_mask & stripe[k].stripe_r->xi) << 3)) >> l; + + xi_v = ((bit_mask & (stripe[k].sigma >> 1)) | ((bit_mask & (stripe[k].xi >> 1)) << 2) | + ((bit_mask & (stripe[k].sigma << 1)) << 1) | ((bit_mask & (stripe[k].xi << 1)) << 3)) >> l; + + if(l == 3) + { + xi_v |= ((0x01 & stripe[k].stripe_u->sigma) | ((0x01 & stripe[k].stripe_u->xi) << 2)); + } + else if(l == 0) + { + xi_v |= (((0x08 & stripe[k].stripe_d->sigma) >> 2) | (0x08 & stripe[k].stripe_d->xi)); + } + + xi_h = SIG2XI[xi_h]; + xi_v = SIG2XI[xi_v]; + + stripe[k].xi |= ((XI2CONT[(xi_h << 2) | xi_v][1] ^ mq_bit_decode(coder->bitcoder, XI2CONT[(xi_h << 2) | xi_v][0])) << l); + + stripe[k].sigma |= bit_mask; + } + } + } + stripe[k].bit[b] |= bit; + } + } + + if(rest < 4) + { + for(x = 0; x < coder->width; ++x, ++k) + { + bit = 0; + + for(bit_mask = 0x08, l = 4; l --> rest; bit_mask >>= 1) + { + if(!(stripe[k].sigma & bit_mask) && !(stripe[k].pi & bit_mask)) + { + k_h = (stripe[k].stripe_l->sigma & bit_mask) + (stripe[k].stripe_r->sigma & bit_mask); + + k_v = ((bit_mask & (stripe[k].sigma >> 1)) + (bit_mask & (stripe[k].sigma << 1))); + + k_d = ((bit_mask & (stripe[k].stripe_l->sigma >> 1)) + (bit_mask & (stripe[k].stripe_l->sigma << 1)) + + (bit_mask & (stripe[k].stripe_r->sigma >> 1)) + (bit_mask & (stripe[k].stripe_r->sigma << 1))); + + if(l == 3) + { + k_v += ((0x01 & stripe[k].stripe_u->sigma) << 3); + k_d += ((0x01 & stripe[k].stripe_u->stripe_l->sigma) + + (0x01 & stripe[k].stripe_u->stripe_r->sigma)) << 3; + } + + bit |= (mq_bit_decode(coder->bitcoder, coder->sig2context[(15 * k_h + 5 * k_v + k_d) >> l]) << l); + + if(bit & bit_mask) + { + xi_h = ((bit_mask & stripe[k].stripe_l->sigma) | ((bit_mask & stripe[k].stripe_l->xi) << 2) | + ((bit_mask & stripe[k].stripe_r->sigma) << 1) | ((bit_mask & stripe[k].stripe_r->xi) << 3)) >> l; + + xi_v = ((bit_mask & (stripe[k].sigma >> 1)) | ((bit_mask & (stripe[k].xi >> 1)) << 2) | + ((bit_mask & (stripe[k].sigma << 1)) << 1) | ((bit_mask & (stripe[k].xi << 1)) << 3)) >> l; + + if(l == 3) + { + xi_v |= ((0x01 & stripe[k].stripe_u->sigma) | ((0x01 & stripe[k].stripe_u->xi) << 2)); + } + + xi_h = SIG2XI[xi_h]; + xi_v = SIG2XI[xi_v]; + + stripe[k].xi |= ((XI2CONT[(xi_h << 2) | xi_v][1] ^ mq_bit_decode(coder->bitcoder, XI2CONT[(xi_h << 2) | xi_v][0])) << l); + + stripe[k].sigma |= bit_mask; + } + } + } + stripe[k].bit[b] |= bit; + } + } + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 07.03.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static uint16 +slope2log(const double lambda) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 exponent, mantissa, raw; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(lambda > 0); + + raw = *(uint64*)λ + + exponent = (uint64)((raw & 0x7FF0000000000000) >> 44) - 0x41F00; + mantissa = (uint64)((raw & 0x000FFFFFFFFFFFFF) >> 44); + raw = (exponent + frac2log[mantissa]) + 0x10000; + + if(raw > 0xFFFF) + { + return 0xFFFF; + } + else if(raw < 2.0) + { + return 2; + } + else + { + return (uint16)raw; + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 07.03.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +compute_convex_hull(bwc_encoded_cblk *const encoded_codeblock, double *const mse) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 delta_L; + uint64 *Length; + uint16 *Slope; + uint8 *h; + uint8 hull[MAXIMUM_NO_PASSES] = {0}; + uint8 hlast, i, j; + + /*-----------------------*\ + ! DEFINE FLOAT VARIABLES: ! + \*-----------------------*/ + double delta_D; + double lambda[MAXIMUM_NO_PASSES + 1] = {0}; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(encoded_codeblock); + + Length = encoded_codeblock->L; + Slope = encoded_codeblock->S; + + h = hull; + hlast = 0; + lambda [0] = 0xFFFFFFFFFFFFFFFF; + + for(i = 0; i < encoded_codeblock->Z; ++i) + { + delta_D = 0; + for(j = hlast; j <= i; ++j) + { + delta_D += mse[j]; + } + delta_L = (hlast > 0) ? (Length[i] - Length[hlast - 1]) : Length[i]; + + if(delta_D > 0) + { + while(delta_D >= (lambda[hlast] * delta_L)) + { + lambda[hlast] = 0; + h--; + hlast = h[0]; + delta_D = 0; + for(j = hlast; j <= i; ++j) + { + delta_D += mse[j]; + } + delta_L = (hlast > 0) ? (Length[i] - Length[hlast - 1]) : Length[i]; + } + + h++; + hlast = i + 1; + h[0] = hlast; + + if(delta_L == 0) + { + if(delta_D < 0) + { + lambda[hlast] = -1; + } + else if(delta_D == 0) + { + lambda[hlast] = 0; + } + else + { + lambda[hlast] = 0xFFFFFFFFFFFFFFFF; + } + } + else + { + lambda[hlast] = delta_D / delta_L; + } + } + else + { + lambda[i + 1] = 0; + } + } + + for(i = 0; i <= encoded_codeblock->Z; ++i) + { + if(lambda[i] < 0) + { + Slope[i] = 1; + } + else if (lambda[i] == 0) + { + if(i == encoded_codeblock->Z) + { + Slope[i] = 1; + } + else + { + Slope[i] = 0; + } + } + else + { + Slope[i] = slope2log(lambda[i]); + } + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: bwc_encoded_cblk* encode_codeblock(bwc_field *const field, bwc_cblk_access *const access, ! +! -------------- bwc_coder_stripe *const codeblock, ! +! const uint64 width, ! +! const uint64 height, ! +! const uint64 depth, ! +! const uint16 dt) ! +! ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! - Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +encode_codeblock(bwc_field *const field, bwc_cblk_access *const access, + bwc_coder_stripe *const codeblock, + const uint64 width, + const uint64 height, + const uint64 depth, + const uint16 dt) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + int64 delta_mse; + int16 k; + uint8 i, j; + + /*-----------------------*\ + ! DEFINE FLOAT VARIABLES: ! + \*-----------------------*/ + double mse[MAXIMUM_NO_PASSES] = {0}; + double mse_scale; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_subb_ctrl *subb_ctrl; + bwc_subb_inf *subb_inf; + bwc_cblk_ctrl *cblk_ctrl; + bwc_encoded_cblk *encoded_cblk; + bwc_coder coder; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert(access); + assert(codeblock); + assert(access->subband->control.highband_flag <= 15); + assert(access->subband->control.Kmax >= + access->codeblock->control.K); + + /*-----------------------*\ + ! DEFINE FUNCTION PTR: ! + \*-----------------------*/ + uint64 (*coding_pass[3])(bwc_coder*, int8) = {significance_propagation_enc_pass, + magnitude_refinement_enc_pass, + cleanup_enc_pass}; + + /*--------------------------------------------------------*\ + ! Save the global, subband and codeblock control, subband ! + ! info and encoded block structure to temporary variables ! + ! to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + + subb_ctrl = &access->subband->control; + subb_inf = &access->subband->info; + + cblk_ctrl = &access->codeblock->control; + + encoded_cblk = access->codeblock->encoded_block; + + /*--------------------------------------------------------*\ + ! Check if there are any significant bits present in the ! + ! current codeblock. If not, set the proper slope value ! + ! and return to the function caller. ! + \*--------------------------------------------------------*/ + if(cblk_ctrl->K == 0) + { + encoded_cblk->S[0] = 0xFFFF; + return; + } + + /*--------------------------------------------------------*\ + ! Calculate the buffer increment and initial buffer size ! + ! used to allocate memory that will hold the compressed ! + ! bitstream and increment the buffer if the initial buffer ! + ! size is insufficient. ! + \*--------------------------------------------------------*/ + coder.buff_incr = width * height * depth * dt; + coder.buff_size = coder.buff_incr * PREC_BYTE; + + /*--------------------------------------------------------*\ + ! Save the height and width and calculate the number of ! + ! full stripes and slices for the current codeblockblock. ! + ! These variables are used to walk through the bwc_coder_ ! + ! stripe structure. ! + \*--------------------------------------------------------*/ + coder.height = height; + coder.width = width; + + coder.no_full_stripe = height >> 2; + coder.no_slice = depth * dt; + + /*--------------------------------------------------------*\ + ! Save the index of the first significant bitplane used to ! + ! walk through the sample bitplanes in the bwc_coder_ ! + ! stripe structure. ! + \*--------------------------------------------------------*/ + coder.K = cblk_ctrl->K; + + /*--------------------------------------------------------*\ + ! Save the error resilience and highband flag in the coder ! + ! structure. These flags are used to signal if an error ! + ! resilient bitstream is to be created and which subband ! + ! the current codeblock belongs to. ! + \*--------------------------------------------------------*/ + coder.erres = control->error_resilience; + coder.highband_flag = subb_ctrl->highband_flag; + + /*--------------------------------------------------------*\ + ! Associate the significance-to-context pointer with the ! + ! appropriate lookup table for the current subband. ! + \*--------------------------------------------------------*/ + switch(coder.highband_flag) + { + case 0: + case 2: + case 4: + case 6: + case 8: + case 10: + case 12: + case 14: + { + coder.sig2context = SIG2CONTEXT_L; + break; + } + case 1: + case 5: + case 9: + case 13: + { + coder.sig2context = SIG2CONTEXT_H; + break; + } + case 3: + case 7: + case 11: + case 15: + { + coder.sig2context = SIG2CONTEXT_HH; + break; + } + } + + /*--------------------------------------------------------*\ + ! Associate the data pointer with the bwc_coder_stripe ! + ! codeblock structure and allocate the memory block used ! + ! to hold the compressed bitstream. ! + \*--------------------------------------------------------*/ + coder.data = codeblock; + coder.compressed = calloc(coder.buff_size, sizeof(uchar)); + if(!coder.compressed) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return; + } + + /*--------------------------------------------------------*\ + ! Initialize the entropy encoder used for the current com- ! + ! pression run. ! + \*--------------------------------------------------------*/ + if(initialize_mq_encoder(&coder, CONTEXT_TOTAL)) + { + return; + } + + /*--------------------------------------------------------*\ + ! Calculate the weighting factor for the distrotion cal- ! + ! culation according to the distortion contribution de- ! + ! scribed in JPEG2000 by David S. Taubman and Michael W. ! + ! Marcellin (p. 378). ! + \*--------------------------------------------------------*/ + mse_scale = subb_inf->dwt_gain; + mse_scale *= (subb_ctrl->qt_step_size * subb_ctrl->qt_step_size); + mse_scale *= pow(2, coder.K * 2); + + /*--------------------------------------------------------*\ + ! Scale the weighting factor to account for the integer ! + ! representation of the distortion lookup tables. ! + \*--------------------------------------------------------*/ + mse_scale /= 0x10000; + + for(i = 2, j = 0, k = coder.K; k --> 0; i = 0) + { + for(; i < 3; ++i, ++j) + { + /*--------------------------------------------------------*\ + ! Reset the bit encoder for the next coding pass. ! + \*--------------------------------------------------------*/ + if(mq_next_run(coder.bitcoder)) + { + return; + } + + delta_mse = coding_pass[i](&coder, k); + mse[j] = delta_mse * mse_scale; + } + /*--------------------------------------------------------*\ + ! Evaluate the number of bytes generated so far by the bit ! + ! encoder and increase the buffer size if necessary. ! + \*--------------------------------------------------------*/ + if(coder.buff_size <= (mq_get_no_bytes(coder.bitcoder) + coder.buff_incr)) + { + coder.buff_size += ((uint64)k >> 1) * coder.buff_incr; + coder.compressed = realloc(coder.compressed, coder.buff_size * sizeof(uchar)); + if(!coder.compressed) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return; + } + + mq_reset_ptr(coder.bitcoder, coder.compressed); + } + /*--------------------------------------------------------*\ + ! If the error resilience flag is set, encode a segmark ! + ! symbol to allow for error detection during decoding. ! + \*--------------------------------------------------------*/ + if(coder.erres) + { + encode_segmark(coder.bitcoder); + } + + /*--------------------------------------------------------*\ + ! Scale the weighting factor to the next bitplane. ! + \*--------------------------------------------------------*/ + mse_scale *= 0.25; + } + /*--------------------------------------------------------*\ + ! Evalute the number of bytes generated by the bit encoder ! + ! and increase the buffer size if necessary. ! + \*--------------------------------------------------------*/ + if(coder.buff_size <= (mq_get_no_bytes(coder.bitcoder) + 16)) + { + coder.buff_size += 16; + coder.compressed = realloc(coder.compressed, coder.buff_size * sizeof(uchar)); + if(!coder.compressed) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return; + } + + mq_reset_ptr(coder.bitcoder, coder.compressed); + } + /*--------------------------------------------------------*\ + ! Flush the remaining bits in the byte buffer to the coder ! + ! output and calculate the minimum truncation lengths. ! + \*--------------------------------------------------------*/ + mq_termination(coder.bitcoder); + + /*--------------------------------------------------------*\ + ! Save the number of significant bitplanes, insignificant ! + ! leading bitplanes and coding passes in the encoded code- ! + ! block structure. ! + \*--------------------------------------------------------*/ + encoded_cblk->K = coder.K; + encoded_cblk->Kmsbs = subb_ctrl->Kmax - coder.K; + encoded_cblk->Z = j; + + /*--------------------------------------------------------*\ + ! Resize the coder output buffer to its optimal size and ! + ! save the memory handle in the encoded codeblock struc- ! + ! ture. ! + \*--------------------------------------------------------*/ + encoded_cblk->data = realloc(coder.compressed, coder.bitcoder->state->L * sizeof(uchar)); + + /*--------------------------------------------------------*\ + ! Save the lengths of the coding passes in the encoded ! + ! codeblock structure. ! + \*--------------------------------------------------------*/ + mq_get_pass_lengths(coder.bitcoder, encoded_cblk); + + /*--------------------------------------------------------*\ + ! Free the entropy encoder structure. ! + \*--------------------------------------------------------*/ + free_mq_encoder(&coder); + + /*--------------------------------------------------------*\ + ! Calculate the slope values of the distortion/rate convex ! + ! hull. ! + \*--------------------------------------------------------*/ + compute_convex_hull(encoded_cblk, mse); +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: bwc_encoded_cblk* encode_codeblock(bwc_field *const field, bwc_cblk_access *const access, ! +! bwc_coder_stripe *const codeblock, ! +! const uint64 width, ! +! const uint64 height, ! +! const uint64 depth, ! +! const uint16 dt) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! - Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +decode_codeblock(bwc_field *const field, bwc_cblk_access *const access, + bwc_coder_stripe *const codeblock, + const uint64 width, + const uint64 height, + const uint64 depth, + const uint16 dt) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + int16 k; + uint8 i, j; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_subb_ctrl *subb_ctrl; + bwc_encoded_cblk *encoded_cblk; + bwc_coder coder; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert(access); + assert(codeblock); + assert(access->subband->control.highband_flag <= 15); + assert(access->subband->control.Kmax >= + access->codeblock->control.K); + + /*-----------------------*\ + ! DEFINE FUNCTION PTR: ! + \*-----------------------*/ + void (*decoding_pass[3])(bwc_coder*, int8) = {significance_propagation_dec_pass, + magnitude_refinement_dec_pass, + cleanup_dec_pass}; + + /*--------------------------------------------------------*\ + ! Save the global, subband and codeblock control and info ! + ! structure to temporary variables to make the code more ! + ! readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + + subb_ctrl = &access->subband->control; + + encoded_cblk = access->codeblock->encoded_block; + + /*--------------------------------------------------------*\ + ! Save the height and width and calculate the number of ! + ! full stripes and slices for the current codeblockblock. ! + ! These variables are used to walk through the bwc_coder_ ! + ! stripe structure. ! + \*--------------------------------------------------------*/ + coder.height = height; + coder.width = width; + + coder.no_full_stripe = height >> 2; + coder.no_slice = depth * dt; + + /*--------------------------------------------------------*\ + ! Save the index of the first significant bitplane used to ! + ! walk through the sample bitplanes in the bwc_coder_ ! + ! stripe structure. ! + \*--------------------------------------------------------*/ + coder.K = encoded_cblk->K; + + /*--------------------------------------------------------*\ + ! Save the error resilience and highband flag in the coder ! + ! structure. These flags are used to signal if an error ! + ! resilient bitstream is to be created and which subband ! + ! the current codeblock belongs to. ! + \*--------------------------------------------------------*/ + coder.erres = control->error_resilience; + coder.highband_flag = subb_ctrl->highband_flag; + + /*--------------------------------------------------------*\ + ! Associate the significance-to-context pointer with the ! + ! appropriate lookup table for the current subband. ! + \*--------------------------------------------------------*/ + switch(coder.highband_flag) + { + case 0: + case 2: + case 4: + case 6: + case 8: + case 10: + case 12: + case 14: + { + coder.sig2context = SIG2CONTEXT_L; + break; + } + case 1: + case 5: + case 9: + case 13: + { + coder.sig2context = SIG2CONTEXT_H; + break; + } + case 3: + case 7: + case 11: + case 15: + { + coder.sig2context = SIG2CONTEXT_HH; + break; + } + } + + /*--------------------------------------------------------*\ + ! Associate the data pointer with the bwc_coder_stripe ! + ! codeblock structure and allocate the memory block used ! + ! to hold the compressed bitstream. ! + \*--------------------------------------------------------*/ + coder.data = codeblock; + coder.compressed = encoded_cblk->data; + + /*--------------------------------------------------------*\ + ! Initialize the entropy encoder used for the current com- ! + ! pression run. ! + \*--------------------------------------------------------*/ + if(initialize_mq_decoder(&coder, CONTEXT_TOTAL, encoded_cblk->L[encoded_cblk->Z - 1])) + { + return; + } + + for(i = 2, j = encoded_cblk->Z, k = coder.K; k --> 0; i = 0) + { + for(; i < 3; ++i, --j) + { + if(j == 0) + { + goto break_out; + } + decoding_pass[i](&coder, k); + } + + if((coder.erres) && (((mq_bit_decode(coder.bitcoder, CONTEXT_UNI) << 3) | + (mq_bit_decode(coder.bitcoder, CONTEXT_UNI) << 2) | + (mq_bit_decode(coder.bitcoder, CONTEXT_UNI) << 1) | + mq_bit_decode(coder.bitcoder, CONTEXT_UNI)) != 0x0A)) + { + goto break_out; + } + } + + break_out: + + /*--------------------------------------------------------*\ + ! Save the last bitplane and coding pass in the data struc-! + ! ture for proper reconstruction. ! + \*--------------------------------------------------------*/ + coder.data->bitplane = (k > 0) ? k : 0; + coder.data->codingpass = i; + + /*--------------------------------------------------------*\ + ! Free the entropy encoder structure. ! + \*--------------------------------------------------------*/ + free_mq_encoder(&coder); +} + +/************************************************************************************************************\ +|| ___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || +|| |__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ || +|| | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] || +|| || +\************************************************************************************************************/ +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 02.07.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uchar +t1_encode(bwc_field *const field, bwc_tile *const tile, bwc_parameter *const parameter) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 c; + uint64 cbSizeX, cbSizeY, cbSizeZ; + uint64 width, height, depth; + int64 buff_size; + int64 j; + uint16 cbSizeTS; + uint16 slope_max, slope_min; + int16 i, z; + uint8 nThreads; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_codeblock *codeblock; + bwc_cblk_inf *cblk_info; + bwc_coder_stripe *working_buffer; + bwc_coder_stripe **memory; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert(tile); + assert(parameter); + + /*--------------------------------------------------------*\ + ! Save the global control structure to a temporary varia- ! + ! ble to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + + /*--------------------------------------------------------*\ + ! Save the minimum and maximum slope values for the cur- ! + ! rent parameter tile to temporary variables to make the ! + ! code more readable. ! + \*--------------------------------------------------------*/ + slope_max = tile->control.slope_max; + slope_min = tile->control.slope_min; + + /*--------------------------------------------------------*\ + ! Evaluate the width, height and depth of the current ! + ! parameter. ! + \*--------------------------------------------------------*/ + width = parameter->info.X1 - parameter->info.X0; + height = parameter->info.Y1 - parameter->info.Y0; + depth = parameter->info.Z1 - parameter->info.Z0; + + /*--------------------------------------------------------*\ + ! Evaluate the number of threads used for the current com- ! + ! pression run. ! + \*--------------------------------------------------------*/ + #if defined (_OPENMP) + nThreads = omp_get_max_threads(); + #else + nThreads = 1; + #endif + + /*--------------------------------------------------------*\ + ! Calculate the size of the buffer that holds the wavelet ! + ! coefficients for the entropy encoding stage. The size of ! + ! the buffer is divided by 4 since the Structure is organ- ! + ! ized in a (4-sample per) stripe pattern. Additionally, ! + ! the size is increased by two to account for boundary ! + ! handling during the entropy encoding stage. ! + \*--------------------------------------------------------*/ + buff_size = (uint64)(1 << (control->cbX + (control->cbY >= 2 ? control->cbY - 2 : 0) + + control->cbZ + control->cbTS)) + 2; + + /*--------------------------------------------------------*\ + ! Allocate the pointer array which holds the memory addres-! + ! es for the working buffers that are used by the OpenMP ! + ! threads during a parallel run. For a serial run the ! + ! pointer array has the size 1. ! + \*--------------------------------------------------------*/ + memory = calloc(nThreads, sizeof(bwc_coder_stripe*)); + if(!memory) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + /*--------------------------------------------------------*\ + ! Allocate the working buffers that are used by the OpenMP ! + ! threads during a parallel run. For a serial run only one ! + ! working buffer is allocated. ! + \*--------------------------------------------------------*/ + for(i = 0; i < nThreads; ++i) + { + memory[i] = calloc(buff_size, sizeof(bwc_coder_stripe)); + if(!memory[i]) + { + // memory allocation error + fprintf(stderr, MEMERROR); + for(; i --> 0;) + { + for(j = buff_size - 1; j --> 0;) + { + free(memory[i][j].bit); + free(memory[i][j].sample); + } + free(memory[i]); + } + free(memory); + return 1; + } + /*--------------------------------------------------------*\ + ! The left and right neighbours for the dummy stripe, re- ! + ! presenting the upper and lower boundary of the code- ! + ! block, are set to the dummy stripe used to describe its ! + ! vertical boundaries to properly uncouple the evaluation ! + ! of the context lables from the neighbouring codeblocks. ! + \*--------------------------------------------------------*/ + memory[i][1].stripe_r = &memory[i][0]; + memory[i][1].stripe_l = &memory[i][0]; + + /*--------------------------------------------------------*\ + ! Allocate the sample and bit arrays used to hold the mag- ! + ! nitude of a wavelet coefficient and its bitplane repre- ! + ! sentation. ! + \*--------------------------------------------------------*/ + for(j = 0; j < buff_size; ++j) + { + memory[i][j].bit = calloc(PREC_BIT, sizeof(uint8)); + memory[i][j].sample = calloc(4, sizeof(uint64)); + if(!memory[i][j].sample || !memory[i][j].bit) + { + // memory allocation error + fprintf(stderr, MEMERROR); + for(; i >= 0; --i) + { + for(; j >= 0; --j) + { + free(memory[i][j].bit); + free(memory[i][j].sample); + } + j = buff_size; + free(memory[i]); + } + free(memory); + return 1; + } + } + } + + #if defined(_OPENMP) + #pragma omp parallel private(working_buffer, codeblock, cblk_info, cbSizeX, cbSizeY, cbSizeZ, cbSizeTS) reduction(max:slope_max) reduction(min:slope_min) + #endif + { + /*--------------------------------------------------------*\ + ! Associate the working buffer pointer to the allocated ! + ! memory block. ! + \*--------------------------------------------------------*/ + #if defined (_OPENMP) + working_buffer = &memory[omp_get_thread_num()][2]; + #else + working_buffer = &memory[0][2]; + #endif + + /*--------------------------------------------------------*\ + ! Loop through and encode all codeblocks for the current ! + ! parameter. ! + \*--------------------------------------------------------*/ + #if defined(_OPENMP) + #pragma omp for + #endif + for(c = 0; c < parameter->control.number_of_codeblocks; ++c) + { + /*--------------------------------------------------------*\ + ! Save the codeblock and codeblock info structure to tempo-! + ! rary variables to make the code more readable. ! + \*--------------------------------------------------------*/ + codeblock = parameter->access[c].codeblock; + cblk_info = &codeblock->info; + + /*--------------------------------------------------------*\ + ! Evaluate the width, height, depth and dt for the current ! + ! codeblock. ! + \*--------------------------------------------------------*/ + cbSizeX = cblk_info->X1 - cblk_info->X0; + cbSizeY = cblk_info->Y1 - cblk_info->Y0; + cbSizeZ = cblk_info->Z1 - cblk_info->Z0; + cbSizeTS = cblk_info->TS1 - cblk_info->TS0; + + /*--------------------------------------------------------*\ + ! Copy the wavelet coefficients for the current codeblock ! + ! from the data to the working buffer memory block. The ! + ! working buffer stores the codeblock in stripes of 4 co- ! + ! efficients. Additionally, a bitplane representation of ! + ! each coefficient is evaluated for easy access during the ! + ! entropy encoding stage. ! + \*--------------------------------------------------------*/ + cblkcopy_forward(working_buffer, parameter->data, + ¶meter->access[c], width, + height, depth); + + /*--------------------------------------------------------*\ + ! Encode the wavelet coefficients for the current code- ! + ! block and save the compressed bitstream (data), number ! + ! of coding passes (Z), number of encoded bitplanes (K), ! + ! number of non-significant, leading bitplanes (Kmsbs), ! + ! truncation points (L) and possible slope values (S) in ! + ! the bwc_encoded_cblk structure. ! + \*--------------------------------------------------------*/ + encode_codeblock(field, ¶meter->access[c], working_buffer, + cbSizeX, cbSizeY, + cbSizeZ, cbSizeTS); + + /*--------------------------------------------------------*\ + ! Check if a compressed bitstream has been created. ! + \*--------------------------------------------------------*/ + if(codeblock->encoded_block->data) + { + /*--------------------------------------------------------*\ + ! Walk through all coding passes, ... ! + \*--------------------------------------------------------*/ + for(z = 0; z <= codeblock->encoded_block->Z; ++z) + { + /*--------------------------------------------------------*\ + ! ...check if a viable slope value has been created... ! + \*--------------------------------------------------------*/ + if(codeblock->encoded_block->S[z]) + { + /*--------------------------------------------------------*\ + ! ...and update the minimum and maximum slope values for ! + ! the current parameter tile. ! + \*--------------------------------------------------------*/ + slope_max = MAX(slope_max, codeblock->encoded_block->S[z]); + slope_min = MIN(slope_min, codeblock->encoded_block->S[z]); + } + } + } + + /*--------------------------------------------------------*\ + ! Reset the working buffer for the next entropy encoding ! + ! pass. ! + \*--------------------------------------------------------*/ + cblkreset_fwd(working_buffer, cbSizeX * ceil((double)cbSizeY/4) * cbSizeZ * cbSizeTS); + } + } + + /*--------------------------------------------------------*\ + ! Update the minimum and maximum slope values for the cur- ! + ! rent parameter tile. ! + \*--------------------------------------------------------*/ + tile->control.slope_max = slope_max; + tile->control.slope_min = slope_min; + + /*--------------------------------------------------------*\ + ! Deallocate the working buffer pointer array and memory ! + ! blocks. ! + \*--------------------------------------------------------*/ + for(i = 0; i < nThreads; ++i) + { + for(j = 0; j < buff_size; ++j) + { + free(memory[i][j].bit); + free(memory[i][j].sample); + } + free(memory[i]); + } + free(memory); + + return 0; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void *test(void) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 02.07.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uchar +t1_decode(bwc_field *const field, bwc_tile *const tile, bwc_parameter *const parameter) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 c; + uint64 cbSizeX, cbSizeY, cbSizeZ; + uint64 width, height, depth; + int64 buff_size; + int64 j; + uint16 cbSizeTS; + int16 i; + uint8 nThreads; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_codeblock *codeblock; + bwc_cblk_inf *cblk_info; + bwc_subb_ctrl *subb_ctrl; + bwc_coder_stripe *working_buffer; + bwc_coder_stripe **memory; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert(tile); + assert(parameter); + + /*--------------------------------------------------------*\ + ! Save the global control structure to a temporary varia- ! + ! ble to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + + /*--------------------------------------------------------*\ + ! Evaluate the width, height and depth of the current ! + ! parameter. ! + \*--------------------------------------------------------*/ + width = parameter->info.X1 - parameter->info.X0; + height = parameter->info.Y1 - parameter->info.Y0; + depth = parameter->info.Z1 - parameter->info.Z0; + + /*--------------------------------------------------------*\ + ! Evaluate the number of threads used for the current de- ! + ! compression run. ! + \*--------------------------------------------------------*/ + #if defined (_OPENMP) + nThreads = omp_get_max_threads(); + #else + nThreads = 1; + #endif + + /*--------------------------------------------------------*\ + ! Calculate the size of the buffer that holds the decoded ! + ! wavelet coefficients. The size of the buffer is divided ! + ! by 4 since the Structure is organized in a (4-sample per)! + ! stripe pattern. Additionally, the size is increased by ! + ! two to account for boundary handling during the entropy ! + ! encoding stage. ! + \*--------------------------------------------------------*/ + buff_size = (uint64)(1 << (control->cbX + (control->cbY >= 2 ? control->cbY - 2 : 0) + + control->cbZ + control->cbTS)) + 2; + + /*--------------------------------------------------------*\ + ! Allocate the pointer array which holds the memory addres-! + ! es for the working buffers that are used by the OpenMP ! + ! threads during a parallel run. For a serial run the ! + ! pointer array has the size 1. ! + \*--------------------------------------------------------*/ + memory = calloc(nThreads, sizeof(bwc_coder_stripe*)); + if(!memory) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + /*--------------------------------------------------------*\ + ! Allocate the working buffers that are used by the OpenMP ! + ! threads during a parallel run. For a serial run only one ! + ! working buffer is allocated. ! + \*--------------------------------------------------------*/ + for(i = 0; i < nThreads; ++i) + { + memory[i] = calloc(buff_size, sizeof(bwc_coder_stripe)); + if(!memory[i]) + { + // memory allocation error + fprintf(stderr, MEMERROR); + for(; i --> 0;) + { + for(j = buff_size - 1; j --> 0;) + { + free(memory[i][j].bit); + free(memory[i][j].sample); + } + free(memory[i]); + } + free(memory); + return 1; + } + /*--------------------------------------------------------*\ + ! The left and right neighbours for the dummy stripe, re- ! + ! presenting the upper and lower boundary of the code- ! + ! block, are set to the dummy stripe used to describe its ! + ! vertical boundaries to properly uncouple the evaluation ! + ! of the context lables from the neighbouring codeblocks. ! + \*--------------------------------------------------------*/ + memory[i][1].stripe_r = &memory[i][0]; + memory[i][1].stripe_l = &memory[i][0]; + + /*--------------------------------------------------------*\ + ! Allocate the sample and bit arrays used to hold the mag- ! + ! nitude of a wavelet coefficient and its bitplane repre- ! + ! sentation. ! + \*--------------------------------------------------------*/ + for(j = 0; j < buff_size; ++j) + { + memory[i][j].bit = calloc(PREC_BIT, sizeof(uint8)); + memory[i][j].sample = calloc(4, sizeof(uint64)); + if(!memory[i][j].sample || !memory[i][j].bit) + { + // memory allocation error + fprintf(stderr, MEMERROR); + for(; i >= 0; --i) + { + for(; j >= 0; --j) + { + free(memory[i][j].bit); + free(memory[i][j].sample); + } + j = buff_size; + free(memory[i]); + } + free(memory); + return 1; + } + } + } + + #if defined(_OPENMP) + #pragma omp parallel private(working_buffer, codeblock, cblk_info, subb_ctrl,\ + cbSizeX, cbSizeY, cbSizeZ, cbSizeTS) + #endif + { + /*--------------------------------------------------------*\ + ! Associate the working buffer pointer to the allocated ! + ! memory block. ! + \*--------------------------------------------------------*/ + #if defined (_OPENMP) + working_buffer = &memory[omp_get_thread_num()][2]; + #else + working_buffer = &memory[0][2]; + #endif + + /*--------------------------------------------------------*\ + ! Loop through and encode all codeblocks for the current ! + ! parameter. ! + \*--------------------------------------------------------*/ + #if defined(_OPENMP) + #pragma omp for + #endif + for(c = 0; c < parameter->control.number_of_codeblocks; ++c) + { + /*--------------------------------------------------------*\ + ! Save the codeblock, subband info and codeblock info and ! + ! control structure to temporary variables to make the ! + ! code more readable. ! + \*--------------------------------------------------------*/ + subb_ctrl = ¶meter->access[c].subband->control; + codeblock = parameter->access[c].codeblock; + cblk_info = &codeblock->info; + + /*--------------------------------------------------------*\ + ! Evaluate the width, height, depth and dt for the current ! + ! codeblock. ! + \*--------------------------------------------------------*/ + cbSizeX = cblk_info->X1 - cblk_info->X0; + cbSizeY = cblk_info->Y1 - cblk_info->Y0; + cbSizeZ = cblk_info->Z1 - cblk_info->Z0; + cbSizeTS = cblk_info->TS1 - cblk_info->TS0; + + /*--------------------------------------------------------*\ + ! Evaluate the index of the first significant bitplane for ! + ! the current codeblock. ! + \*--------------------------------------------------------*/ + codeblock->encoded_block->K = subb_ctrl->Kmax - codeblock->encoded_block->Kmsbs; + + /*--------------------------------------------------------*\ + ! Reset the working buffer for the next entropy encoding ! + ! pass. ! + \*--------------------------------------------------------*/ + cblkreset_inv(working_buffer, cbSizeX, cbSizeY, + cbSizeZ, cbSizeTS); + + if(codeblock->encoded_block->Z > 0) + { + decode_codeblock(field, ¶meter->access[c], working_buffer, + cbSizeX, cbSizeY, + cbSizeZ, cbSizeTS); + } + + /*--------------------------------------------------------*\ + ! Copy the wavelet coefficients for the current codeblock ! + ! from the working buffer to the data memory block. ! + \*--------------------------------------------------------*/ + cblkcopy_inverse(working_buffer, parameter->data, + ¶meter->access[c], width, + height, depth); + } + } + + /*--------------------------------------------------------*\ + ! Deallocate the working buffer pointer array and memory ! + ! blocks. ! + \*--------------------------------------------------------*/ + for(i = 0; i < nThreads; ++i) + { + for(j = 0; j < buff_size; ++j) + { + free(memory[i][j].bit); + free(memory[i][j].sample); + } + free(memory[i]); + } + free(memory); + + return 0; +} diff --git a/1-bwc/src/library/tier2.c b/1-bwc/src/library/tier2.c new file mode 100755 index 0000000..138affd --- /dev/null +++ b/1-bwc/src/library/tier2.c @@ -0,0 +1,1677 @@ +/*================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| DESCRIPTION: || +|| ------------ || +|| || +|| This file describes a set of functions that can be used to de-/encode bwc || +|| codeblocks described by the bwc_field structure according to the embedded block || +|| coding paradigm described by the JPEG 2000 standard. For more information please || +|| refere to JPEG2000 by D. S. Taubman and M. W. Marcellin. || +|| || +|| -------------------------------------------------------------------------------------------- || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are || +|| permitted provided that the following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of || +|| conditions and the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || +|| of conditions and the following disclaimer in the documentation and/or other || +|| materials provided with the distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS || +|| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF || +|| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE || +|| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, || +|| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF || +|| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) || +|| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || +|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, || +|| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*================================================================================================*/ +/************************************************************************************************************\ +|| _ _ _ ____ _ _ _ ___ ____ || +|| | |\ | | | | | | \ |___ || +|| | | \| |___ |___ |__| |__/ |___ || +|| || +\************************************************************************************************************/ +#include +#include +#include +#include +#include +#include +#include + +#include "codestream.h" +#include "bitstream.h" +#include "constants.h" +#include "macros.h" +#include "types.h" +#include "tagtree.h" +#include "tier2.h" + +/************************************************************************************************************\ +|| _ _ ____ ____ ____ ____ ____ || +|| |\/| |__| | |__/ | | [__ || +|| | | | | |___ | \ |__| ___] || +|| || +\************************************************************************************************************/ +/*----------------------------------------------------------------------------------------------------------*\ +! DESCRIPTION: ! +! ------------ ! +! These macros define a variable length encoder and decoder for the delta z (new coding ! +! passes) information. ! +! ! +! Macros: ! +! ------- ! +! Macro Description ! +! ----- ----------- ! +! encode_delta_z - Encoding algorithm used to store the number of new ! +! coding passes in a packet header. ! +! ! +! dencode_delta_z - Decoding algorithm used to extract the number of new ! +! coding passes form a packet header. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 13.05.2019 Patrick Vogler B87D120 V 0.1.0 Macros created ! +\*----------------------------------------------------------------------------------------------------------*/ +#define encode_delta_z(stream, delta_z) \ +{ \ + if(delta_z == 1) \ + { \ + emit_bit(stream, 0); \ + } \ + else if(delta_z == 2) \ + { \ + emit_bit(stream, 1); \ + emit_bit(stream, 0); \ + } \ + else if(delta_z < 6) \ + { \ + delta_z -= 3; \ + emit_bit(stream, 1); \ + emit_bit(stream, 1); \ + emit_bit(stream, 0x02 & delta_z); \ + emit_bit(stream, 0x01 & delta_z); \ + } \ + else if(delta_z < 37) \ + { \ + delta_z -= 6; \ + emit_bit(stream, 1); \ + emit_bit(stream, 1); \ + emit_bit(stream, 1); \ + emit_bit(stream, 1); \ + emit_bit(stream, 0x10 & delta_z); \ + emit_bit(stream, 0x08 & delta_z); \ + emit_bit(stream, 0x04 & delta_z); \ + emit_bit(stream, 0x02 & delta_z); \ + emit_bit(stream, 0x01 & delta_z); \ + } \ + else if(delta_z < 293) \ + { \ + delta_z -= 37; \ + emit_bit(stream, 1); \ + emit_bit(stream, 1); \ + emit_bit(stream, 1); \ + emit_bit(stream, 1); \ + emit_bit(stream, 1); \ + emit_bit(stream, 1); \ + emit_bit(stream, 1); \ + emit_bit(stream, 1); \ + emit_bit(stream, 1); \ + emit_bit(stream, 0x080 & delta_z); \ + emit_bit(stream, 0x040 & delta_z); \ + emit_bit(stream, 0x020 & delta_z); \ + emit_bit(stream, 0x010 & delta_z); \ + emit_bit(stream, 0x008 & delta_z); \ + emit_bit(stream, 0x004 & delta_z); \ + emit_bit(stream, 0x002 & delta_z); \ + emit_bit(stream, 0x001 & delta_z); \ + } \ +} + +#define decode_delta_z(stream, delta_z) \ +{ \ + if(!get_bit(stream)) \ + { \ + delta_z = 1; \ + } \ + else if(!get_bit(stream)) \ + { \ + delta_z = 2; \ + } \ + else \ + { \ + delta_z = (get_bit(stream) << 1) | \ + get_bit(stream); \ + \ + if(delta_z < 3) \ + { \ + delta_z += 3; \ + } \ + else \ + { \ + delta_z = (get_bit(stream) << 4) | \ + (get_bit(stream) << 3) | \ + (get_bit(stream) << 2) | \ + (get_bit(stream) << 1) | \ + get_bit(stream); \ + \ + if(delta_z < 31) \ + { \ + delta_z += 6; \ + } \ + else \ + { \ + delta_z = (get_bit(stream) << 7) | \ + (get_bit(stream) << 6) | \ + (get_bit(stream) << 5) | \ + (get_bit(stream) << 4) | \ + (get_bit(stream) << 3) | \ + (get_bit(stream) << 2) | \ + (get_bit(stream) << 1) | \ + get_bit(stream); \ + \ + delta_z += 37; \ + } \ + } \ + } \ +} + +/************************************************************************************************************\ +|| ___ ____ _ _ _ ____ ___ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || +|| |__] |__/ | | | |__| | |___ |___ | | |\ | | | | | | |\ | [__ || +|| | | \ | \/ | | | |___ | |__| | \| |___ | | |__| | \| ___] || +|| || +\************************************************************************************************************/ +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void encode_length(bitstream *const header, bwc_codeblock *const codeblock, ! +! -------------- int8 const quality_layer, ! +! uchar const estimate) ! +! ! +! ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 29.04.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +encode_length(bitstream *const header, bwc_codeblock *const codeblock, + int8 const quality_layer, + uchar const estimate) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint32 L; + int32 L_bits; + uint16 beta, max_beta; + uint16 cp_bits; + int16 *cp_contr; + int16 z_curr, z_prev; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_cblk_ctrl *cblk_ctrl; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(codeblock); + assert(header); + + /*--------------------------------------------------------*\ + ! Save the global control and info structure to temporary ! + ! variables to make the code more readable. ! + \*--------------------------------------------------------*/ + cblk_ctrl = &codeblock->control; + cp_contr = cblk_ctrl->cp_contr; + + z_curr = cp_contr[quality_layer ] - 1; + z_prev = cp_contr[quality_layer - 1] - 1; + + beta = (!estimate) ? cblk_ctrl->beta : cblk_ctrl->beta_est; + max_beta = beta; + + L = codeblock->encoded_block->L[z_curr] - + ((z_prev >= 0) ? codeblock->encoded_block->L[z_prev] : 0); + + cp_bits = (uint16)log2(z_curr - z_prev); + L_bits = (uint16)log2(L) + 1 - cp_bits; + + max_beta = (max_beta < L_bits) ? L_bits : max_beta; + + while(beta < max_beta) + { + emit_bit(header, 1); + beta++; + } + + emit_bit(header, 0); + + L_bits = 1 << (beta + cp_bits - 1); + + while(L_bits > 0) + { + emit_bit(header, L & L_bits); + L_bits >>= 1; + } + + if(estimate == 0) + { + cblk_ctrl->beta = beta; + cblk_ctrl->beta_est = beta; + } + else if(estimate == 1) + { + cblk_ctrl->beta_est = beta; + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void create_quality_layers(bwc_field *const field, bwc_tile *const tile) ! +! -------------- ! +! ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 29.04.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +decode_length(bitstream *const header, bwc_codeblock *const codeblock, int8 const quality_layer) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint32 i; + uint16 L_bits; + int16 *cp_contr; + int16 z_curr, z_prev; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_cblk_ctrl *cblk_ctrl; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(codeblock); + assert(header); + + cblk_ctrl = &codeblock->control; + cp_contr = cblk_ctrl->cp_contr; + + while(get_bit(header)) + { + cblk_ctrl->beta++; + } + + z_curr = cp_contr[quality_layer ] - 1; + z_prev = cp_contr[quality_layer - 1] - 1; + + L_bits = cblk_ctrl->beta + (uint16)log2(z_curr - z_prev); + + for(i = 0; L_bits > 0; --L_bits) + { + i <<= 1; + i |= get_bit(header); + } + + codeblock->encoded_block->L[z_curr] = ((z_prev >= 0) ? codeblock->encoded_block->L[z_prev] : 0) + i; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: int64 create_packet(bwc_field *const field, bwc_tile *const tile, ! +! -------------- bwc_resolution *const resolution, ! +! uint32 const prec_idx, ! +! int8 const q_layer, ! +! uchar const est) ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is used to assemble a codestream packet for a given precinct (prec_idx) ! +! and quality layer (q_layer). In order to facilitate a fast quality layer creation, ! +! the est flag can be used to instruct the function to merely estimate the packet head- ! +! er size and circumvent the packet body creation. If est > 1 only the header size is ! +! evaluated, while for est = 1 the packet body size is calculated as well. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! tile bwc_tile* - Structure defining a bwc tile. ! +! ! +! resolution bwc_resolution* - Structure defining a bwc resolution ! +! level. ! +! ! +! prec_idx unsigned int(32 bit) - Index of the current precinct. ! +! ! +! q_layer signed int(16 bit) - Index of the current quality layer. ! +! ! +! est unsigned char - Flag used to instruct the function on ! +! wether a header byte size estimation or ! +! a final packet assembly is required. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! integer(16 bit) - Returns the packet header size if successful or -1 if an ! +! error occurred. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 29.04.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static int32 +create_packet(bwc_field *const field, bwc_tile *const tile, + bwc_resolution *const resolution, + uint32 const prec_idx, + int16 const q_layer, + uchar const est) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint32 size, start, end; + uint32 k; + uint16 cb; + int16 *cp_contr; + int16 delta_z; + int8 m; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_packet *packet; + bwc_precinct *precinct; + bwc_codeblock *codeblock; + bitstream *header; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert(tile); + assert(resolution); + + /*--------------------------------------------------------*\ + ! Save the current packet structure to a temporary varia- ! + ! ble to make the code more readable. ! + \*--------------------------------------------------------*/ + packet = &resolution->packet[q_layer * resolution->control.number_of_precincts + prec_idx]; + + /*--------------------------------------------------------*\ + ! Check if the current packet has any codeblock contribu- ! + ! tion. ! + \*--------------------------------------------------------*/ + if(packet->e) + { + /*--------------------------------------------------------*\ + ! Initialize the stream that is used to assemble the pack- ! + ! et header. ! + \*--------------------------------------------------------*/ + header = init_stream(NULL, PACKET_HEADER_SIZE, 'c'); + if(!header) + { + // memory allocation error + return -1; + } + + /*--------------------------------------------------------*\ + ! If the function caller does not specify a packet size es-! + ! timation, allocate the packet body packed stream that is ! + ! used to hold the codeblock contributions to the current ! + ! qualitylayer. ! + \*--------------------------------------------------------*/ + if(!est) + { + packet->body.access = + packet->body.memory = calloc(packet->body.size, sizeof(bwc_stream)); + if(!packet->body.memory) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return -1; + } + } + + /*--------------------------------------------------------*\ + ! Emit the contribution bit to the packet header that sig- ! + ! nals a non-empty packet body. ! + \*--------------------------------------------------------*/ + emit_bit(header, 1); + + /*--------------------------------------------------------*\ + ! Iterate over all codeblocks in all subbands to assemble ! + ! the packet header and, if no estimation has been spec- ! + ! ified, body. ! + \*--------------------------------------------------------*/ + for(m = 0; m < resolution->control.number_of_subbands; ++m) + { + /*--------------------------------------------------------*\ + ! Save the precinct structure to a temporary variable to ! + ! make the code more readable. ! + \*--------------------------------------------------------*/ + precinct = &resolution->subband[m].precinct[prec_idx]; + + for(cb = 0; cb < precinct->control.number_of_codeblocks; ++cb) + { + /*--------------------------------------------------------*\ + ! Save the codeblock and coding pass contribution struc- ! + ! tures to temporary variables to make the code more ! + ! readable. ! + \*--------------------------------------------------------*/ + codeblock = &precinct->codeblock[cb]; + cp_contr = codeblock->control.cp_contr; + + /*--------------------------------------------------------*\ + ! Evaluate the new coding passes added to the packet body ! + ! for the current quality layer. ! + \*--------------------------------------------------------*/ + delta_z = cp_contr[q_layer] - cp_contr[q_layer - 1]; + + /*--------------------------------------------------------*\ + ! Evaluate if the current codeblock already contributed to ! + ! a packet. ! + \*--------------------------------------------------------*/ + if(cp_contr[q_layer - 1] == 0) + { + /*--------------------------------------------------------*\ + ! If no contribution has yet been made, encode the inclu- ! + ! sion tagtree for the current codeblock and... ! + \*--------------------------------------------------------*/ + encode_tagtree(precinct->control.tag_inclusion, header, q_layer + 1, cb, est); + + /*--------------------------------------------------------*\ + ! If the codeblock contributes to the current packet, en- ! + ! code the tagtree for the non-significant most signifi- ! + ! cant bit planes. ! + \*--------------------------------------------------------*/ + if(cp_contr[q_layer]) + { + for(k = 1; k <= codeblock->encoded_block->Kmsbs + 1u; ++k) + { + encode_tagtree(precinct->control.tag_msbs, header, k, cb, est); + } + } + } + else + { + /*--------------------------------------------------------*\ + ! If a contribution has already been made, transmit a flag ! + ! to signal if new coding passes are to be contributed. ! + \*--------------------------------------------------------*/ + emit_bit(header, delta_z); + } + + /*--------------------------------------------------------*\ + ! Check if new coding passes contributions are available. ! + \*--------------------------------------------------------*/ + if(delta_z) + { + /*--------------------------------------------------------*\ + ! If new coding passes are available, encode delta_z and ! + ! the corresponding coding pass lengths in the packet ! + ! header. ! + \*--------------------------------------------------------*/ + encode_delta_z(header, delta_z); + encode_length(header, codeblock, q_layer, est); + + /*--------------------------------------------------------*\ + ! If the final quality layer (est = 1) or packet (est = 0) ! + ! are assembled, evaluate the start and end points as well ! + ! as the size of the contribution in the encoded block ! + ! memory block and... ! + \*--------------------------------------------------------*/ + if(est <= 1) + { + start = (cp_contr[q_layer - 1] == 0) ? 0 : codeblock->encoded_block->L[cp_contr[q_layer - 1] - 1]; + end = (cp_contr[q_layer] == 0) ? 0 : codeblock->encoded_block->L[cp_contr[q_layer] - 1]; + size = end - start; + + /*--------------------------------------------------------*\ + ! ...add up the packet body size for the final quality ! + ! layer assembly or... ! + \*--------------------------------------------------------*/ + if(est == 1) + { + packet->body.size += size; + } + /*--------------------------------------------------------*\ + ! ...copy the contribution to the packet body for the fi- ! + ! nal packet assembly. ! + \*--------------------------------------------------------*/ + else + { + memcpy(packet->body.access, codeblock->encoded_block->data + start, size); + packet->body.access += size; + packet->body.position += size; + } + } + } + } + } + + /*--------------------------------------------------------*\ + ! Flush the remaining bits from the buffer to the header ! + ! stream. ! + \*--------------------------------------------------------*/ + flush_stream(header); + + /*--------------------------------------------------------*\ + ! If a packet header size estimation has been performed ! + ! (est > 0), reset the non-empty packet flag, free the ! + ! header stream and return the estimated number of header ! + ! bytes to the function caller. ! + \*--------------------------------------------------------*/ + if(est) + { + if(est == 2) + { + packet->e = 0; + } + + k = header->L; + terminate_stream(header, NULL); + return k; + } + /*--------------------------------------------------------*\ + ! If the final packet has been assembled, terminate the ! + ! header stream, evaluate the overall packet size and re- ! + ! turn the total number of header bytes to the function ! + ! caller. ! + \*--------------------------------------------------------*/ + else + { + if(terminate_stream(header, &packet->header)) + { + // memory allocation error + return -1; + } + + packet->size = packet->body.size + packet->header.size; + + return packet->header.size; + } + } + else + { + /*--------------------------------------------------------*\ + ! If the packet has no codeblock contributions, reset the ! + ! non-empty packet flag and return a header size of 1 for ! + ! a packet header size estimation or... ! + \*--------------------------------------------------------*/ + if(est) + { + if(est == 2) + { + packet->e = 0; + } + + return 1; + } + /*--------------------------------------------------------*\ + ! ... set the overall packet and header size to 1 and re- ! + ! turn the value to the function caller. ! + \*--------------------------------------------------------*/ + else + { + packet->size = 1; + packet->header.size = 1; + + packet->header.access = + packet->header.memory = calloc(1, sizeof(uchar)); + if(packet->header.memory == NULL) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return -1; + } + + return packet->header.size; + } + } +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: uchar create_packets(bwc_field *const field, bwc_tile *const tile) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function iterates overall quality layers for every precinct in all resolution ! +! levels to create the codestream packets for all tile parameters. If an error occurres ! +! during packet creation the function returns to the function caller with an error flag. ! +! If packet creation for all quality layers belonging to a specific precinct is success- ! +! ful, the function iterates over all codeblocks that are a part of the current precinct, ! +! to free all encoded memory blocks and reset the encoded block structure for the next ! +! compression run. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! tile bwc_tile* - Structure defining a bwc tile. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! uchar - Returns an unsigned char for error handling. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 29.04.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static uchar +create_packets(bwc_field *const field, bwc_tile *const tile) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 cb, p; + uint16 j, r; + uint8 l, m; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_gl_inf *info; + bwc_parameter *parameter; + bwc_resolution *resolution; + bwc_codeblock *codeblock; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert(tile); + + /*--------------------------------------------------------*\ + ! Save the global control and info structure to temporary ! + ! variables to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + info = field->info; + + /*--------------------------------------------------------*\ + ! Iterate overall quality layers for every precinct in all ! + ! resolution levels to create the codestream packets for ! + ! all tile parameters. ! + \*--------------------------------------------------------*/ + for(j = 0; j < info->nPar; ++j) + { + /*--------------------------------------------------------*\ + ! Save the parameter structure to a temporary variable to ! + ! make the code more readable. ! + \*--------------------------------------------------------*/ + parameter = &tile->parameter[j]; + + for(r = 0; r < control->nDecomp + 1; ++r) + { + /*--------------------------------------------------------*\ + ! Save the resolution structure to a temporary variable to ! + ! make the code more readable. ! + \*--------------------------------------------------------*/ + resolution = ¶meter->resolution[r]; + + for(p = 0; p < resolution->control.number_of_precincts; ++p) + { + for(l = 0; l < control->nLayers; ++l) + { + if(create_packet(field, tile, resolution, p, l, 0) < 0) + { + // memory allocation error + return 1; + } + } + + /*--------------------------------------------------------*\ + ! If packet creation for all quality layers belonging to ! + ! the current precinct is successful, iterate over all ! + ! codeblocks that are a part of the current precinct and ! + ! reset the encoded block structure for another compres- ! + ! sion run. ! + \*--------------------------------------------------------*/ + for(m = 0; m < resolution->control.number_of_subbands; ++m) + { + for(cb = 0; cb < resolution->subband[m].precinct[p].control.number_of_codeblocks; ++cb) + { + /*--------------------------------------------------------*\ + ! Save the codeblock structure and to a temporary variable ! + ! to make the code more readable. ! + \*--------------------------------------------------------*/ + codeblock = &resolution->subband[m].precinct[p].codeblock[cb]; + + /*--------------------------------------------------------*\ + ! Free the encoded block memory block that holds the com- ! + ! pressed codeblock bitstream. ! + \*--------------------------------------------------------*/ + free(codeblock->encoded_block->data); + + /*--------------------------------------------------------*\ + ! Reset the encoded block and coding pass contribution ! + ! structure for the next compression run. ! + \*--------------------------------------------------------*/ + memset(codeblock->encoded_block, 0, sizeof(bwc_encoded_cblk)); + memset(codeblock->control.cp_contr, 0, sizeof(int16) * control->nLayers); + } + } + } + } + } + return 0; +} + + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: int64 create_quality_layer(bwc_field *const field, bwc_tile *const tile, ! +! -------------- uint16 const threshold, ! +! int16 const q_layer, ! +! uchar const est) ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function iterates over all codeblocks for every precinct in all resolution levels ! +! to assemble the quality layers for all tile parameters. If an error occurres during ! +! packet creation the function returns to the function caller with an error flag. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! tile bwc_tile* - Structure defining a bwc tile. ! +! ! +! threshold unsigned int(16 bit) - Index of the current quality layer. ! +! ! +! q_layer signed int(16 bit) - Index of the current quality layer. ! +! ! +! est unsigned char - Flag used to instruct the function on ! +! wether a quality layer size estimation ! +! or final assembly is required. ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! integer(16 bit) - Returns the quality layer size if successful or -1 if an ! +! error occurred. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 29.04.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static int64 +create_quality_layer(bwc_field *const field, bwc_tile *const tile, + uint16 const threshold, + int16 const q_layer, + uchar const est) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 cb, nPrec, p; + int64 estimated_ql_size, estimated_ph_size; + uint16 j, r; + int16 *cp_contr; + int16 z; + uint8 l, m; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_gl_inf *info; + bwc_parameter *parameter; + bwc_resolution *resolution; + bwc_subband *subband; + bwc_codeblock *codeblock; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert(tile); + + /*--------------------------------------------------------*\ + ! Save the global control and info structure to temporary ! + ! variables to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + info = field->info; + + for(j = 0, estimated_ql_size = 0; j < info->nPar; ++j) + { + /*--------------------------------------------------------*\ + ! Save the parameter structure to a temporary variable to ! + ! make the code more readable. ! + \*--------------------------------------------------------*/ + parameter = &tile->parameter[j]; + + for(r = 0; r < control->nDecomp + 1; ++r) + { + /*--------------------------------------------------------*\ + ! Save the resolution structure to a temporary variable to ! + ! make the code more readable. ! + \*--------------------------------------------------------*/ + resolution = ¶meter->resolution[r]; + nPrec = resolution->control.number_of_precincts; + + for(m = 0; m < resolution->control.number_of_subbands; ++m) + { + /*--------------------------------------------------------*\ + ! Save the subband structure to a temporary variable to ! + ! make the code more readable. ! + \*--------------------------------------------------------*/ + subband = &resolution->subband[m]; + + for(p = 0; p < resolution->control.number_of_precincts; ++p) + { + for(cb = 0; cb < subband->precinct[p].control.number_of_codeblocks; ++cb) + { + /*--------------------------------------------------------*\ + ! Save the codeblock structure and the coding pass contri- ! + ! bution array to temporary variables to make the code ! + ! readable. ! + \*--------------------------------------------------------*/ + codeblock = &subband->precinct[p].codeblock[cb]; + cp_contr = codeblock->control.cp_contr; + + /*--------------------------------------------------------*\ + ! Loop through all coding passes until the first value is ! + ! reached that is smaller than the prescribed slope thresh-! + ! old. ! + \*--------------------------------------------------------*/ + for(z = codeblock->encoded_block->Z; z >= 0 && codeblock->encoded_block->S[z] < threshold; --z); + + /*--------------------------------------------------------*\ + ! Check if the calculated coding pass has a smaller index ! + ! than the previous quality layer. If true, no additional ! + ! information will be encoded. The coding pass for the ! + ! current quality layer is therefore set to the coding ! + ! pass of the previous quality layer. If no previous qual- ! + ! ity layer has been generated, the length of the first ! + ! coding pass is added to the estimated quality layer ! + ! length. ... ! + \*--------------------------------------------------------*/ + if(z < cp_contr[q_layer - 1]) + { + cp_contr[q_layer] = cp_contr[q_layer - 1]; + + if(cp_contr[q_layer] == 1) + { + estimated_ql_size += codeblock->encoded_block->L[0]; + } + } + /*--------------------------------------------------------*\ + ! If false, the coding pass index is added to the coding ! + ! pass contribution list. If no information has been in- ! + ! cluded in the previous quality layer, or the coding pass ! + ! index is equal to 1, the length of the previous coding ! + ! pass is added to the estimated quality layer length. If ! + ! the previous quality layer contains information, the ! + ! length difference between the two evaluated coding pass- ! + ! es is added. ! + \*--------------------------------------------------------*/ + else + { + cp_contr[q_layer] = z; + + if(z > 0) + { + estimated_ql_size += codeblock->encoded_block->L[z - 1]; + + if(z > 1 && (cp_contr[q_layer - 1] > 0)) + { + estimated_ql_size -= codeblock->encoded_block->L[cp_contr[q_layer - 1] - 1]; + } + } + } + + /*--------------------------------------------------------*\ + ! Check if the current packet has any codeblock contribu- ! + ! tion and set the empty header indicator and its coordi- ! + ! nates accordingly. ! + \*--------------------------------------------------------*/ + if(cp_contr[q_layer] > cp_contr[q_layer - 1]) + { + resolution->packet[q_layer * nPrec + p].e = 1; + } + + /*--------------------------------------------------------*\ + ! If the last, valid quality layer has been correctly cal- ! + ! culated, add the information to the appropriate tagtree. ! + \*--------------------------------------------------------*/ + if(!est) + { + /*--------------------------------------------------------*\ + ! Set the value for the number of non-significant, leading ! + ! bitplanes in the appropriate tagtree. ! + \*--------------------------------------------------------*/ + if(q_layer == 0) + { + tagtree_set_value(subband->precinct[p].control.tag_msbs, cb, codeblock->encoded_block->Kmsbs); + } + + /*--------------------------------------------------------*\ + ! If the last, valid quality layer has been correctly cal- ! + ! culated, add the information to the appropriate tagtree. ! + \*--------------------------------------------------------*/ + if(q_layer + 1 == control->nLayers) + { + for(l = 0; (l < control->nLayers) && (cp_contr[l] == 0); ++l); + + tagtree_set_value(subband->precinct[p].control.tag_inclusion, cb, l); + } + } + } + } + } + + for(p = 0; p < resolution->control.number_of_precincts; ++p) + { + estimated_ph_size = create_packet(field, tile, resolution, p, q_layer, est + 1); + + if(estimated_ph_size < 0) + { + return -1; + } + else + { + estimated_ql_size += estimated_ph_size; + } + + } + } + } + return estimated_ql_size; +} + + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: void create_quality_layers(bwc_field *const field, bwc_tile *const tile) ! +! -------------- ! +! ! +! ! +! DESCRIPTION: ! +! ------------ ! +! DESCRIPTION NEEDED ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! tile bwc_tile* - Structure defining a bwc tile. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! uchar - Returns an unsigned char for error handling. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 29.04.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static uchar +create_quality_layers(bwc_field *const field, bwc_tile *const tile) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 tile_size, header_size; + int64 estimated_tile_size, target_ql_size; + int64 estimated_ql_size; + uint32 main_header_size; + uint16 slope, slope_min, slope_max; + uint16 tmp; + uint8 l; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_gl_ctrl *control; + bwc_gl_inf *info; + bwc_tile_ctrl *tile_control; + bwc_tile_inf *tile_info; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert(tile); + + /*--------------------------------------------------------*\ + ! Save the global and tile control and info structure to ! + ! temporary variables to make the code more readable. ! + \*--------------------------------------------------------*/ + control = &field->control; + info = field->info; + + tile_control = &tile->control; + tile_info = &tile->info; + + /*--------------------------------------------------------*\ + ! Initialize the target and estimated quality layer size ! + ! and the estimated tile size. ! + \*--------------------------------------------------------*/ + target_ql_size = 0; + estimated_ql_size = 0; + estimated_tile_size = 0; + + /*--------------------------------------------------------*\ + ! Calculate the size of the main header, including the end ! + ! of header marker segment. ! + \*--------------------------------------------------------*/ + main_header_size = control->header.size + 4 + (control->nTiles * info->nPar * 2 * PREC_BYTE); + + /*--------------------------------------------------------*\ + ! Calculate the size of the present tile and the overall ! + ! impact of the codestream headers per quality layer. ! + \*--------------------------------------------------------*/ + tile_size = ((tile_info->X1 - tile_info->X0) * (tile_info->Y1 - tile_info->Y0) * + (tile_info->Z1 - tile_info->Z0) * (tile_info->TS1 - tile_info->TS0)) * (uint64)info->nPar; + + header_size = (uint64)ceilf((float)(main_header_size + tile_control->header_size) / control->nLayers); + + /*--------------------------------------------------------*\ + ! Loop through and create all the user specified quality ! + ! layers. ! + \*--------------------------------------------------------*/ + for(l = 0; l < control->nLayers; ++l) + { + /*--------------------------------------------------------*\ + ! Calculate the size of target size of quality layer l. ! + \*--------------------------------------------------------*/ + target_ql_size = (int64)ceilf(control->bitrate[l] * tile_size / 8.0f); + + if(target_ql_size > 0.0f) + { + slope_min = tile_control->slope_min; + slope_max = tile_control->slope_max; + slope = slope_min; + tmp = slope_min; + + while(slope_min < slope_max) + { + slope = (slope_max + slope_min) >> 1; + + estimated_ql_size = create_quality_layer(field, tile, slope, l, 1); + + if(estimated_ql_size >= 0) + { + estimated_ql_size += estimated_tile_size + header_size; + } + else + { + return 1; + } + + if(estimated_ql_size > target_ql_size) + { + if(slope_min == slope) + { + slope_max = slope; + } + slope_min = slope; + } + else if(estimated_ql_size < target_ql_size) + { + if(slope_max == slope) + { + slope_min = slope; + } + slope_max = slope; + tmp = slope; + } + else + { + slope_max = slope; + slope_min = slope; + } + } + + if(estimated_ql_size > target_ql_size) + { + slope = MAX(tmp, tile_control->slope_min); + } + } + else + { + slope = 0; + } + + estimated_ql_size = create_quality_layer(field, tile, slope, l, 0); + + if(estimated_ql_size >= 0) + { + estimated_tile_size += estimated_ql_size + header_size; + } + else + { + return 1; + } + } + return 0; +} + +/************************************************************************************************************\ +|| ___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || +|| |__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ || +|| | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] || +|| || +\************************************************************************************************************/ +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: uchar t2_encode(bwc_field *const field, bwc_tile *const tile) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function defines the rate control portion of the entropy encoding stage. In ! +! the first step, the quality layers are evaluated according to the bitrates de- ! +! fined by the user. The quality layers are then used to create the data packets ! +! that comprise the bwc codestream. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! tile bwc_tile* - Structure defining a bwc tile. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! uchar - Returns an unsigned char for error handling. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 12.06.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uchar +t2_encode(bwc_field *const field, bwc_tile *const tile) +{ + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert(tile); + + /*--------------------------------------------------------*\ + ! Create the quality layers according to the bitrate val- ! + ! ues provided by the user. ! + \*--------------------------------------------------------*/ + if(create_quality_layers(field, tile)) + { + return 1; + } + + /*--------------------------------------------------------*\ + ! Create the data packets according to the quality layers ! + ! evaluated in the previous step. ! + \*--------------------------------------------------------*/ + if(create_packets(field, tile)) + { + return 1; + } + + return 0; +} + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: uchar parse_packet(bwc_field *const field, bwc_tile *const tile, ! +! -------------- bwc_packet *const packet, ! +! uint64 const body_size) ! +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is used to parse a codestream packet for a given precinct (prec_idx) ! +! and quality layer (q_layer). ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! field bwc_field* - Structure defining the compression/ ! +! decompression stage. ! +! ! +! tile bwc_tile* - Structure defining a bwc tile. ! +! ! +! packet bwc_packet* - Structure defining a bwc packet. ! +! ! +! body_size unsigned int(64 bit) - Size of the remaining bwc codestream. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! uchar - Returns an unsigned char for error handling. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 29.04.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +uchar +parse_packet(bwc_field *const field, bwc_tile *const tile, + bwc_packet *const packet, + uint64 const body_size) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint32 size, start, end; + uint32 k; + uint16 cb; + int16 *cp_contr; + int16 delta_z; + int8 m; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_resolution *resolution; + bwc_precinct *precinct; + bwc_codeblock *codeblock; + bwc_encoded_cblk *encoded_block; + bitstream *header; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(field); + assert(tile); + assert(packet); + + resolution = &tile->parameter[packet->c].resolution[packet->r]; + + /*--------------------------------------------------------*\ + ! Initialize the stream that is used to parse the packet ! + ! codestream. ! + \*--------------------------------------------------------*/ + header = init_stream(packet->header.memory, body_size, 'd'); + if(!header) + { + // memory allocation error + return 1; + } + + /*--------------------------------------------------------*\ + ! Extract the codeblock contribution marker from the code- ! + ! stream. ! + \*--------------------------------------------------------*/ + packet->e = get_bit(header); + + /*--------------------------------------------------------*\ + ! Check if the current packet has any codeblock contribu- ! + ! tion. ! + \*--------------------------------------------------------*/ + if(packet->e) + { + /*--------------------------------------------------------*\ + ! Iterate over all codeblocks in all subbands to parse the ! + ! the packet header and body. ! + \*--------------------------------------------------------*/ + for(m = 0; m < resolution->control.number_of_subbands; ++m) + { + /*--------------------------------------------------------*\ + ! Save the precinct structure to a temporary variable to ! + ! make the code more readable. ! + \*--------------------------------------------------------*/ + precinct = &resolution->subband[m].precinct[packet->p]; + + for(cb = 0; cb < precinct->control.number_of_codeblocks; ++cb) + { + /*--------------------------------------------------------*\ + ! Save the codeblock and coding pass contribution struc- ! + ! tures to temporary variables to make the code more ! + ! readable. ! + \*--------------------------------------------------------*/ + codeblock = &precinct->codeblock[cb]; + cp_contr = codeblock->control.cp_contr; + + /*--------------------------------------------------------*\ + ! Initialize the coding passes present in the packet body ! + ! for the current quality layer. ! + \*--------------------------------------------------------*/ + delta_z = 0; + + /*--------------------------------------------------------*\ + ! Evaluate if the current codeblock already contributed to ! + ! a packet. ! + \*--------------------------------------------------------*/ + if(cp_contr[packet->l - 1] == 0) + { + /*--------------------------------------------------------*\ + ! If no contribution has yet been made, decode the inclu- ! + ! sion tagtree for the current codeblock and... ! + \*--------------------------------------------------------*/ + decode_tagtree(precinct->control.tag_inclusion, header, packet->l + 1, cb); + + /*--------------------------------------------------------*\ + ! Check if the codeblock has any contributions to the cur- ! + ! rent packet. If true, decode the tagtree for the none- ! + ! significant bit planes. ! + \*--------------------------------------------------------*/ + if(tagtree_get_value(precinct->control.tag_inclusion, cb) <= packet->l) + { + delta_z = 1; + k = 1; + + while(decode_tagtree(precinct->control.tag_msbs, header, k++, cb)); + + codeblock->encoded_block->Kmsbs = tagtree_get_value(precinct->control.tag_msbs, cb); + } + } + else + { + /*--------------------------------------------------------*\ + ! If a contribution has already been made, extract the ! + ! flag from the codestream that signals if new coding pas- ! + ! ses are available. ! + \*--------------------------------------------------------*/ + delta_z = get_bit(header); + } + + + /*--------------------------------------------------------*\ + ! Initialize the current quality layer with the number of ! + ! coding pass contributions present in the previous qual- ! + ! ity layer. ! + \*--------------------------------------------------------*/ + cp_contr[packet->l] = cp_contr[packet->l - 1]; + + /*--------------------------------------------------------*\ + ! Check if new coding passes contributions are available. ! + \*--------------------------------------------------------*/ + if(delta_z) + { + /*--------------------------------------------------------*\ + ! If new coding passes are available, decode delta_z, ... ! + \*--------------------------------------------------------*/ + decode_delta_z(header, delta_z); + + /*--------------------------------------------------------*\ + ! ... add the additional coding passes to the current qual-! + ! ity layer and update the maximum number of coding passes ! + ! of the current codeblock... ! + \*--------------------------------------------------------*/ + cp_contr[packet->l] += delta_z; + codeblock->encoded_block->Z = cp_contr[packet->l]; + + /*--------------------------------------------------------*\ + ! ... and decode the corresponding coding pass lengths. ! + \*--------------------------------------------------------*/ + decode_length(header, codeblock, packet->l); + } + } + } + } + else + { + /*--------------------------------------------------------*\ + ! Iterate over all codeblocks in all subbands. ! + \*--------------------------------------------------------*/ + for(m = 0; m < resolution->control.number_of_subbands; ++m) + { + /*--------------------------------------------------------*\ + ! Save the precinct structure to a temporary variable to ! + ! make the code more readable. ! + \*--------------------------------------------------------*/ + precinct = &resolution->subband[m].precinct[packet->p]; + + for(cb = 0; cb < precinct->control.number_of_codeblocks; ++cb) + { + /*--------------------------------------------------------*\ + ! Save the codeblock and coding pass contribution struc- ! + ! tures to temporary variables to make the code more ! + ! readable. ! + \*--------------------------------------------------------*/ + codeblock = &precinct->codeblock[cb]; + cp_contr = codeblock->control.cp_contr; + + /*--------------------------------------------------------*\ + ! Initialize the current quality layer with the number of ! + ! coding pass contributions present in the previous qual- ! + ! ity layer. ! + \*--------------------------------------------------------*/ + cp_contr[packet->l] = cp_contr[packet->l - 1]; + } + } + } + + /*--------------------------------------------------------*\ + ! If the header size has not already been evaluated, safe ! + ! the number of used bytes in the appropriate variable. ! + \*--------------------------------------------------------*/ + if(!packet->header.size) + { + packet->header.size = bytes_used(header); + } + + /*--------------------------------------------------------*\ + ! If the packet body memory handle has not been set, safe ! + ! the current position in the header stream in the memory ! + ! and access variables. ! + \*--------------------------------------------------------*/ + if(!packet->body.memory) + { + packet->body.access = + packet->body.memory = get_access(header); + } + + /*--------------------------------------------------------*\ + ! Free the packet header stream. ! + \*--------------------------------------------------------*/ + free(header); + + /*--------------------------------------------------------*\ + ! If the error resilience mode is active for the current ! + ! codestream... ! + \*--------------------------------------------------------*/ + if(field->control.error_resilience) + { + /*--------------------------------------------------------*\ + ! check if the next symbol corresponds to the end of pack- ! + ! header (EOH) marker... ! + \*--------------------------------------------------------*/ + if(packet->body.memory[0] != 0xFF || + packet->body.memory[1] != 0x92) + { + /*--------------------------------------------------------*\ + ! ... If not, return to the function caller with an error ! + ! marker. ! + \*--------------------------------------------------------*/ + return 1; + } + else + { + /*--------------------------------------------------------*\ + ! ... If true, advance the packet body memory and access ! + ! pointer and increase the header size by 2 bytes. ! + \*--------------------------------------------------------*/ + packet->body.access = + packet->body.memory += 2; + packet->header.size += 2; + } + } + + /*--------------------------------------------------------*\ + ! Check if the current packet has any codeblock contribu- ! + ! tion. ! + \*--------------------------------------------------------*/ + if(packet->e) + { + /*--------------------------------------------------------*\ + ! Iterate over all codeblocks in all subbands. ! + \*--------------------------------------------------------*/ + for(m = 0; m < resolution->control.number_of_subbands; ++m) + { + /*--------------------------------------------------------*\ + ! Save the precinct structure to a temporary variable to ! + ! make the code more readable. ! + \*--------------------------------------------------------*/ + precinct = &resolution->subband[m].precinct[packet->p]; + + for(cb = 0; cb < precinct->control.number_of_codeblocks; ++cb) + { + /*--------------------------------------------------------*\ + ! Save the codeblock, encoded codeblock and coding pass ! + ! contribution structures to temporary variables to make ! + ! the code more readable. ! + \*--------------------------------------------------------*/ + codeblock = &precinct->codeblock[cb]; + encoded_block = codeblock->encoded_block; + cp_contr = codeblock->control.cp_contr; + + /*--------------------------------------------------------*\ + ! Check if new contributions are available. ! + \*--------------------------------------------------------*/ + if(cp_contr[packet->l] > cp_contr[packet->l - 1]) + { + /*--------------------------------------------------------*\ + ! Evaluate the start and end position, as well as the size ! + ! of the new contribution in the encoded codeblock memory ! + ! block and. ! + \*--------------------------------------------------------*/ + start = (cp_contr[packet->l - 1] == 0) ? 0 : codeblock->encoded_block->L[cp_contr[packet->l - 1] - 1]; + end = (cp_contr[packet->l] == 0) ? 0 : codeblock->encoded_block->L[cp_contr[packet->l] - 1]; + size = end - start; + + /*--------------------------------------------------------*\ + ! Reallocate the encoded codeblock memory block to accomo- ! + ! date the coding pass contribution. ! + \*--------------------------------------------------------*/ + encoded_block->data = realloc(encoded_block->data, end + size); + if(!encoded_block->data) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return 1; + } + + /*--------------------------------------------------------*\ + ! Copy the data to the encoded block structure. ! + \*--------------------------------------------------------*/ + memcpy(codeblock->encoded_block->data + start, packet->body.access, size); + + /*--------------------------------------------------------*\ + ! Advance the packet body access pointer to the next cod- ! + ! ing pass contribution and increase the packet body size ! + ! accordingly. ! + \*--------------------------------------------------------*/ + packet->body.access += size; + packet->body.size += size; + } + } + } + } + + /*--------------------------------------------------------*\ + ! Evaluate the packet size and return to the function ! + ! caller. ! + \*--------------------------------------------------------*/ + packet->size = packet->header.size + packet->body.size; + return 0; +} \ No newline at end of file diff --git a/1-bwc/src/tools/CMakeLists.txt b/1-bwc/src/tools/CMakeLists.txt new file mode 100755 index 0000000..adf9154 --- /dev/null +++ b/1-bwc/src/tools/CMakeLists.txt @@ -0,0 +1,85 @@ +#*================================================================================================*# +#| |# +#| /$$$$$$$ /$$ /$$ /$$ /$$ |# +#| | $$__ $$|__/ | $$ /$ | $$| $$ |# +#| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ |# +#| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ |# +#| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ |# +#| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ |# +#| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ |# +#| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ |# +#| /$$ \ $$ | $$ |# +#| | $$$$$$/ | $$ |# +#| \______/ |__/ |# +#| |# +#| DESCRIPTION: |# +#| ------------ |# +#| |# +#| Defines the cmake script for the BigWhoop command line tool. |# +#| |# +#| -------------------------------------------------------------------------------------------- |# +#| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart |# +#| |# +#| Redistribution and use in source and binary forms, with or without modification, are |# +#| permitted provided that the following conditions are met: |# +#| |# +#| (1) Redistributions of source code must retain the above copyright notice, this list of |# +#| conditions and the following disclaimer. |# +#| |# +#| (2) Redistributions in binary form must reproduce the above copyright notice, this list |# +#| of conditions and the following disclaimer in the documentation and/or other |# +#| materials provided with the distribution. |# +#| |# +#| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS |# +#| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |# +#| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |# +#| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |# +#| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |# +#| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |# +#| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |# +#| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |# +#| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |# +#| |# +#*================================================================================================*# +#----------------------------------------------------------# +# Add the bwc command line utility and get hash tool to # +# the current project using the utility source files. # +#----------------------------------------------------------# +add_executable(bwccmd bwccmdl.c + ../interfaces/reader/eas3.c) + +#----------------------------------------------------------# +# Set the target compile definition for the requested file # +# format support. # +#----------------------------------------------------------# +MESSAGE(STATUS "EAS3 file format support: ${BUILD_EAS3}") + +if(${BUILD_EAS3}) + target_compile_definitions(bwccmd PRIVATE -DBWC_EAS3) +endif() + +if(${BUILD_NETCDF}) + target_compile_definitions(bwccmd PRIVATE -DBWC_NETCDF) +endif() + +#----------------------------------------------------------# +# Define the output name for the utility binaries. # +#----------------------------------------------------------# +set_property(TARGET bwccmd PROPERTY OUTPUT_NAME bwc) + +#----------------------------------------------------------# +# Setup up the include directory for the bwc utilities. # +#----------------------------------------------------------# +target_include_directories(bwccmd PRIVATE ${CMAKE_SOURCE_DIR}/include/tools) +target_include_directories(bwccmd PRIVATE ${CMAKE_SOURCE_DIR}/include/library/public) +target_include_directories(bwccmd PRIVATE ${CMAKE_SOURCE_DIR}/include/interfaces/reader) + +#----------------------------------------------------------# +# Setup the install directories. # +#----------------------------------------------------------# +install(TARGETS bwccmd DESTINATION ${CMAKE_INSTALL_BINDIR}) + +#----------------------------------------------------------# +# Link the bwc utility to the bwc library. # +#----------------------------------------------------------# +target_link_libraries(bwccmd PRIVATE bwclib m) \ No newline at end of file diff --git a/1-bwc/src/tools/bwccmdl.c b/1-bwc/src/tools/bwccmdl.c new file mode 100644 index 0000000..672d973 --- /dev/null +++ b/1-bwc/src/tools/bwccmdl.c @@ -0,0 +1,3222 @@ +/*====================================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| DESCRIPTION: || +|| ------------ || +|| This is a simple command line tool that uses the Big Whoop library to (de)com- || +|| press a 2- to 4-dimensional IEEE 754 floating point array. For further infor- || +|| mation use the --help (-h) argument in the command-line or consult the appro- || +|| priate README file. || +|| || +|| FILE REFERENCES: || +|| ---------------- || +|| || +|| Name I/O Description || +|| ---- --- ----------- || +|| - input - input - Input file that corresponds to || +|| an uncompressed dataset, for a || +|| compression run, or a com- || +|| pressed bitstream, for a decom- || +|| pression run. || +|| || +|| - output - Output - Output file that the com- || +|| pressed bitstream, for a com- || +|| pression run, or reconstructed || +|| dataset, for a decompression || +|| run, is written to. || +|| || +|| FUNCTIONS: || +|| ---------- || +|| || +|| PRIVATE: PUBLIC: || +|| -------- ------- || +|| - get_digit_sep - main || +|| - get_size || +|| - get_dimension || +|| - get_prog_ord || +|| - get_quant_style || +|| || +|| DEVELOPMENT HISTORY: || +|| -------------------- || +|| || +|| Date Author Change Id Release Description Of Change || +|| ---- ------ --------- ------- --------------------- || +|| 13.10.2017 Patrick Vogler B87D120 V 0.1.0 source file created || +|| 26.11.2020 Patrick Vogler B87E7E4 V 0.1.0 Command line tool refac- || +|| tored. || +|| || +|| || +|| ------------------------------------------------------------------------------------------------------ || +|| || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are permitted || +|| provided that the following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of || +|| conditions and the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || +|| of conditions and the following disclaimer in the documentation and/or other materials || +|| provided with the distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED || +|| WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A || +|| PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR || +|| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT || +|| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS || +|| INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || +|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF || +|| ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*====================================================================================================================*/ +/**********************************************************************************************************************\ +|| _ _ _ ____ _ _ _ ___ ____ || +|| | |\ | | | | | | \ |___ || +|| | | \| |___ |___ |__| |__/ |___ || +|| || +\**********************************************************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bwccmdl.h" +#include "eas3.h" + +/**********************************************************************************************************************\ +|| ____ _ ____ ___ ____ _ ____ ____ _ _ ____ ___ ____ _ _ ___ ____ || +|| | __ | | | |__] |__| | | | | |\ | [__ | |__| |\ | | [__ || +|| |__] |___ |__| |__] | | |___ |___ |__| | \| ___] | | | | \| | ___] || +|| || +\**********************************************************************************************************************/ +/*--------------------------------------------------------------------------------------------------------------------*\ +! ! +! DESCRIPTION: ! +! ------------ ! +! This array defines the arguments supported by the bwc command line tool. Each ! +! argument follows the following structure: ! +! ! +! | flag | long name | short name | opt | type | example | description | ! +! ! +! The flag signals if the argument is active, while the opt and type string def- ! +! ine the argument type and wether it is optional. Finally, the example string ! +! is 24 characters long and highlights how the argument is to be used while the ! +! description should be no longer than 1024 and contain the argument description. ! +! Additionally, the description needs to be subdivided into blocks of 50 charac- ! +! ters for formating. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description ! +! ---- ------ --------- ------- ----------- ! +! 09.07.2019 Patrick Vogler B87D120 V 0.1.0 Constant created. ! +! 03.05.2021 Patrick Vogler B87E7E4 V 0.1.0 Description updated. ! +! ! +\*--------------------------------------------------------------------------------------------------------------------*/ +static bwc_cmdl_args CMDL_ARGS[] = { +//----|---------------------------|-----|---------|---------|---------------------------|--------------------------------------------------| +{1, "compress", "c", "arg", "str1", "-c", "Compress a numerical dataset."}, +//----|---------------------------|-----|---------|---------|---------------------------|--------------------------------------------------| +{1, "decompress", "d", "arg", "str1", "-d", "Decompress a BigWhoop file."}, +//----|---------------------------|-----|---------|---------|---------------------------|--------------------------------------------------| +{1, "analysis", "al", "arg", "lit", "-al", "Analyze the Peak Signal to Noise Ratio (PSNR) and " + "Mean Square Error (MSE) of a decompressed dataset."}, +//----|---------------------------|-----|---------|---------|---------------------------|--------------------------------------------------| +{1, "info", "if", "arg", "str1", "-if", "Display the header information of a BigWhoop file."}, +//----|---------------------------|-----|---------|---------|---------------------------|--------------------------------------------------| +{1, "help", "h", "arg", "lit", "-h", "Print this help message and exit."}, +//----|---------------------------|-----|---------|---------|---------------------------|--------------------------------------------------| +{1, "input", "i", "arg", "str1", "-i /path/to/input", "Valid path to a file that can be parsed/read by " + "this command line tool. For a full list of the " + "supported file extension see the bottom of this " + "message."}, +//----|---------------------------|-----|---------|---------|---------------------------|--------------------------------------------------| +{1, "output", "o", "arg", "str1", "-o /path/to/output", "Valid path and filename that defines the output of" + "the (de)compressed dataset. If not defined, the " + "[input] argument is used to generate the (de)com- " + "pressed output."}, +//----|---------------------------|-----|---------|---------|---------------------------|--------------------------------------------------| +{1, "reference", "rf", "arg", "str1", "-rf /path/to/output", "Valid path to a file that is used as a reference " + "for the [analysis] option."}, +//----|---------------------------|-----|---------|---------|---------------------------|--------------------------------------------------| +{1, "verbose", "v", "opt", "num1", "-v *", "Displays miscellaneous information. This option " + "accepts the value 0 (default) for compression sta-" + "tistics and 1 for the applied compression param. "}, +//----|---------------------------|-----|---------|---------|---------------------------|--------------------------------------------------| +{1, "bitrate", "b", "opt", "numl", "-b *, *, *...", "Defines the quality layers present in the code- " + "stream as a function of the average bits per data " + "point. This option accepts real numbers in the " + "range of 0 < * < 64."}, +//----|---------------------------|-----|---------|---------|---------------------------|--------------------------------------------------| +{1, "codeblock_size", "cb", "opt", "num4", "-cb x=* y=* z=* ts=*", "Defines the codeblocks size for all dimensions and" + "timesteps. This option accepts natural numbers in " + "log2 format in the range of 1 <= * <= 10. The sum " + "of all values has to lie within the range of " + "4 < sum* < 20."}, +//----|---------------------------|-----|---------|---------|---------------------------|--------------------------------------------------| +{1, "compression_ratio", "cr", "opt", "num1", "-cr *", "Defines the ratio between the uncompresssed and " + "uncompressed file size. This option accepts all " + "positive real numbers."}, +//----|---------------------------|-----|---------|---------|---------------------------|--------------------------------------------------| +{1, "decomposition_levels", "dl", "opt", "num4", "-dl x=* y=* z=* ts=*", "Deefines the number of wavelet decompositions ap- " + "plied to all dimensions and timesteps. This option" + "accepts natural numbers in the range of 1 <= * <= " + "63."}, +//----|---------------------------|-----|---------|---------|---------------------------|--------------------------------------------------| +{1, "number_of_threads", "n", "opt", "num1", "-n *", "Defines the number of OpenMP threads used to (de) " + "compress the [input] file. This option accepts " + "natural numbers in the range of 1 <= * <= 255. "}, +//----|---------------------------|-----|---------|---------|---------------------------|--------------------------------------------------| +{1, "layer", "l", "opt", "num1", "-l *", "Defines the quality layer used to generate the nu-" + "merical dataset from the bwc codestream. This op- " + "tion accepts natural numbers in the range of 0 < " + "* <= number_of_quality_layers."}, +//----|---------------------------|-----|---------|---------|---------------------------|--------------------------------------------------| +{0, "wavelet_kernels", "k", "opt", "str4", "-k x=* y=* z=* ts=*", "Ddefines the wavelet kernels applied to all dimen-" + "sions and timesteps. This option accepts the " + "strings CDF, LeGall and Haar."}, +//----|---------------------------|-----|---------|---------|---------------------------|--------------------------------------------------| +{0, "quantisation_step_size", "q", "opt", "num1", "-q *", "Defines the step size of the quantization applied " + "to the wavelet coefficients. This option accepts " + "real numbers in the range of 0 < * < 2."}, +//----|---------------------------|-----|---------|---------|---------------------------|--------------------------------------------------| +{1, "q_format_range", "qm", "opt", "num1", "-qm *", "Defines the Q format's number of fractional bits " + "used to transform the floating to a fixed point " + "format. This option accepts natural numbers in the" + "range of 1 <= * <= 62."}, +//----|---------------------------|-----|---------|---------|---------------------------|--------------------------------------------------| +{1, "error_resilience", "r", "opt", "lit", "-r", "The [error_resilience] option is used to place " + "special markers in the compressed bitstream that " + "help with error detection and limit error propaga-" + "tion."}, +//----|---------------------------|-----|---------|---------|---------------------------|--------------------------------------------------| +{1, "tile_size", "t", "opt", "num4", "-t x=* y=* z=* ts=*", "Defines the tile size for all dimensions and time-" + "steps of a tile. This option accepts natural num- " + "bers in the range of 16 <= * <= domain size."}, +//----|---------------------------|-----|---------|---------|---------------------------|--------------------------------------------------| +{1, "precinct_size", "p", "opt", "num4", "-p x=* y=* z=* ts=*", "Defines the precinct size for all dimensions and " + "timesteps. This option accepts natural numbers in " + "log2 format in the range of 1 <= * <= 15."}, +//----|---------------------------|-----|---------|---------|---------------------------|--------------------------------------------------| +{0, "", "", "end", "", "", ""}}; + +/**********************************************************************************************************************\ +|| ___ ____ _ _ _ ____ ___ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || +|| |__] |__/ | | | |__| | |___ |___ | | |\ | | | | | | |\ | [__ || +|| | | \ | \/ | | | |___ | |__| | \| |___ | | |__| | \| ___] || +|| || +\**********************************************************************************************************************/ +/*----------------------------------------------------------------------------------------------------------*\ +! ! +! DESCRIPTION: ! +! ------------ ! +! This function converts the endianess of half, single or double precision values. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! value void* - Memory address of the parame- ! +! ter to be converted. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description ! +! ---- ------ --------- ------- ----------- ! +! 30.04.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! 21.11.2019 Patrick Vogler B87E7E4 V 0.1.0 functionality expanded ! +! to 32 bit integers ! +! 21.11.2019 Patrick Vogler B87E7E4 V 0.1.0 functionality expanded ! +! to 16 bit integers ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +static void +endian_conversion(void *value, + uint8_t const accuracy) +{ + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(value); + + switch(accuracy) + { + case 2: + { + uint16_t *tmp = (uint16_t*)value; + + *tmp = (uint16_t)( *tmp << 8) | + (uint16_t)( *tmp >> 8); + break; + } + + case 4: + { + uint32_t *tmp = (uint32_t*)value; + + *tmp = (uint32_t)((*tmp << 8) & 0xFF00FF00) | + (uint32_t)((*tmp >> 8) & 0x00FF00FF); + + *tmp = (uint32_t)( *tmp << 16) | + (uint32_t)( *tmp >> 16); + break; + } + + case 8: + { + uint64_t *tmp = (uint64_t*)value; + + *tmp = (uint64_t)((*tmp << 8) & 0xFF00FF00FF00FF00ULL) | + (uint64_t)((*tmp >> 8) & 0x00FF00FF00FF00FFULL); + + *tmp = (uint64_t)((*tmp << 16) & 0xFFFF0000FFFF0000ULL) | + (uint64_t)((*tmp >> 16) & 0x0000FFFF0000FFFFULL); + + *tmp = (uint64_t)( *tmp << 32) | + (uint64_t)( *tmp >> 32); + break; + } + default: + { + break; + } + } +} + +/*--------------------------------------------------------------------------------------------------------------------*\ +! ! +! DESCRIPTION: ! +! ------------ ! +! This function takes a command line argument, checks if it is hyphenated and, ! +! if true, returns a pointer to the first valid character in the string. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! str char* - String containing a command ! +! line argument. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! char* - Pointer to a hyphenated com- ! +! mand line argument. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description ! +! ---- ------ --------- ------- ----------- ! +! 03.05.2021 Patrick Vogler B87D120 V 0.1.0 function created ! +! 04.05.2021 Patrick Vogler B87E7E4 V 0.1.0 clean up ! +! ! +\*--------------------------------------------------------------------------------------------------------------------*/ +static char* +get_opt(char* str) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + size_t trim; + + trim = strspn(str, " "); + + if((trim < strlen(str)) && (str[trim] == '-')) + return &str[trim]; + else + return NULL; +} + +/*--------------------------------------------------------------------------------------------------------------------*\ +! ! +! DESCRIPTION: ! +! ------------ ! +! This function takes an integer value, generates a version with proper digital ! +! group separators and returns the string to the function caller. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! integer unsigned int(64 bit) - Integer value. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! char* - Character array containing the ! +! group seperated integer value. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description ! +! ---- ------ --------- ------- ----------- ! +! 03.02.2020 Patrick Vogler B87D120 V 0.1.0 function created ! +! 04.05.2021 Patrick Vogler B87E7E4 V 0.1.0 clean up ! +! ! +\*--------------------------------------------------------------------------------------------------------------------*/ +static char* +get_digit_sep(uint64_t integer) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64_t multiplier; + uint16_t buffI; + uint8_t length, shift; + + /*-----------------------*\ + ! DEFINE CHAR VARIABLES: ! + \*-----------------------*/ + char buffC[7] = {0}; + char *str; + + /*--------------------------------------------------------*\ + ! Calculate the decimal power of the integer value, esti- ! + ! mate the length of the group seperated string and alloc- ! + ! cate the corresponding character array. ! + \*--------------------------------------------------------*/ + shift = (uint8_t)log10(integer); + length = (uint8_t)floor(shift/3.0f) + shift + 2; + + str = calloc(length, sizeof(char)); + if(str == NULL) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return NULL; + } + + /*--------------------------------------------------------*\ + ! Iterate over the integer value and assemble the group ! + ! serparated string. ! + \*--------------------------------------------------------*/ + do + { + /*--------------------------------------------------------*\ + ! If the first digits do not form a group, decrement the ! + ! shift to the next group, extract the first digits from ! + ! the integer and write them to the string. ! + \*--------------------------------------------------------*/ + if(shift % 3 || shift == 0) + { + shift -= (shift % 3); + multiplier = (uint64_t)pow(10, shift); + buffI = integer/multiplier; + integer -= (uint64_t)buffI * multiplier; + + sprintf(buffC, "%d", buffI); + strcat(str, buffC); + memset(buffC, '\0', 5); + } + /*--------------------------------------------------------*\ + ! If the next digits form a group, decrement the decimal ! + ! shift, extract digits from the integer and write them ! + ! to the string with the proper separator. ! + \*--------------------------------------------------------*/ + else + { + shift -= 3; + multiplier = (uint64_t)pow(10, shift); + buffI = integer/multiplier; + integer -= (uint64_t)buffI * multiplier; + if(strlen(str)) + { + sprintf(buffC, ".%03d", buffI); + } + else + { + sprintf(buffC, "%03d", buffI); + } + strcat(str, buffC); + memset(buffC, '\0', 5); + } + } while(shift); + return str; +} + +/*--------------------------------------------------------------------------------------------------------------------*\ +! ! +! DESCRIPTION: ! +! ------------ ! +! This function takes an integer value and generates a version with the appropri- ! +! ate byte unit in log2 format that is returned to the function caller. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! integer unsigned int(64 bit) - Integer value. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! char* - Character array containing ! +! the group seperated string. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description ! +! ---- ------ --------- ------- ----------- ! +! 03.05.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! 04.05.2021 Patrick Vogler B87E7E4 V 0.1.0 clean up ! +! ! +\*--------------------------------------------------------------------------------------------------------------------*/ +static char* +get_size(uint64_t integer) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64_t multiplier; + uint8_t i; + + /*-----------------------*\ + ! DEFINE CHAR VARIABLES: ! + \*-----------------------*/ + char *sizes[] = { "EiB", "PiB", "TiB", "GiB", "MiB", "KiB", "B" }; + char *str; + + /*--------------------------------------------------------*\ + ! Set up the multiplier used to evaluate the digital unit ! + ! prefix and allocate the character array returned to the ! + ! function caller. ! + \*--------------------------------------------------------*/ + multiplier = 1024ULL * 1024ULL * 1024ULL * + 1024ULL * 1024ULL * 1024ULL; + + str = calloc(10, sizeof(char)); + if(str == NULL) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return NULL; + } + + /*--------------------------------------------------------*\ + ! If larger than 0, iterate over the byte units until the ! + ! integer is within its range and populate the char. array ! + ! with the appropriate information. ! + \*--------------------------------------------------------*/ + if(integer > 0) + { + for(i = 0; i < 7; ++i, multiplier /= 1024) + { + if(integer < multiplier) + continue; + if(integer % multiplier == 0) + sprintf(str, "%" PRIu64 " %s", integer / multiplier, sizes[i]); + else + sprintf(str, "%.1f %s", floor((10.0 * integer) / multiplier) / 10.0, sizes[i]); + break; + } + } + else + { + strcpy(str, "0 B"); + } + return str; +} + + +/*--------------------------------------------------------------------------------------------------------------------*\ +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is a variant of the DJB hash function that takes a string, con- ! +! verts it to uppercase and returns the appropriate hash. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! str char* - String used to generate a u- ! +! niquely identifiable hash. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! uint64_t - Uniquely identifiable hash. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description ! +! ---- ------ --------- ------- ----------- ! +! 17.04.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! 04.05.2021 Patrick Vogler B87E7E4 V 0.1.0 clean up ! +! ! +\*--------------------------------------------------------------------------------------------------------------------*/ +static uint64_t +hash(char* str) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64_t hash; + uint8_t c; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(str); + + /*--------------------------------------------------------*\ + ! Initialize the hash with a magic number. ! + \*--------------------------------------------------------*/ + hash = 0x1505; + + /*--------------------------------------------------------*\ + ! Walk through all the characters in the string, convert ! + ! them to uppercase and use them to generate the hash. ! + \*--------------------------------------------------------*/ + while((c = *str++)) + { + if((c >= 97) && + (c <= 122)) + { + c = c - 32; + } + + hash = (hash * 33) ^ c; + } + + /*--------------------------------------------------------*\ + ! Return the hash. ! + \*--------------------------------------------------------*/ + return hash; +} + +/*--------------------------------------------------------------------------------------------------------------------*\ +! ! +! DESCRIPTION: ! +! ------------ ! +! This function deallocates a util_arg_node linked list that is used to store ! +! the bwc command line arguments. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! args util_arg_node* - Arguments/options linked list ! +! for the bwc command-line tool. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description ! +! ---- ------ --------- ------- ----------- ! +! 24.04.2019 Patrick Vogler B87D120 V 0.1.0 Function created ! +! 04.05.2021 Patrick Vogler B87E7E4 V 0.1.0 clean up ! +! ! +\*--------------------------------------------------------------------------------------------------------------------*/ +static void +bwc_kill_arg(bwc_cmdl_arg_node *args) +{ + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_cmdl_arg_node *temp; + + if(args != NULL) + { + /*--------------------------------------------------------*\ + ! Reset the arguments linked list to its root node. ! + \*--------------------------------------------------------*/ + args = args->root; + + /*--------------------------------------------------------*\ + ! Walk through the arguments linked list and deallocate ! + ! the lit_opt, num_ opt and util_arg_node structure. ! + \*--------------------------------------------------------*/ + while(args != NULL) + { + temp = args; + args = args->next; + + free(temp->lit_opt); + free(temp->num_opt); + free(temp); + } + } +} + +/*--------------------------------------------------------------------------------------------------------------------*\ +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is used to parse the command-line arguments, check if they are ! +! valid arguments and options for the bwc command-line tool and save them in a ! +! linked list. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! argc int - Argument count ! +! ! +! argv char** - Argument vector ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! util_arg_node* - Arguments/options linked list ! +! for the bwc command-line tool. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description ! +! ---- ------ --------- ------- ----------- ! +! 17.04.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! 04.05.2021 Patrick Vogler B87E7E4 V 0.1.0 clean up ! +! ! +\*--------------------------------------------------------------------------------------------------------------------*/ +static bwc_cmdl_arg_node* +parse_arguments(int argc, + char **argv) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64_t buf; + uint64_t *hash_list; + uint64_t *tmp; + + uint16_t l, lsiz; + + uint8_t i, j; + + /*-----------------------*\ + ! DEFINE CHAR VARIABLES: ! + \*-----------------------*/ + char *token, *ptr; + char *str; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_cmdl_arg_node *args; + + /*--------------------------------------------------------*\ + ! Allocate an integer array used to store the hash values ! + ! for all active command line arguments and options. ! + \*--------------------------------------------------------*/ + hash_list = calloc(40, sizeof(uint64_t)); + if(hash_list == NULL) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return NULL; + } + + /*--------------------------------------------------------*\ + ! Loop through the command line argument list and store ! + ! the hash value of the long and short name for all active ! + ! command line arguments in the hash list. ! + \*--------------------------------------------------------*/ + for(l = 0, lsiz = 20; strcmp(CMDL_ARGS[l].arg_type, "end"); ++l) + { + if(l >= lsiz) + { + lsiz *= 2; + hash_list = realloc(hash_list, lsiz * 2 * sizeof(uint64_t)); + if(hash_list == NULL) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return NULL; + } + } + + hash_list[2 * l] = hash(CMDL_ARGS[l].arg_long); + hash_list[2 * l + 1] = hash(CMDL_ARGS[l].arg_short); + } + + /*--------------------------------------------------------*\ + ! Save the total number of active command line arguments, ! + ! reallocate the corresponding hash list and initialize ! + ! the arguments linked list. ! + \*--------------------------------------------------------*/ + lsiz = l; + tmp = realloc(hash_list, lsiz * 2 * sizeof(uint64_t)); + if(tmp == NULL) + { + // memory allocation error + free(hash_list); + fprintf(stderr, MEMERROR); + return NULL; + } + else + { + hash_list = tmp; + } + + args = calloc(1, sizeof(bwc_cmdl_arg_node)); + if(args == NULL) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return NULL; + } + args->root = args; + + /*--------------------------------------------------------*\ + ! Walk through all the command-line arguments passed to ! + ! main. ! + \*--------------------------------------------------------*/ + for(i = 0; i < argc; ++i) + { + /*--------------------------------------------------------*\ + ! Check if the command-line argument is hyphenated, indi- ! + ! cating a bwc argument or option. If this is the case, ! + ! save a pointer to the argument in a temporary variable. ! + \*--------------------------------------------------------*/ + str = get_opt(argv[i]); + + if(str) + { + /*--------------------------------------------------------*\ + ! Generate a hash from the argument string. ! + \*--------------------------------------------------------*/ + buf = hash(++str); + + /*--------------------------------------------------------*\ + ! Check if the command-line argument is a valid bwc argu- ! + ! ment or option and if additional values are expected for ! + ! the current argument or option. The additional values ! + ! are handled according to the type of the current argu- ! + ! ment. ! + \*--------------------------------------------------------*/ + for(l = 0; l < lsiz; ++l) + { + if(buf == hash_list[2 * l] || buf == hash_list[2 * l + 1]) + { + switch(hash(CMDL_ARGS[l].type)) + { + /*--------------------------------------------------------*\ + ! This type of argument/option requires no additional in- ! + ! formation and the parser can advance to the next hyphen- ! + ! ated command-line argument. ! + \*--------------------------------------------------------*/ + case 0x000000000B87DB14: + { + /*--------------------------------------------------------*\ + ! Store the hash identifier in the linked list node. ! + \*--------------------------------------------------------*/ + args->hash = hash_list[2 * l]; + break; + } + + /*--------------------------------------------------------*\ + ! This type of argument/option accepts a single string ! + ! that is passed to the parser as a non-hyphenated ! + ! command-line argument. ! + \*--------------------------------------------------------*/ + case 0x000000017C8A3F41: + { + /*--------------------------------------------------------*\ + ! Store the hash identifier in the linked list node. ! + \*--------------------------------------------------------*/ + args->hash = hash_list[2 * l]; + + /*--------------------------------------------------------*\ + ! Check that the next command-line argument is non-hypenat-! + ! ed. If true, allocate the lit_opt character array and ! + ! store the arguments memory handle. ! + \*--------------------------------------------------------*/ + if(((i + 1) < argc) && (get_opt(argv[i + 1]) == NULL)) + { + args->lit_opt = calloc(args->count + 1, sizeof(char*)); + if(args->lit_opt == NULL) + { + // memory allocation error + fprintf(stderr, MEMERROR); + bwc_kill_arg(args); + free(hash_list); + return NULL; + } + args->lit_opt[args->count++] = argv[i + 1]; + } + break; + } + + /*--------------------------------------------------------*\ + ! This type of argument/option accepts four additional ! + ! strings that are passed to parser as a non-hyphenated ! + ! command-line arguments. ! + \*--------------------------------------------------------*/ + case 0x000000017C8A3F44: + { + /*--------------------------------------------------------*\ + ! Store the hash identifier in the linked list node. ! + \*--------------------------------------------------------*/ + args->hash = hash_list[2 * l]; + + /*--------------------------------------------------------*\ + ! Loop through the next four command-line arguments, check ! + ! that they are non-hyphenated and, if true, store their ! + ! memory handle in the list node. ! + \*--------------------------------------------------------*/ + for(j = i + 1; j < argc && (get_opt(argv[j]) == NULL); ++j) + { + /*--------------------------------------------------------*\ + ! Allocate the lit_opt array for 4 character strings. ! + \*--------------------------------------------------------*/ + if(args->lit_opt == NULL) + { + args->lit_opt = calloc(4, sizeof(char*)); + if(args->lit_opt == NULL) + { + // memory allocation error + fprintf(stderr, MEMERROR); + bwc_kill_arg(args); + free(hash_list); + return NULL; + } + args->count = 0x04; + } + + /*--------------------------------------------------------*\ + ! Save the memory handle for the next argument in a tempo- ! + ! rary variable and tokenize the string according to the ! + ! specified delimiters. ! + \*--------------------------------------------------------*/ + str = argv[j]; + token = strtok_r(str, ":=\t, ", &ptr); + + /*--------------------------------------------------------*\ + ! Check if a valid token has been generated for the first ! + ! spatial direction. If true, save the memory handle, set ! + ! the dimension flag and generate the next token. ! + \*--------------------------------------------------------*/ + if(token && ((strchr(token, 'x') != NULL) || + (strchr(token, 'X') != NULL))) + { + token = strtok_r(NULL, ":=\t, ", &ptr); + args->lit_opt[0] = token; + args->dim |= 0x01; + token = strtok_r(NULL, ":=\t, ", &ptr); + } + + /*--------------------------------------------------------*\ + ! Check if a valid token has been generated for the second ! + ! spatial direction. If true, save the memory handle, set ! + ! the dimension flag and generate the next token. ! + \*--------------------------------------------------------*/ + if(token && ((strchr(token, 'y') != NULL) || + (strchr(token, 'Y') != NULL))) + { + token = strtok_r(NULL, ":=\t, ", &ptr); + args->lit_opt[1] = token; + args->dim |= 0x02; + token = strtok_r(NULL, ":=\t, ", &ptr); + } + + /*--------------------------------------------------------*\ + ! Check if a valid token has been generated for the third ! + ! spatial direction. If true, save the memory handle, set ! + ! the dimension flag and generate the next token. ! + \*--------------------------------------------------------*/ + if(token && ((strchr(token, 'z') != NULL) || + (strchr(token, 'Z') != NULL))) + { + token = strtok_r(NULL, ":=\t, ", &ptr); + args->lit_opt[2] = token; + args->dim |= 0x04; + token = strtok_r(NULL, ":=\t, ", &ptr); + } + + /*--------------------------------------------------------*\ + ! Check if a valid token has been generated for the first ! + ! temporal direction. If true, save the memory handle, set ! + ! the dimension flag and generate the next token. ! + \*--------------------------------------------------------*/ + if(token && ((strchr(token, 't') != NULL) || + (strchr(token, 'T') != NULL))) + { + token = strtok_r(NULL, ":=\t, ", &ptr); + args->lit_opt[3] = token; + args->dim |= 0x08; + token = strtok_r(NULL, ":=\t, ", &ptr); + } + } + break; + } + + /*--------------------------------------------------------*\ + ! This type of argument/option accepts a single numerical ! + ! value that is passed to parser as a non-hyphenated com- ! + ! mand-line argument. ! + \*--------------------------------------------------------*/ + case 0x000000017C82A8C2: + { + /*--------------------------------------------------------*\ + ! Store the hash identifier in the linked list node. ! + \*--------------------------------------------------------*/ + args->hash = hash_list[2 * l]; + + /*--------------------------------------------------------*\ + ! Check that the next command-line argument is non-hypenat-! + ! ed and a valid floating point value. If true, allocate ! + ! the num_opt array and store the real value in it. ! + \*--------------------------------------------------------*/ + if(((i + 1) < argc) && (get_opt(argv[i + 1]) == NULL)) + { + str = argv[i + 1]; + + if(strtof(str, NULL) > 0.0f) + { + args->num_opt = calloc(args->count + 1, sizeof(double)); + if(args->num_opt == NULL) + { + // memory allocation error + fprintf(stderr, MEMERROR); + bwc_kill_arg(args); + free(hash_list); + return NULL; + } + args->num_opt[args->count++] = strtof(str, NULL); + } + } + break; + } + + /*--------------------------------------------------------*\ + ! This type of argument/option accepts four additional nu- ! + ! merical values that are passed to parser as a non-hyphen-! + ! ated command-line arguments. ! + \*--------------------------------------------------------*/ + case 0x000000017C82A8C7: + { + /*--------------------------------------------------------*\ + ! Store the hash identifier in the linked list node. ! + \*--------------------------------------------------------*/ + args->hash = hash_list[2 * l]; + + /*--------------------------------------------------------*\ + ! Loop through the next four command-line arguments, check ! + ! that they are non-hyphenated and, if true, store their ! + ! numerical values handle in the list node. ! + \*--------------------------------------------------------*/ + for(j = i + 1; j < argc && (get_opt(argv[j]) == NULL); ++j) + { + /*--------------------------------------------------------*\ + ! Allocate the num_opt array for 4 real values. ! + \*--------------------------------------------------------*/ + if(args->num_opt == NULL) + { + args->num_opt = calloc(4, sizeof(double)); + if(args->num_opt == NULL) + { + // memory allocation error + fprintf(stderr, MEMERROR); + bwc_kill_arg(args); + free(hash_list); + return NULL; + } + args->count = 0x04; + } + + /*--------------------------------------------------------*\ + ! Save the memory handle for the next argument in a tempo- ! + ! rary variable and tokenize the string according to the ! + ! specified delimiters. ! + \*--------------------------------------------------------*/ + str = argv[j]; + token = strtok_r(str, ":=\t, ", &ptr); + + /*--------------------------------------------------------*\ + ! Check if a valid token has been generated for the first ! + ! spatial direction. If true, save the numerical value, ! + ! set the dimension flag and generate the next token. ! + \*--------------------------------------------------------*/ + if(token && ((strchr(token, 'x') != NULL) || + (strchr(token, 'X') != NULL))) + { + token = strtok_r(NULL, ":=\t, ", &ptr); + if(token != NULL) + { + args->num_opt[0] = strtof(token, NULL); + args->dim |= 0x01; + } + token = strtok_r(NULL, ":=\t, ", &ptr); + } + + /*--------------------------------------------------------*\ + ! Check if a valid token has been generated for the second ! + ! spatial direction. If true, save the numerical value, ! + ! set the dimension flag and generate the next token. ! + \*--------------------------------------------------------*/ + if(token && ((strchr(token, 'y') != NULL) || + (strchr(token, 'Y') != NULL))) + { + token = strtok_r(NULL, ":=\t, ", &ptr); + if(token != NULL) + { + args->num_opt[1] = strtof(token, NULL); + args->dim |= 0x02; + } + token = strtok_r(NULL, ":=\t, ", &ptr); + } + + /*--------------------------------------------------------*\ + ! Check if a valid token has been generated for the third ! + ! spatial direction. If true, save the numerical value, ! + ! set the dimension flag and generate the next token. ! + \*--------------------------------------------------------*/ + if(token && ((strchr(token, 'z') != NULL) || + (strchr(token, 'Z') != NULL))) + { + token = strtok_r(NULL, ":=\t, ", &ptr); + if(token != NULL) + { + args->num_opt[2] = strtof(token, NULL); + args->dim |= 0x04; + } + token = strtok_r(NULL, ":=\t, ", &ptr); + } + + /*--------------------------------------------------------*\ + ! Check if a valid token has been generated for the first ! + ! temporal direction. If true, save the numerical value, ! + ! set the dimension flag and generate the next token. ! + \*--------------------------------------------------------*/ + if(token && ((strchr(token, 't') != NULL) || + (strchr(token, 'T') != NULL))) + { + token = strtok_r(NULL, ":=\t, ", &ptr); + if(token != NULL) + { + args->num_opt[3] = strtof(token, NULL); + args->dim |= 0x08; + } + token = strtok_r(NULL, ":=\t, ", &ptr); + } + } + break; + } + + /*--------------------------------------------------------*\ + ! This type of argument/option accepts one ore more numeri-! + ! cal values that are passed to parser as a non-hyphenated ! + ! command-line arguments. ! + \*--------------------------------------------------------*/ + case 0x000000017C82A8BF: + { + /*--------------------------------------------------------*\ + ! Store the hash identifier in the linked list node. ! + \*--------------------------------------------------------*/ + args->hash = hash_list[2 * l]; + + /*--------------------------------------------------------*\ + ! Loop through the next command-line arguments that are ! + ! non-hyphenated and store their numerical values handle ! + ! in the list node. ! + \*--------------------------------------------------------*/ + for(j = i + 1; j < argc && (get_opt(argv[j]) == NULL); ++j) + { + /*--------------------------------------------------------*\ + ! Save the memory handle for the next argument in a tempo- ! + ! rary variable and tokenize the string according to the ! + ! specified delimiters. ! + \*--------------------------------------------------------*/ + str = argv[j]; + token = strtok_r(str, ", ", &ptr); + + /*--------------------------------------------------------*\ + ! Check if a valid token has been generated. If true, re- ! + ! size the num_opt array, save the numerical value, and ! + ! generate the next token. ! + \*--------------------------------------------------------*/ + for(; (token != NULL); token = strtok_r(NULL, ", ", &ptr)) + { + if(token != NULL) + { + if(strtof(token, NULL) > 0.0f) + { + args->num_opt = realloc(args->num_opt, (args->count + 1) * sizeof(double)); + if(args->num_opt == NULL) + { + // memory allocation error + fprintf(stderr, MEMERROR); + bwc_kill_arg(args); + free(hash_list); + return NULL; + } + args->num_opt[args->count++] = strtof(token, NULL); + } + } + } + } + break; + } + + default: + { + continue; + } + } + /*--------------------------------------------------------*\ + ! Allocate and initialize the next linked list node. ! + \*--------------------------------------------------------*/ + args->next = calloc(1, sizeof(bwc_cmdl_arg_node)); + if(args->next == NULL) + { + // memory allocation error + fprintf(stderr, MEMERROR); + bwc_kill_arg(args); + free(hash_list); + return NULL; + } + args->next->root = args->root; + args = args->next; + } + } + } + } + /*--------------------------------------------------------*\ + ! Free the command line argument hash list and return the ! + ! linked list to the function caller. ! + \*--------------------------------------------------------*/ + free(hash_list); + return args; +} + +/*--------------------------------------------------------------------------------------------------------------------*\ +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is used to parse the util_arg_node linked list and, if it is pre- ! +! sent in linked list, return the memory handle to the bwc argument/option short- ! +! /long-name supplied by the function. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! args util_arg_node* - Arguments/options linked list ! +! for the bwc command-line tool. ! +! ! +! str char* - Long-/short-name of a bwc com- ! +! mand-line argument or option. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! util_arg_nodes* - Memory handle bwc argument ! +! linked list node. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description ! +! ---- ------ --------- ------- ----------- ! +! 24.04.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! 04.05.2021 Patrick Vogler B87E7E4 V 0.1.0 clean up ! +! ! +\*--------------------------------------------------------------------------------------------------------------------*/ +static bwc_cmdl_arg_node* +retrieve_arg(bwc_cmdl_arg_node *const args, + char* name) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64_t arg_hash; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_cmdl_arg_node *temp; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(args); + assert(name); + + /*--------------------------------------------------------*\ + ! Generate a hash from the argument/option name and save ! + ! the root node memory address in a temporary variable. ! + \*--------------------------------------------------------*/ + arg_hash = hash(name); + temp = args->root; + + /*--------------------------------------------------------*\ + ! Advance through the linked list until the argument/op- ! + ! tion, corresponding to the supplied name, has been found ! + ! or the end of the list has been reached. ! + \*--------------------------------------------------------*/ + while(temp->hash != arg_hash && temp->next != NULL) + temp = temp->next; + + /*--------------------------------------------------------*\ + ! If found, return the memory handle to the argument/op- ! + ! option to the function caller. ! + \*--------------------------------------------------------*/ + if((temp->next != NULL) && (temp->hash == arg_hash)) + return temp; + else + return NULL; +} + +/*--------------------------------------------------------------------------------------------------------------------*\ +! ! +! DESCRIPTION: ! +! ------------ ! +! This function prints the help page to the standard output. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! - - - ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description ! +! ---- ------ --------- ------- ----------- ! +! 14.05.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! 03.05.2021 Patrick Vogler B87E7E4 V 0.1.0 clean up ! +! ! +\*--------------------------------------------------------------------------------------------------------------------*/ +static void +print_help(void) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint16_t i; + + /*-----------------------*\ + ! DEFINE CHAR VARIABLES: ! + \*-----------------------*/ + char *buf; + + /*--------------------------------------------------------*\ + ! Write the head of the help message to the standard out- ! + ! put. ! + \*--------------------------------------------------------*/ + printf("Usage: bwc [arguments] [file] [options] (De)compress a specified [file] using [options]. \n"\ + " \n"\ + "e.g.: bwc -c -i [input] -o [output] [options] Compress an [input] file with the specified [op- \n"\ + " tions] and save the compressed bitstream in the \n"\ + " [output] file. \n"\ + " \n"\ + "e.g.: bwc -c [input] [options] Compress an [input] file with the specified [op- \n"\ + " tions] and save the compressed bitstream. \n"\ + " \n"\ + "e.g.: bwc -d -i [input] -o [output] [options] Decompress an [input] file with the specified [op-\n"\ + " tions] and save the decompressed bitstream in the \n"\ + " [output] file. \n"\ + " \n"\ + "e.g.: bwc -d [input] [options] Decompress an [input] file with the specified [op-\n"\ + " tions] and save the decompressed bitstream. \n"\ + " \n"\ + "e.g.: bwc -al -i [input] -ref [reference] Evaluate the Peak-Signal-to-Noise-Ratio of the \n"\ + " [input] file with regards to the [reference] file \n"\ + " and print the result to the standard output. \n"\ + " \n"\ + "e.g.: bwc -if -i [input] Print the header information of the compressed \n"\ + " [input] file to the standard output. \n"\ + " \n"\ + " \n"\ + "Arguments: \n"\ + " \n"\ + " [Type] [Usage] [Description] \n"\ + " \n"); + + /*--------------------------------------------------------*\ + ! Loop through the command line arguments list and write ! + ! the short and long name, usage example and description ! + ! for all mandatory (arg) command line arguments to stdout.! + \*--------------------------------------------------------*/ + for(i = 0; strcmp(CMDL_ARGS[i].arg_type, "end"); ++i) + { + if(strcmp(CMDL_ARGS[i].arg_type, "arg") == 0 && CMDL_ARGS[i].active) + { + printf(" -%s,\t", CMDL_ARGS[i].arg_short); + printf("--%-24s", CMDL_ARGS[i].arg_long); + printf("%-24s", CMDL_ARGS[i].usage); + printf("%.50s\n", CMDL_ARGS[i].definition); + + for(buf = CMDL_ARGS[i].definition + 50; strcmp(buf, ""); buf += 50) + { + printf("%58s%.50s\n", "", buf); + } + + printf("\n"); + } + } + + /*--------------------------------------------------------*\ + ! Write the head of the optional arguments list to the ! + ! standard output. ! + \*--------------------------------------------------------*/ + printf("Options: \n"\ + " \n"\ + " [Type] [Usage] [Description] \n"\ + " \n"); + + /*--------------------------------------------------------*\ + ! Loop through the command line arguments list and write ! + ! the short and long name, usage example and description ! + ! for all optional (arg) command line arguments to stdout. ! + \*--------------------------------------------------------*/ + for(i = 0; strcmp(CMDL_ARGS[i].arg_type, "end"); ++i) + { + if(strcmp(CMDL_ARGS[i].arg_type, "opt") == 0 && CMDL_ARGS[i].active) + { + printf(" -%s,\t", CMDL_ARGS[i].arg_short); + printf("--%-24s", CMDL_ARGS[i].arg_long); + printf("%-24s", CMDL_ARGS[i].usage); + printf("%.50s\n", CMDL_ARGS[i].definition); + + for(buf = CMDL_ARGS[i].definition+50; strcmp(buf, ""); buf += 50) + { + printf("%58s%.50s\n", "", buf); + } + + printf("\n"); + } + } +} + +/*--------------------------------------------------------------------------------------------------------------------*\ +! ! +! DESCRIPTION: ! +! ------------ ! +! This function prints the header information of a compressed dataset to the ! +! standard output. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! args util_arg_node* - Arguments/options linked list ! +! for the bwc command-line tool. ! +! ! +! name char* - Long-/short-name of a bwc com- ! +! mand-line argument or option. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! - - ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description ! +! ---- ------ --------- ------- ----------- ! +! 12.09.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! 17.05.2021 Patrick Vogler B87E7E4 V 0.1.0 clean up ! +! ! +\*--------------------------------------------------------------------------------------------------------------------*/ +static void +output_info(bwc_cmdl_arg_node *const args, + char* name) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64_t data_points; + + uint64_t Ld; + uint32_t Ls; + uint16_t Lh; + + uint32_t t; + uint8_t l, p; + + uint16_t marker; + uint8_t index; + + /*-----------------------*\ + ! DEFINE FLOAT VARIABLES: ! + \*-----------------------*/ + bwc_float minVal, maxVal; + + /*-----------------------*\ + ! DEFINE CHAR VARIABLES: ! + \*-----------------------*/ + char *buff; + uchar status; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_field *field; + bwc_data *data; + + bwc_gl_ctrl *control; + bwc_gl_inf *info; + + bwc_param_ctrl *param_ctrl; + bwc_param_inf *param_info; + + bwc_cmdl_arg_node *temp; + + struct stat buf; + + /*-----------------------*\ + ! DEFINE FILE POINTER: ! + \*-----------------------*/ + FILE *fp; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(args); + + /*--------------------------------------------------------*\ + ! Retrieve the file argument from the linked list and con- ! + ! firm that only one file has been specified and that it ! + ! is a regular file. If true, open the file for reading. ! + \*--------------------------------------------------------*/ + temp = retrieve_arg(args, name); + if((temp == NULL) || + (temp->lit_opt == NULL) || + (temp->lit_opt[0] == NULL)) + { + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: File |\n"\ + "| |\n"\ + "| No File has been specified. |\n"\ + "| |\n"\ + "o##########################################################o\n"); + return; + } + + if(temp->count > 1) + { + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: File |\n"\ + "| |\n"\ + "| More than one file has been specified. |\n"\ + "| |\n"\ + "o##########################################################o\n"); + return; + } + + stat(temp->lit_opt[0], &buf); + if(!S_ISREG(buf.st_mode)) + { + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: file |\n"\ + "| |\n"\ + "| The specified input is not a regular file. |\n"\ + "| |\n"\ + "o##########################################################o\n"); + return; + } + + fp = fopen(temp->lit_opt[0], "rb"); + if(fp == NULL) + { + // error opening file + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: Could not open or read %-25s|\n"\ + "o##########################################################o\n", temp->lit_opt[0]); + return; + } + + /*--------------------------------------------------------*\ + ! Initialize the codestream status and reading index var- ! + ! iables and parse the codestream to evaluate the size of ! + ! the main header. ! + \*--------------------------------------------------------*/ + status = CODESTREAM_OK; + index = 0; + + while(status == 0) + { + Ld = fread(&marker, sizeof(uint16_t), 1, fp); + endian_conversion(&marker, 2); + if((Ld != 1) || (marker < 0xFF00)) + { + // Invalid Codestream + fprintf(stderr, CSTERROR); + fclose(fp); + return; + } + + switch(marker) + { + case SOC: + { + break; + } + + case COM: + case SGC: + case SGI: + default: + { + if(fread(&Lh, sizeof(uint16_t), 1, fp) != 1) + { + // Invalid Codestream + fprintf(stderr, CSTERROR); + fclose(fp); + return; + } + + endian_conversion(&Lh, 2); + fseek(fp, Lh - 2, SEEK_CUR); + + break; + } + + case SAX: + { + if(fread(&Ls, sizeof(uint32_t), 1, fp) != 1) + { + // Invalid Codestream + fprintf(stderr, CSTERROR); + fclose(fp); + return; + } + + endian_conversion(&Ls, 4); + fseek(fp, Ls - 4, SEEK_CUR); + + break; + } + + case EOH: + { + if(fread(&Lh, sizeof(uint16_t), 1, fp) != 1) + { + // Invalid Codestream + fprintf(stderr, CSTERROR); + fclose(fp); + return; + } + + endian_conversion(&Lh, 2); + fseek(fp, Lh - 2, SEEK_CUR); + + status |= CODESTREAM_READ; + break; + } + } + index++; + } + + /*--------------------------------------------------------*\ + ! Determine the size of the main header present in the bwc ! + ! codestream and allocate the data structure, packed code- ! + ! stream sub-structure and its memory block. ! + \*--------------------------------------------------------*/ + Ld = ftell(fp); + fseek(fp, 0L, SEEK_SET); + + data = calloc(1, sizeof(bwc_data)); + if(data == NULL) + { + // memory allocation error + fprintf(stderr, MEMERROR); + fclose(fp); + return; + } + + data->codestream.data = calloc(1, sizeof(bwc_stream)); + if(data->codestream.data == NULL) + { + // memory allocation error + fprintf(stderr, MEMERROR); + bwc_free_data(data); + fclose(fp); + return; + } + + data->codestream.data->memory = calloc(Ld, sizeof(uchar)); + if(data->codestream.data->memory == NULL) + { + // memory allocation error + fprintf(stderr, MEMERROR); + bwc_free_data(data); + fclose(fp); + return; + } + + /*--------------------------------------------------------*\ + ! Read the main header from the packed codestream of the ! + ! user specified bcw file and set up the data structure. ! + \*--------------------------------------------------------*/ + if(fread(data->codestream.data->memory, sizeof(uchar), Ld, fp) != Ld) + { + // invalid read + fprintf(stderr, RDERROR); + bwc_free_data(data); + fclose(fp); + return; + } + + data->codestream.data->access = data->codestream.data->memory; + data->codestream.data->size = Ld; + data->codestream.data->position = 0; + + /*--------------------------------------------------------*\ + ! Initialize the bitstream, parse the main header and set ! + ! up the field structure for the current dataset. ! + \*--------------------------------------------------------*/ + field = bwc_create_decompression(data, 0); + if(field == NULL) + { + bwc_free_data(data); + fclose(fp); + return; + } + control = &field->control; + info = field->info; + + /*--------------------------------------------------------*\ + ! Write the help message to the standard output. ! + \*--------------------------------------------------------*/ + printf("/================================================================================\\\n"\ + "| |\n"\ + "| .:-------------: .:-------------: |\n"\ + "| .+++++++++++++++= :+++++++++++++++- |\n"\ + "| :+++. -++= -++= |\n"\ + "| :+++. -++= -++= |\n"\ + "| -++++++++++++++= -++= -++= |\n"\ + "| .=++---------=++= -++= -++= |\n"\ + "| :+++ :++= -++= -++= |\n"\ + "| .+++=--------=+++---=+++---=+++------------: |\n"\ + "| -=++++++++++++++++++++++++++++++++++++++++- |\n"\ + "| |\n"\ + "|------------------------------ General Information -----------------------------|\n"\ + "| |\n"); + + /*--------------------------------------------------------*\ + ! Print the original file size and format. ! + \*--------------------------------------------------------*/ + data_points = (uint64)info->nX * info->nY * info->nZ * + info->nTS * info->nPar; + buff = get_size(data_points * 8); + + printf("| Original size: %42s |\n"\ + "| Original file format: %42s |\n"\ + "|%80s|\n", buff, info->f_ext, " "); + + free(buff); + + /*--------------------------------------------------------*\ + ! Print the file size and compression ratio. ! + \*--------------------------------------------------------*/ + fseek(fp, 0L, SEEK_END); + Ld = ftell(fp); + buff = get_size(Ld); + fclose(fp); + + printf("| Size on Disk: %42s |\n"\ + "| Comp. Ratio: %42.2f |\n"\ + "|%80s|\n", buff, ((double)data_points * 8.0f/Ld), " "); + + free(buff); + + /*--------------------------------------------------------*\ + ! Print the number of datapoints. ! + \*--------------------------------------------------------*/ + buff = get_digit_sep(data_points); + printf("| Number of Datapoints: %42s |\n"\ + "|%80s|\n", buff, " "); + free(buff); + + buff = get_digit_sep(info->nX); + printf("| -1st Dim.: %42s |\n", buff); + free(buff); + + buff = get_digit_sep(info->nY); + printf("| -2nd Dim.: %42s |\n", buff); + free(buff); + + buff = get_digit_sep(info->nZ); + printf("| -3nd Dim.: %42s |\n", buff); + free(buff); + + buff = get_digit_sep(info->nTS); + printf("| -Time Steps: %42s |\n"\ + "| -No. Params: %42d |\n"\ + "|%80s|\n", buff, info->nPar, " "); + free(buff); + + /*--------------------------------------------------------*\ + ! Print the numerical Datapoints. ! + \*--------------------------------------------------------*/ + printf("|----------------------------- Numerical Parameters -----------------------------|\n"\ + "| |\n"); + + for(p = 0; p < info->nPar; ++p) + { + param_ctrl = &field->tile[0].parameter[p].control; + param_info = &field->tile[0].parameter[p].info; + + minVal = param_info->parameter_min; + maxVal = param_info->parameter_max; + + for(t = 0; t <= control->nTiles; ++t) + { + minVal = MIN(minVal, param_info->parameter_min); + maxVal = MIN(maxVal, param_info->parameter_max); + } + + buff = param_info->name + strlen(param_info->name) - 1; + while(buff > param_info->name && isspace((unsigned char)*buff)) buff--; + buff[1] = '\0'; + + if(p != 0) + { + printf("| ........................................................................ |\n" + "|%80s|\n"," "); + } + + printf("| Name: %55s |\n"\ + "| Minimum value: %55.2e |\n"\ + "| Maximum value: %55.2e |\n", param_info->name, + minVal, + maxVal); + } + printf("|%80s|\n"," "); + /*--------------------------------------------------------*\ + ! Print the quality layers. ! + \*--------------------------------------------------------*/ + printf("|-------------------------------- Quality Layers --------------------------------|\n"\ + "| |\n"); + + for(l = 0; l < control->nLayers; ++l) + { + buff = get_size(data_points * control->bitrate[l]); + + printf("| |\n"\ + "| Quality Layer Nr. %d: %40.2f Bpd |\n"\ + "| %44s |\n", l + 1, control->bitrate[l], buff); + free(buff); + } + + printf("| |\n"\ + "\\--------------------------------------------------------------------------------/\n"); + + /*--------------------------------------------------------*\ + ! Free the field structure. ! + \*--------------------------------------------------------*/ + bwc_kill_compression(field); + bwc_free_data(data); +} + +/*--------------------------------------------------------------------------------------------------------------------*\ +! ! +! DESCRIPTION: ! +! ------------ ! +! This function opens a bwc file, checks it for its validity and loads its con- ! +! tent into a properly set up bwc_data structure. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! filename char* - Name of the bwc file that is ! +! to be opened and read. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! bwc_data* - Structure containing a code- ! +! stream/numerical dataset. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description ! +! ---- ------ --------- ------- ----------- ! +! 20.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! 17.05.2021 Patrick Vogler B87E7E4 V 0.1.0 clean up ! +! ! +\*--------------------------------------------------------------------------------------------------------------------*/ +static bwc_data* +read_bwc(char *const filename) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64_t Lfield; + uint16_t root; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_data *file; + + /*-----------------------*\ + ! DEFINE FILE POINTER: ! + \*-----------------------*/ + FILE *fp; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(filename); + + /*--------------------------------------------------------*\ + ! Open the specified file for reading and, if succesful, ! + ! determine the size of the codestream. If the file could ! + ! not be opened, print an error message to stderr and exit.! + \*--------------------------------------------------------*/ + fp = fopen(filename, "rb"); + if(fp != NULL) + { + root = ftell(fp); + fseek(fp, 0L, SEEK_END); + Lfield = ftell(fp) - root; + fseek(fp, root, SEEK_SET); + } + else + { + // error opening file + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: Could not open or read %-25s|\n"\ + "o##########################################################o\n", filename); + return NULL; + } + + /*--------------------------------------------------------*\ + ! Allocate the data and packed codestream structure as ! + ! well as the memory block that will hold the codestream. ! + \*--------------------------------------------------------*/ + file = calloc(1, sizeof(bwc_data)); + if(file == NULL) + { + // memory allocation error + fprintf(stderr, MEMERROR); + fclose(fp); + return NULL; + } + + file->codestream.data = calloc(1, sizeof(bwc_stream)); + if(file->codestream.data == NULL) + { + // memory allocation error + fprintf(stderr, MEMERROR); + bwc_free_data(file); + fclose(fp); + return NULL; + } + + file->codestream.data->memory = calloc(Lfield, sizeof(uchar)); + if(file->codestream.data->memory == NULL) + { + // memory allocation error + fprintf(stderr, MEMERROR); + bwc_free_data(file); + fclose(fp); + return NULL; + } + + /*--------------------------------------------------------*\ + ! Read the compressed bitstream from the file and, if suc- ! + ! essfull, properly set up the packed codestream and re- ! + ! turn the bwc_data structre to the function caller. ! + \*--------------------------------------------------------*/ + if(fread(file->codestream.data->memory, sizeof(uchar), Lfield, fp) != Lfield) + { + // invalid read + fprintf(stderr, RDERROR); + bwc_free_data(file); + fclose(fp); + return NULL; + } + + file->codestream.data->access = file->codestream.data->memory; + file->codestream.data->size = Lfield; + file->codestream.data->position = 0; + + fclose(fp); + return file; +} + +/*--------------------------------------------------------------------------------------------------------------------*\ +! ! +! DESCRIPTION: ! +! ------------ ! +! This function opens a bwc file, checks it for its validity and writes the code- ! +! stream, provided by the function caller, to the file. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! filename char* - Name of the bwc file that is ! +! to be created. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! unsigned char - Returns an unsigned char for ! +! error handling. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description ! +! ---- ------ --------- ------- ----------- ! +! 20.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! +! 17.05.2021 Patrick Vogler B87E7E4 V 0.1.0 clean up ! +! ! +\*--------------------------------------------------------------------------------------------------------------------*/ +static uchar +write_bwc(bwc_data *const data, + char *const filename) +{ + /*-----------------------*\ + ! DEFINE FILE POINTER: ! + \*-----------------------*/ + FILE *fp; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(data); + assert(filename); + + /*--------------------------------------------------------*\ + ! Open the specified file for writing If the file could ! + ! not be opened, print an error message to stderr and exit.! + \*--------------------------------------------------------*/ + fp = fopen(filename, "wb"); + if(fp == NULL) + { + // error opening file + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: Could not open %-33s|\n"\ + "o##########################################################o\n", filename); + return EXIT_FAILURE; + } + + /*--------------------------------------------------------*\ + ! Write the compressed codestream to file and, if success- ! + ! ful, close the file ptr and return to the fun. caller. ! + \*--------------------------------------------------------*/ + if(fwrite(data->codestream.data->memory, sizeof(uchar), data->codestream.data->size, fp) != + data->codestream.data->size) + { + // error opening file + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: Could not write to %-29s|\n"\ + "o##########################################################o\n", filename); + fclose(fp); + return EXIT_FAILURE; + } + + fclose(fp); + return EXIT_SUCCESS; +} + +/*--------------------------------------------------------------------------------------------------------------------*\ +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is a wrapper that is used to invoke the appropriate read func- ! +! tion according to the file extension of the user supplied filename. The data- ! +! set is stored in the bwc_data structure and passed onto the function caller. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! args util_arg_node* - Arguments/options linked list ! +! for the bwc command-line tool. ! +! ! +! str char* - Long-/short-name of a bwc com- ! +! mand-line argument or option. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! bwc_data* - Structure containing a code- ! +! stream/numerical dataset. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description ! +! ---- ------ --------- ------- ----------- ! +! 14.05.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! 03.05.2021 Patrick Vogler B87E7E4 V 0.1.0 clean up ! +! ! +\*--------------------------------------------------------------------------------------------------------------------*/ +static bwc_data* +read_file(bwc_cmdl_arg_node *const args, + char* name) +{ + /*-----------------------*\ + ! DEFINE CHAR VARIABLES: ! + \*-----------------------*/ + char *str; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_cmdl_arg_node *temp; + bwc_data *file; + struct stat buf; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(args); + assert(name); + + /*--------------------------------------------------------*\ + ! Retrieve the file argument from the linked list and con- ! + ! firm that only one file has been specified and that it ! + ! is a regular file. ! + \*--------------------------------------------------------*/ + temp = retrieve_arg(args, name); + if((temp == NULL) || + (temp->lit_opt == NULL) || + (temp->lit_opt[0] == NULL)) + { + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: File |\n"\ + "| |\n"\ + "| No File has been specified. |\n"\ + "| |\n"\ + "o##########################################################o\n"); + return NULL; + } + + if(temp->count > 1) + { + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: File |\n"\ + "| |\n"\ + "| More than one file has been specified. |\n"\ + "| |\n"\ + "o##########################################################o\n"); + return NULL; + } + + stat(temp->lit_opt[0], &buf); + if(!S_ISREG(buf.st_mode)) + { + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: file |\n"\ + "| |\n"\ + "| The specified input is not a regular file. |\n"\ + "| |\n"\ + "o##########################################################o\n"); + return NULL; + } + + /*--------------------------------------------------------*\ + ! Extract the file extension from the input string and use ! + ! it to invoke the appropriate read function. ! + \*--------------------------------------------------------*/ + str = strrchr(temp->lit_opt[0], '.'); + switch(hash(str)) + { + case 0x000000017C4DC25C: + { + file = read_eas3(temp->lit_opt[0]); + if(file == NULL) + { + return NULL; + } + + return file; + } + + case 0x000000017C4DAF1D: + { + file = read_bwc(temp->lit_opt[0]); + if(file == NULL) + { + return NULL; + } + + return file; + } + + default: + { + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: File |\n"\ + "| |\n"\ + "| The format of the specified file is currently |\n"\ + "| not supported. |\n"\ + "| |\n"\ + "o##########################################################o\n"); + return NULL; + } + } +} + +/*--------------------------------------------------------------------------------------------------------------------*\ +! ! +! DESCRIPTION: ! +! ------------ ! +! This function is a wrapper that is used to invoke the appropriate write func- ! +! tion according to the file extension supplied by the user or codestream. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! args util_arg_node* - Arguments/options linked list ! +! for the bwc command-line tool. ! +! ! +! str char* - Long-/short-name of a bwc com- ! +! mand-line argument or option. ! +! ! +! data bwc_data* - Structure containing a code- ! +! stream/numerical dataset. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! unsigned char - Returns an unsigned char for ! +! error handling. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description ! +! ---- ------ --------- ------- ----------- ! +! 14.05.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! 17.05.2021 Patrick Vogler B87E7E4 V 0.1.0 clean up ! +! ! +\*--------------------------------------------------------------------------------------------------------------------*/ +static uchar +write_file(bwc_cmdl_arg_node *const args, + bwc_data *const data, + char* name) +{ + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + uint64_t ext_hash; + uint16_t new_len; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_cmdl_arg_node *temp; + + /*-----------------------*\ + ! DEFINE CHAR VARIABLES: ! + \*-----------------------*/ + char *str; + + /*-----------------------*\ + ! DEFINE ASSERTIONS: ! + \*-----------------------*/ + assert(data); + assert(args); + assert(name); + + /*--------------------------------------------------------*\ + ! Retrieve the file argument from the linked list and con- ! + ! firm that only one file has been specified. ! + \*--------------------------------------------------------*/ + temp = retrieve_arg(args, name); + if((temp == NULL) || + (temp->lit_opt == NULL) || + (temp->lit_opt[0] == NULL)) + { + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: File |\n"\ + "| |\n"\ + "| No File has been specified. |\n"\ + "| |\n"\ + "o##########################################################o\n"); + return EXIT_FAILURE; + } + + if(temp->count > 1) + { + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: File |\n"\ + "| |\n"\ + "| More than one file has been specified. |\n"\ + "| |\n"\ + "o##########################################################o\n"); + return EXIT_FAILURE; + } + + /*--------------------------------------------------------*\ + ! If the output is a packed codestream, replace the user ! + ! supplied with the propper '.bwc' file extension to en- ! + ! sure uniformity. ! + \*--------------------------------------------------------*/ + if((retrieve_arg(args, "compress") != NULL) && (data->codestream.data != NULL)) + { + /*--------------------------------------------------------*\ + ! Extract the filename in the output argument, remove its ! + ! file extension and calculate the new string length with ! + ! the '.bwc' extension. ! + \*--------------------------------------------------------*/ + str = strrchr(temp->lit_opt[0], '.'); + str[1] = '\0'; + + new_len = (strlen(temp->lit_opt[0]) + 4) * sizeof(char); + + /*--------------------------------------------------------*\ + ! Resize the filename string in the output argument and ! + ! ammend the new file extension. ! + \*--------------------------------------------------------*/ + str = calloc(new_len, sizeof(char)); + if(str == NULL) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return EXIT_FAILURE; + } + sprintf(str, "%s%s", temp->lit_opt[0],"bwc"); + + /*--------------------------------------------------------*\ + ! Write the codestream to the filesystem. ! + \*--------------------------------------------------------*/ + if(write_bwc(data, str) == EXIT_FAILURE) + { + free(str); + return EXIT_FAILURE; + } + } + /*--------------------------------------------------------*\ + ! If the output is a numerical dataset, generate the ap- ! + ! propriate filename and write the information to file. ! + \*--------------------------------------------------------*/ + else if((retrieve_arg(args, "decompress") != NULL) && ((data->field.d != NULL) || + (data->field.f != NULL))) + { + /*--------------------------------------------------------*\ + ! If no output file has been specified, assemble the file- ! + ! name using the input name and file extension assoc. with ! + ! the codestream. Generate the ext. hash accordingly. ! + \*--------------------------------------------------------*/ + if(strcmp(name, "decompress") == 0) + { + ext_hash = hash(data->info.f_ext); + str = strrchr(temp->lit_opt[0], '.'); + str[0] = '\0'; + + new_len = (strlen(temp->lit_opt[0]) + + strlen(data->info.f_ext) + 7) * sizeof(char); + + str = calloc(new_len, sizeof(char)); + if(str == NULL) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return EXIT_FAILURE; + } + sprintf(str, "%s%s%s", temp->lit_opt[0], "_d.", data->info.f_ext); + } + /*--------------------------------------------------------*\ + ! If an output file has been specified, extract the file ! + ! extension, evaluate the corresponding hash and check ! + ! that the codestream supports the file format. ! + \*--------------------------------------------------------*/ + else + { + ext_hash = hash(strrchr(temp->lit_opt[0], '.') + 1); + if(ext_hash != hash(data->info.f_ext)) + { + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: Incompatible File Format |\n"\ + "| |\n"\ + "| The format of the specified file is incom- |\n"\ + "| patible with the information stored in the |\n"\ + "| codestream. |\n"\ + "| |\n"\ + "o##########################################################o\n"); + return EXIT_FAILURE; + } + + str = calloc(strlen(temp->lit_opt[0]) + 1, sizeof(char)); + if(str == NULL) + { + // memory allocation error + fprintf(stderr, MEMERROR); + return EXIT_FAILURE; + } + strcpy(str, temp->lit_opt[0]); + } + + /*--------------------------------------------------------*\ + ! Use the extension hash to invoke the appropriate write ! + ! function. ! + \*--------------------------------------------------------*/ + switch (ext_hash) + { + case 0X0000000000B87A592: + { + if(write_eas3(data, str) == EXIT_FAILURE) + { + free(str); + return EXIT_FAILURE; + } + break; + } + + default: + { + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: File |\n"\ + "| |\n"\ + "| The format of the specified file is currently |\n"\ + "| not supported. |\n"\ + "| |\n"\ + "o##########################################################o\n"); + free(str); + return EXIT_FAILURE; + } + } + } + /*--------------------------------------------------------*\ + ! If no apporprite in- or output argument has been speci- ! + ! fied return an error handle to the function caller. ! + \*--------------------------------------------------------*/ + else + { + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: Data |\n"\ + "| |\n"\ + "| Output can not be generated because no valid |\n"\ + "| data has been specified. |\n"\ + "| |\n"\ + "o##########################################################o\n"); + return EXIT_FAILURE; + } + + free(str); + return EXIT_SUCCESS; +} + +/*--------------------------------------------------------------------------------------------------------------------*\ +! ! +! DESCRIPTION: ! +! ------------ ! +! | | ! +! This function calculates the Peak-Signal-to-Noise-Ratio of a compressed file ! +! in relation to the original reference file. The mean square error and peak ! +! signal to noise ratio are written to the standard output. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! args util_arg_node* - Arguments/options linked list ! +! for the bwc command-line tool. ! +! ! +! name char* - Long-/short-name of a bwc com- ! +! mand-line argument or option. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! unsigned char - Returns an unsigned char for ! +! error handling. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description ! +! ---- ------ --------- ------- ----------- ! +! 12.09.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! 17.05.2021 Patrick Vogler B87E7E4 V 0.1.0 clean up ! +! ! +\*--------------------------------------------------------------------------------------------------------------------*/ +static uchar +output_analysis(bwc_cmdl_arg_node *const args) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64_t size; + uint64_t i; + + uint8_t p; + + /*-----------------------*\ + ! DEFINE FLOAT VARIABLES: ! + \*-----------------------*/ + double MSE, PSNR; + double peakVal; + double sum; + + double *dOrig, *dRef; + float *fOrig, *fRef; + + bwc_float minVal, maxVal; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_data *file, *ref; + + bwc_cmd_opts_ll *param; + + /*--------------------------------------------------------*\ + ! Load the input and reference files into the appropriate ! + ! file structures. ! + \*--------------------------------------------------------*/ + file = read_file(args, "input"); + if(file == NULL) + { + return EXIT_FAILURE; + } + + ref = read_file(args, "reference"); + if(ref == NULL) + { + bwc_free_data(file); + return EXIT_FAILURE; + } + + dOrig = file->field.d; + dRef = ref->field.d; + + fOrig = file->field.f; + fRef = ref->field.f; + + if(file->info.nX == ref->info.nX && + file->info.nY == ref->info.nY && + file->info.nZ == ref->info.nZ && + file->info.nTS == ref->info.nTS && + file->info.nPar == ref->info.nPar) + { + size = (uint64_t)ref->info.nX * ref->info.nY * + ref->info.nZ * ref->info.nTS; + + peakVal = -1.7976931348623157e+308; + PSNR = + MSE = 0; + + if(ref->info.parameter) + { + param = ref->info.parameter->root; + p = 0; + while(param != NULL) + { + minVal = 1.7976931348623157e+308; + maxVal = -1.7976931348623157e+308; + + if(param->precision == 8) + { + for(i = 0; i < size; ++i) + { + minVal = MIN(minVal, (double)dRef[i + p * size]); + maxVal = MAX(maxVal, (double)dRef[i + p * size]); + + sum = ((double)dRef[i + p * size] - (double)dOrig[i + p * size]); + + MSE += sum * sum; + } + } + else if(param->precision == 4) + { + for(i = 0; i < size; ++i) + { + minVal = MIN(minVal, (double)fRef[i + p * size]); + maxVal = MAX(maxVal, (double)fRef[i + p * size]); + + sum = ((double)fRef[i + p * size] - (double)fOrig[i + p * size]); + + MSE += sum * sum; + } + } + peakVal = MAX(peakVal, maxVal - minVal); + param = param -> next; + p++; + } + } + + MSE /= (double)size * ref->info.nPar; + PSNR = 20 * log10(peakVal/(2 * sqrt(MSE))); + + printf("==============================================================\n"); + printf(" Mean Square Error: %*.2f\n", 22, MSE); + printf(" Peak Signal-to-Noise Ratio: %*.2f\n", 22, PSNR); + printf("==============================================================\n"); + + } + /*--------------------------------------------------------*\ + ! Load the input and reference files into the appropriate ! + ! file structures. ! + \*--------------------------------------------------------*/ + bwc_free_data(file); + bwc_free_data(ref); + + return EXIT_SUCCESS; +} + +/**********************************************************************************************************************\ +|| ___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || +|| |__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ || +|| | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] || +|| || +\**********************************************************************************************************************/ +/*--------------------------------------------------------------------------------------------------------------------*\ +! ! +! DESCRIPTION: ! +! ------------ ! +! This function provides a command-line interface for the BigWhoop compression ! +! library. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! argc int - Number of strings pointed to ! +! by argv. ! +! ! +! argv char** - Array of arguments. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! int - Return value signaling a normal ! +! or abnormal process exit. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description ! +! ---- ------ --------- ------- ----------- ! +! 17.04.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! 15.05.2021 Patrick Vogler B880CA2 V 0.1.0 Clean up. ! +! ! +\*--------------------------------------------------------------------------------------------------------------------*/ +int +main(int argc, + char *argv[]) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64_t size=0; + uint64_t i; + uint8_t error_handle; + + /*-----------------------*\ + ! DEFINE CHAR VARIABLES: ! + \*-----------------------*/ + char *csSize = NULL; + char *fdSize = NULL; + char buff[200]; + char rate[10]; + + /*-----------------------*\ + ! DEFINE FLOAT VARIABLES: ! + \*-----------------------*/ + double comp_ratio; + double bpd; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_field *field = NULL; + bwc_data *file = NULL; + + bwc_gl_ctrl *control; + + bwc_dwt_filter filter[4]; + bwc_cmdl_arg_node *args, *temp; + + bwc_cmd_opts_ll *param; + + /*--------------------------------------------------------*\ + ! Initialize the field and args structures for proper er- ! + ! ror handling, as well as the error handle itself. ! + \*--------------------------------------------------------*/ + field = NULL; + args = NULL; + + error_handle = EXIT_SUCCESS; + + /*--------------------------------------------------------*\ + ! Assemble the arg. linked list using the command-line ar- ! + ! guments passed by the function caller. ! + \*--------------------------------------------------------*/ + args = parse_arguments(argc, argv); + if(args == NULL) + { + error_handle = EXIT_FAILURE; + print_help(); + goto OUT; + } + + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + if(retrieve_arg(args, "compress") != NULL) + { + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + if(retrieve_arg(args, "input")) + file = read_file(args, "input"); + else + file = read_file(args, "compress"); + + if(file == NULL) + { + error_handle = EXIT_FAILURE; + goto OUT; + } + + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + /*--------------------------------------------------------*\ + ! Save frequently used variables/structures to temporary ! + ! variables to make the code more readable. ! + \*--------------------------------------------------------*/ + field = bwc_initialize_field(file); + if(field == NULL) + { + error_handle = EXIT_FAILURE; + goto OUT; + } + control = &field->control; + + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + temp = retrieve_arg(args, "q_format_range"); + if((temp != NULL) && (temp->count == 1)) + { + bwc_set_qm(field, (uint8_t)temp->num_opt[0]); + } + + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + temp = retrieve_arg(args, "wavelet_kernels"); + if((temp != NULL) && (temp->count == 4) && (temp->dim != 0x00)) + { + for(i = 0; i < temp->count; ++i) + { + switch(hash(temp->lit_opt[i])) + { + case 0x000000000B87CF64: + { + filter[i] = bwc_dwt_9_7; + break; + } + case 0x00000652AB15772A: + { + filter[i] = bwc_dwt_5_3; + break; + } + case 0x000000017C858EFF: + { + filter[i] = bwc_dwt_5_3; + break; + } + default: + { + filter[i] = bwc_dwt_9_7; + break; + } + } + } + bwc_set_kernels(field, filter[0], filter[1], + filter[2], filter[3]); + } + + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + temp = retrieve_arg(args, "decomposition_levels"); + if((temp != NULL) && (temp->count == 4) && (temp->dim != 0x00)) + { + bwc_set_decomp(field, (uint8_t)temp->num_opt[0], (uint8_t)temp->num_opt[1], + (uint8_t)temp->num_opt[2], (uint8_t)temp->num_opt[3]); + } + + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + temp = retrieve_arg(args, "tile_size"); + if((temp != NULL) && (temp->count == 4) && (temp->dim != 0x00)) + { + bwc_set_tiles(field, (uint64_t)temp->num_opt[0], (uint64_t)temp->num_opt[1], + (uint64_t)temp->num_opt[2], (uint64_t)temp->num_opt[3], bwc_tile_sizeof); + } + + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + temp = retrieve_arg(args, "precinct_size"); + if((temp != NULL) && (temp->count == 4) && (temp->dim != 0x00)) + { + bwc_set_precincts(field, (uint8_t)temp->num_opt[0], (uint8_t)temp->num_opt[1], + (uint8_t)temp->num_opt[2], (uint8_t)temp->num_opt[3]); + } + + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + temp = retrieve_arg(args, "codeblock_size"); + if((temp != NULL) && (temp->count == 4) && (temp->dim != 0x00)) + { + bwc_set_codeblocks(field, (uint8_t)temp->num_opt[0], (uint8_t)temp->num_opt[1], + (uint8_t)temp->num_opt[2], (uint8_t)temp->num_opt[3]); + } + + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + temp = retrieve_arg(args, "quantisation_style"); + if((temp != NULL) && (temp->count == 1)) + { + if(strcmp(temp->lit_opt[0], "NONE")) + bwc_set_quant_style(field, bwc_qt_none); + else + bwc_set_quant_style(field, bwc_qt_derived); + } + + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + temp = retrieve_arg(args, "quantisation_step_size"); + if((temp != NULL) && (temp->count == 1)) + { + bwc_set_quant_step_size(field, temp->num_opt[0]); + } + + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + memset(buff, 0, 200 * sizeof(char)); + + temp = retrieve_arg(args, "bitrate"); + if((temp != NULL) && (temp->count > 0)) + { + for(i = 0; i < temp->count && strlen(buff) < 192; ++i) + { + sprintf(rate, "%05.3f,", temp->num_opt[i]); + strcat(buff, rate); + } + buff[strlen(buff) - 1] = '0'; + } + + temp = retrieve_arg(args, "compression_ratio"); + if((temp != NULL) && (temp->count == 1)) + { + sprintf(buff, "%05.3f", ((double)PREC_BIT + 1.0f)/temp->num_opt[0]); + } + + if(strlen(buff) == 0) + { + sprintf(buff, "-"); + } + + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + #if defined (_OPENMP) + temp = retrieve_arg(args, "number_of_threads"); + if((temp != NULL) && (temp->count == 1)) + { + omp_set_num_threads((uint8_t)temp->num_opt[0]); + } + #endif + + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + if(retrieve_arg(args, "error_resilience")) + { + bwc_set_error_resilience(field); + } + + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + if(bwc_create_compression(field, buff)) + { + error_handle = EXIT_FAILURE; + goto OUT; + } + + if(bwc_compress(field, file)) + { + error_handle = EXIT_FAILURE; + goto OUT; + } + + + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + if(retrieve_arg(args, "output")) + { + if(write_file(args, file, "output")) + { + error_handle = EXIT_FAILURE; + goto OUT; + } + } + else + { + if(write_file(args, file, "compress")) + { + error_handle = EXIT_FAILURE; + goto OUT; + } + } + temp = retrieve_arg(args, "verbose"); + if(temp != NULL) + { + /*--------------------------------------------------------*\ + ! Calculate the original field size, compression ratio and ! + ! bits per datapoint and print the miscellaneous compres- ! + ! sion information to the standard output. ! + \*--------------------------------------------------------*/ + if((temp->count == 1) && (temp->num_opt[0] > 1) && (control->CSsgc != 0)) + { + printf("==============================================================\n"); + printf(" \n"\ + " .:-------------: .:-------------: \n"\ + " .+++++++++++++++= :+++++++++++++++- \n"\ + " :+++. -++= -++= \n"\ + " :+++. -++= -++= \n"\ + " -++++++++++++++= -++= -++= \n"\ + " .=++---------=++= -++= -++= \n"\ + " :+++ :++= -++= -++= \n"\ + " .+++=--------=+++---=+++---=+++------------: \n"\ + " -=++++++++++++++++++++++++++++++++++++++++- \n"\ + " \n"); + printf("----------------- Compression Parameters -----------------\n\n"); + if((control->CSsgc &0x200) != 0) + { + printf(" Number of Tiles: %27d\n", control->nTiles); + printf(" - Samples in 1.D: %27ld\n", control->tileSizeX); + printf(" - Samples in 2.D: %27ld\n", control->tileSizeY); + printf(" - Samples in 3.D: %27ld\n", control->tileSizeZ); + printf(" - Timesteps: %27d\n", control->tileSizeTS); + printf(" ..........................................................\n"); + printf("\n"); + } + + if((control->CSsgc &0xE0) != 0) + { + printf(" 1.D | 2.D | 3.D | TS\n"); + if((control->CSsgc &0x20) != 0) + { + printf(" Decomposition Levels: %2d | %2d | %2d | %2d\n", control->decompX + , control->decompY + , control->decompZ + , control->decompTS); + } + if((control->CSsgc &0x40) != 0) + { + printf(" Precincts [log2]: %2d | %2d | %2d | %2d\n", control->precSizeX + , control->precSizeY + , control->precSizeZ + , control->precSizeTS); + + } + if((control->CSsgc &0x80) != 0) + { + printf(" Codeblocks [log2]: %2d | %2d | %2d | %2d\n", control->cbX + , control->cbY + , control->cbZ + , control->cbTS); + } + printf(" ..........................................................\n"); + printf("\n"); + } + + if((control->CSsgc &0x101) != 0) + { + if((control->CSsgc &0x100) != 0) + printf(" Q Number Format: %27d\n", control->Qm); + if((control->CSsgc &0x1) != 0) + printf(" Error Resilience: %27s\n", ((control->error_resilience > 0) ? "True" : "False")); + + printf(" ..........................................................\n"); + printf("\n"); + } + + for(i = 0; i < control->nLayers; ++i) + { + printf(" Quality Layer Nr. %2ld: %23.2f bpd\n", i + 1, control->bitrate[i]/8.0f); + } + + printf("\n"); + printf("---------------- Compression Performance -----------------\n\n"); + } + else + { + printf("==============================================================\n"); + } + + /*--------------------------------------------------------*\ + ! Calculate the original field size, compression ratio and ! + ! bits per datapoint and print the miscellaneous compres- ! + ! sion information to the standard output. ! + \*--------------------------------------------------------*/ + if(file->info.parameter) + { + param = file->info.parameter->root; + + while(param != NULL) + { + size += (param->size * param->precision); + param = param -> next; + } + } + + comp_ratio = (double)size/(file->codestream.data->size); + bpd = (double)(file->codestream.data->size * 64)/size; + + /*--------------------------------------------------------*\ + ! Calculate the original field size, compression ratio and ! + ! bits per datapoint and print the miscellaneous compres- ! + ! sion information to the standard output. ! + \*--------------------------------------------------------*/ + csSize = get_size(file->codestream.data->size); + fdSize = get_size(size); + + /*--------------------------------------------------------*\ + ! Calculate the original field size, compression ratio and ! + ! bits per datapoint and print the miscellaneous compres- ! + ! sion information to the standard output. ! + \*--------------------------------------------------------*/ + printf(" Compression Time: %*.2f s\n", 25, field->meter.time.ttl); + printf(" - Wavelet transformation: %*.2f s\n", 25, field->meter.time.wav); + printf(" - Entropy encoding: %*.2f s\n", 25, field->meter.time.ent); + printf(" - Codestream assembly: %*.2f s\n", 25, field->meter.time.ass); + printf("\n"); + printf(" Compression Ratio: %*.2f\n", 27, comp_ratio); + printf(" - Codestream size: %*s\n", 25, csSize); + printf(" - Field size: %*s\n", 25, fdSize); + printf(" - Average bpd: %*.2f\n", 27, bpd); + printf("==============================================================\n"); + + /*--------------------------------------------------------*\ + ! Calculate the original field size, compression ratio and ! + ! bits per datapoint and print the miscellaneous compres- ! + ! sion information to the standard output. ! + \*--------------------------------------------------------*/ + free(csSize); + free(fdSize); + } + } + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + else if(retrieve_arg(args, "decompress") != NULL) + { + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + if(retrieve_arg(args, "input")) + file = read_file(args, "input"); + else + file = read_file(args, "decompress"); + + if(file == NULL) + { + error_handle = EXIT_FAILURE; + goto OUT; + } + + if(file->codestream.data == NULL) + { + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: File |\n"\ + "| |\n"\ + "| Input file does not contain a packed code- |\n"\ + "| stream. |\n"\ + "| |\n"\ + "o##########################################################o\n"); + + error_handle = EXIT_FAILURE; + goto OUT; + } + + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + temp = retrieve_arg(args, "layer"); + if((temp != NULL) && (temp->count == 1)) + field = bwc_create_decompression(file, (uint8_t)temp->num_opt[0]); + else + field = bwc_create_decompression(file, 0); + + if(field == NULL) + { + error_handle = EXIT_FAILURE; + goto OUT; + } + + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + #if defined (_OPENMP) + temp = retrieve_arg(args, "number_of_threads"); + if((temp != NULL) && (temp->count == 1)) + { + omp_set_num_threads((uint8_t)temp->num_opt[0]); + } + #endif + + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + if(bwc_decompress(field, file)) + { + error_handle = EXIT_FAILURE; + goto OUT; + } + + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + if(retrieve_arg(args, "output")) + { + if(write_file(args, file, "output")) + { + error_handle = EXIT_FAILURE; + goto OUT; + } + } + else + { + if(write_file(args, file, "decompress")) + { + error_handle = EXIT_FAILURE; + goto OUT; + } + } + + /*--------------------------------------------------------*\ + ! If the verbose flag is set by the function caller, print ! + ! the miscellaneous decompression information to the stan- ! + ! dard output. ! + \*--------------------------------------------------------*/ + temp = retrieve_arg(args, "verbose"); + if(temp != NULL) + { + printf("==============================================================\n"); + printf(" Decompression Time: %*.2f s\n", 24, field->meter.time.ttl); + printf(" - Wavelet transformation: %*.2f s\n", 24, field->meter.time.wav); + printf(" - Entropy encoding: %*.2f s\n", 24, field->meter.time.ent); + printf("==============================================================\n"); + } + } + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + else if(retrieve_arg(args, "info") != NULL) + { + if(retrieve_arg(args, "input")) + output_info(args, "input"); + else + output_info(args, "info"); + } + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + else if(retrieve_arg(args, "analysis") != NULL) + { + if(output_analysis(args) == EXIT_FAILURE) + { + error_handle = EXIT_FAILURE; + goto OUT; + } + } + /*--------------------------------------------------------*\ + ! ! + \*--------------------------------------------------------*/ + else + { + print_help(); + goto OUT; + } + +OUT: + if(field != NULL) + { + bwc_kill_compression(field); + } + + if(file != NULL) + { + bwc_free_data(file); + } + + if(args != NULL) + { + bwc_kill_arg(args); + } + + fclose(stdin); + fclose(stdout); + fclose(stderr); + + return error_handle; +} \ No newline at end of file diff --git a/1-bwc/src/tools/get_hash.c b/1-bwc/src/tools/get_hash.c new file mode 100755 index 0000000..360023a --- /dev/null +++ b/1-bwc/src/tools/get_hash.c @@ -0,0 +1,154 @@ +/*==================================================================================================================================*\ +|| || +|| /$$$$$$$ /$$ /$$ /$$ /$$ || +|| | $$__ $$|__/ | $$ /$ | $$| $$ || +|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || +|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || +|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || +|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || +|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || +|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || +|| /$$ \ $$ | $$ || +|| | $$$$$$/ | $$ || +|| \______/ |__/ || +|| || +|| FILE NAME: get_hash.c || +|| || +|| || +|| DESCRIPTION: || +|| ------------ || +|| This is a simple command line tool that converts the command-line arguments to a uniquely identifiable || +|| hash. || +|| || +|| || +|| PUBLIC FUNCTIONS: || +|| ----------------- || +|| - main || +|| || +|| DEVELOPMENT HISTORY: || +|| -------------------- || +|| || +|| Date Author Change Id Release Description Of Change || +|| ---- ------ --------- ------- --------------------- || +|| 02.05.2019 Patrick Vogler B87D120 V 0.1.0 module created || +|| || +|| -------------------------------------------------------------------------------------------------------------------- || +|| || +|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || +|| || +|| Redistribution and use in source and binary forms, with or without modification, are permitted provided that the || +|| following conditions are met: || +|| || +|| (1) Redistributions of source code must retain the above copyright notice, this list of conditions and || +|| the following disclaimer. || +|| || +|| (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions || +|| and the following disclaimer in the documentation and/or other materials provided with the || +|| distribution. || +|| || +|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, || +|| INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE || +|| DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, || +|| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR || +|| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, || +|| WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE || +|| USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || +|| || +\*==================================================================================================================================*/ + +/************************************************************************************************************\ +|| _ _ _ ____ _ _ _ ___ ____ || +|| | |\ | | | | | | \ |___ || +|| | | \| |___ |___ |__| |__/ |___ || +|| || +\************************************************************************************************************/ +#include +#include +#include +#include +#include + + +/*----------------------------------------------------------------------------------------------------------*\ +! FUNCTION NAME: int main(int argc, char* argv[]) ! +! -------------- ! +! ! +! DESCRIPTION: ! +! ------------ ! +! ! +! This function uses a variant of the DJB hash function to turn the command-line argument ! +! strings and converts them to a uniquely identifiable hash. The hashes are written to the ! +! command-line in a hexadecimal format. ! +! ! +! PARAMETERS: ! +! ----------- ! +! Variable Type Description ! +! -------- ---- ----------- ! +! argc int - Number of strings pointed to by argv. ! +! ! +! argv char** - Array of arguments. ! +! ! +! RETURN VALUE: ! +! ------------- ! +! Type Description ! +! ---- ----------- ! +! int - Return value signaling a normal or abnormal process exit. ! +! ! +! DEVELOPMENT HISTORY: ! +! -------------------- ! +! ! +! Date Author Change Id Release Description Of Change ! +! ---- ------ --------- ------- --------------------- ! +! 02.05.2019 Patrick Vogler B87D120 V 0.1.0 function created ! +! ! +\*----------------------------------------------------------------------------------------------------------*/ +int main(int argc, char* argv[]) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64_t hash; + uint8_t c, i; + + /*-----------------------*\ + ! DEFINE CHAR VARIABLES: ! + \*-----------------------*/ + char* str; + + /*--------------------------------------------------------*\ + ! Loop through all additional command-line arguments. ! + \*--------------------------------------------------------*/ + for(i = 1, str = argv[1]; i < argc; ++i, str = argv[i]) + { + /*--------------------------------------------------------*\ + ! Initialize the hash with a magic number. ! + \*--------------------------------------------------------*/ + hash = 0x1505; + + /*--------------------------------------------------------*\ + ! Walk through all the characters in the string. ! + \*--------------------------------------------------------*/ + while ((c = *str++)) + { + /*--------------------------------------------------------*\ + ! Convert the current characters to uppercase. ! + \*--------------------------------------------------------*/ + if((c >= 97) && (c <= 122)) + { + c = c - 32; + } + + /*--------------------------------------------------------*\ + ! Multiply the hash with 33 and add the current character ! + ! to the hash. ! + \*--------------------------------------------------------*/ + hash = (hash * 33) ^ c; + } + + /*--------------------------------------------------------*\ + ! Write the hash to the command-line. ! + \*--------------------------------------------------------*/ + printf("%#020lX \n", hash); + } + return 0; +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..4053e31 --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ + +

Data Compression of numerical data sets with the BigWhoop library

+ +This repository contains all the resources needed to participate in the hands-on sessions of the lecture `Data Compression of numerical data sets with the BigWhoop library`. The repository is organized as follows. +- 0-docs lecture slides +- 1-bwc source code of the BigWhoop compression library +- 2-data Test data sets. + + +

Building BigWhoop

+ +### Dependencies + +* make +* cmake (>= 3.5.1) +* gcc (>= 8.5.0) + +### Building + +pull the sources from HLRS' gitea instance (note: default branch is `main`): +``` +git pull https://code.hlrs.de/hpcpvogl/BigWhoop.git +``` + +Now change into the source directory and run the following commands. + +**for a simple build** +``` +make clean +make +``` +**for a full build (including command line tool)** +``` +make full +``` +**for debugging** +``` +make clean +make debug +``` +This builds the library and places the associated files in the `/lib` or `/lib64` folders. If a full build was attempted, the command line tool binaries are placed in the `/bin` folder. \ No newline at end of file